| php import_request_variables exploit example | [December 31, 2009 | 5:41 PM] |
|---|
I previously ran across some code that used import_request_variables to set all post, get and cookie parameters to global variable. This saved time since you would not need to explicitly call:
1 2 3 |
if(isset($_GET['some_param']) and $_GET['some_param']){
$some_var = $_GET['some_param'];
}
|
It was called using:
1 |
import_request_variables('GPC','_') ;
|
This code was called on every page of the site. The first parameter ‘GPC’ tells import_request_variables to import get, post and cookie parameters. The second parameter ‘_’ tells import_request_variables to add a underscore to the variable name. For example, passing $_GET[‘foo’] will create a variable called $_foo. If the second parameter is passed, there will be a E_NOTICE warning since this would allow any user to create or modify any variable. In this code, the underscore was provided as a prefix but this does not mean we are in the clear security wise. Before I show the example, lets draw up some example code for index.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
<?
#the following code is example code
#and should not be used as an example
#of the "right" way of doing things.
#There may even be syntax errors.
#starts the session, connects to db,
#and calls import_request_variables
function begin(){
session_start();
mysql_connect('localhost',
'mysql_user',
'mysql_password');
import_request_variables('GPC', '_');
}
#checks username and password with db
#and sets $_SESSION['user_id'] if they authenticate successfully.
function login($username, $password){
$username = mysql_real_escape_string($username);
$password = mysql_real_escape_string($password);
#as stated above, this code is only an example,
#for a real site you would want a hash/salt, not plaintext
#password.
$query = "SELECT * FROM users WHERE username =
'$username' and password = '$password' LIMIT 1";
$result = mysql_query($query);
$user = mysql_fetch_assoc($result);
if($user){
$_SESSION['user_id'] = $user['user_id'];
}
}
#destroys session
function logout(){
session_destroy();
}
#will return true if $_SESSION['user_id'] is set and belongs to a user
function isLoggedIn(){
if(isset($_SESSION['user_id'])){
$user_id = $_SESSION['user_id'];
$query = "SELECT * FROM users WHERE user_id = '$user_id' LIMIT 1";
$result = mysql_query($query);
$user = mysql_fetch_assoc($query);
if($user){
return true;
}else{
return false;
}
}else{
return false;
}
}
begin();
#note that variables starting with
#$_ where set above with import_request_variables
if(isset($_logout)){
logout();
}
if(isset($_username) && isset($_password)){
login($_username, $_password);
}
if(isLoggedIn()){
?>
You are an authorized user! <a href='index.php?logout=true'>Logout</a>.
<?
}else{
?>
You are not authorized, use the form below to log in.
<form action='index.php'>
Username: <input type='text' name='username' /><br />
Password: <input type='password' name='password' />
</form>
<?
}
?>
|
This is a simple page which will tell you if you are authorized, or give the login form if not. If the user successfully logs in, the $_SESSION[‘user_id’] is set. $_username and $_password are set by import_request_variables if the username and password get, post or cookie variables are set. Now on to the attack. Any variable starting with $_ can be set by passing a get, post or cookie with the appropriate parameters. If a user sent the request http://www.example.com/?SESSION[user_id]=1 would overwrite the $_SESSION[‘user_id’] variable to 1. Since database ids are often sequential, it would not be that hard to use a script to run through each number and find ids that belong to users. It would essentially allow a hacker to log in as any user. Make sure if using the import_request_variables function, make sure to choose a prefix that will not be used by any other variables.