WordPress.org

Make WordPress Core

Ticket #4748: 4748.patch

File 4748.patch, 3.4 KB (added by hakre, 13 years ago)

Security Hotfix for #4748 / admin privilege escalation

  • wp-includes/vars.php

     
    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