Ticket #4748: 4748.patch

File 4748.patch, 3.4 kB (added by hakre, 10 months ago)

Security Hotfix for #4748 / admin privilege escalation

  • wp-includes/vars.php

    old new  
    1212        $pagenow = 'index.php'; 
    1313} 
    1414 
     15$pagenow = pagenow_hotfix($pagenow); 
     16 
     17/// {{{ 
     18/** 
     19 * pagenow_hotfix 
     20 * 
     21 * will return the filename of the current page 
     22 * after "On which page are we?" applying a hotfix to #4748 preventing 
     23 * to trick wordpress admin. 
     24 * 
     25 * this is a hotfix only and does not solve the underlying problems 
     26 * which created the defect. A deeper analysis is available. 
     27 * 
     28 * @see      #4748 
     29 * @affected 2.2.2 
     30 * @todo     define $PHP_SELF usage inside wordpress 
     31 * 
     32 * @param  string pagenow current pagenow value to let pass if needed 
     33 * 
     34 * @return string filename of the pagenow/currentage sanitized if within the admin 
     35 */ 
     36function pagenow_hotfix($pagenow) { 
     37        global $PHP_SELF; 
     38         
     39        /* get propper relative document root */ 
     40        $docroot_virt = get_option('home'); 
     41        $docroot_path = parse_url ($docroot_virt, PHP_URL_PATH); 
     42 
     43        // ensure that this value is properly slashed at the end, if not, escalate by wp_die 
     44        if (strlen($docroot_path > 0)) { 
     45                if (substr($docroot_path, -1) == '/') { 
     46                        // error: get_option('home') did not return an expected value 
     47                        wp_die('Request Error #4748-1.'); 
     48                } 
     49        } 
     50        // ensure slash - only one at the end. granted. 
     51        $docroot_path .= '/'; 
     52 
     53        /* check against $PHP_SELF */ 
     54        $self = $PHP_SELF; 
     55 
     56        if (strlen($self) < strlen($docroot_path)) { 
     57                // error: request can not mapped into the blogs document root by length 
     58                wp_die('Request Error #4748-2.'); 
     59        } 
     60 
     61        if (substr($self, 0, strlen($docroot_path)) != $docroot_path) { 
     62                // error: request can not mapped at least into the blogs document root 
     63                wp_die('Request Error #4748-3.'); 
     64        } 
     65 
     66        /* this is a hotfix, we do only care about wp-admin here. */     
     67        $admin_path = $docroot_path . 'wp-admin/'; 
     68         
     69        if (strlen($self) >= strlen($admin_path)) { 
     70                if (substr($self, 0, strlen($admin_path)) == $admin_path) { 
     71                        $self_file = substr($self, strlen($admin_path)); 
     72 
     73                        /* extract admin filename */ 
     74                        if (strlen($self_file) == 0) { 
     75                                // ok: requesting the index 
     76                                $pagenow = 'index.php'; 
     77                        } else { 
     78                                $p = strpos($self_file, '.php');                                 
     79                                if ($p === false) { 
     80                                        // error: can not parse request. taking this personally. you should as well. 
     81                                        //                if you encounter this error be advised to have a talk back  
     82                                        //                with core-devs about $PHP_SELF usage. write it down then. 
     83                                        wp_die('Request Error #4748-4.'); 
     84                                } 
     85                                // small blacklist 
     86                                if ($p == 0) { 
     87                                        // fault: there is no file "/.php" in wp-admin. 
     88                                        $pagenow = ''; 
     89                                } else { 
     90                                        // ok: getting the filename now. 
     91                                        $pagenow = substr($self_file, 0, $p + 4); 
     92                                } 
     93 
     94                        } 
     95 
     96                        // check for errors, $pagenow is empty in that case 
     97                        if ($pagenow == '') { 
     98                                wp_die('Request Error. Please contact the Administrator.'); 
     99                        } else { 
     100                                // $self                 as wordpress sees the request itself 
     101                                // $self_file    my pagenow for the admin including bogus stuff at the end but starting properly 
     102                                // $docroot_virt wordpress docroot by URL 
     103                                // $docroot_path my docroot, the relative one to the relative one (serverdocroot + this = this file directory)                           
     104                        } 
     105                } 
     106        } // end if (was: wp-admin) 
     107         
     108        return $pagenow; 
     109} 
     110/// }}} 
     111 
     112 
    15113// Simple browser detection 
    16114$is_lynx = $is_gecko = $is_winIE = $is_macIE = $is_opera = $is_NS4 = false; 
    17115