12.因缺思汀的繞過

分析:
先檢視頁面源代碼,收集資訊:
看來這又是一道代碼審計:
<?php
error_reporting(0);
if (!isset($_POST['uname']) || !isset($_POST['pwd'])) {
echo '<form action="" method="post">'."<br/>";
echo '<input name="uname" type="text"/>'."<br/>";
echo '<input name="pwd" type="text"/>'."<br/>";
echo '<input type="submit" />'."<br/>";
echo '</form>'."<br/>";
echo '<!--source: source.txt-->'."<br/>";
die;
}
function AttackFilter($StrKey,$StrValue,$ArrReq){
if (is_array($StrValue)){#判斷是否為數組
$StrValue=implode($StrValue);#如果是數組,則連接配接成字元串
}
if (preg_match("/".$ArrReq."/is",$StrValue)==1){
#隻要比對到就是exciting!/比對到一次就停/比對方式就是正則
print "水可載舟,亦可賽艇!";
exit();
}
}
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)";
foreach($_POST as $key=>$value){
#foreach 可以周遊數組與對象,它會把目前單元的鍵名也會在每次循環中被賦給變量 $key,
#值賦給變量$val,
AttackFilter($key,$value,$filter);
}
$con = mysql_connect("XXXXXX","XXXXXX","XXXXXX");
if (!$con){
die('Could not connect: ' . mysql_error());
}
$db="XXXXXX";
mysql_select_db($db, $con);
$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'";
$query = mysql_query($sql); #執行語句
if (mysql_num_rows($query) == 1) { #該函數傳回一個整數,表示記錄中有多少行資料
$key = mysql_fetch_array($query);
#mysql_fetch_array() 函數從結果集中取得一行作為關聯數組,第二個參數,(MYSQL_BOTH - 預設)。
#同時産生關聯和數字數組
if($key['pwd'] == $_POST['pwd']) {
print "CTF{XXXXXX}";#很明顯,這是重點
}else{
print "亦可賽艇!";
}
}else{
print "一顆賽艇!";
}
mysql_close($con);
?>
總結:
這裡有三層限制,繞過這三層限制就可以得到flag
0X00
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)";
在第一層的filter裡面就過濾了常用的SQL關鍵詞,是以正常的SQL 注入就不行了。如果輸入了filter裡面的語句,網頁傳回“水可載舟,亦可賽艇!”
0X01
if (mysql_num_rows($query) == 1) {
//傳回結果集中行的數目
$key = mysql_fetch_array($query);
第二層是限制從資料庫傳回的資料必須是一行,在滿足第一層條件的情況下可以使用 limit 的傳回來确定資料庫中總共有幾行資料。
注意它的查詢語句是 $sql = select * from interest where uname = ‘{$_POST[‘uname’]}’于是構造:
1' or 1 limit 1 offset 0#
1' or 1 limit 1 offset 1#
1' or 1 limit 1 offset 2#
發現2#時傳回“一顆賽艇!” 其他都是“亦可賽艇!”———–說明資料庫隻有兩條資訊
舉例解析:
1' or 1 含義如下:
Group by with rollup 會在最後多計算一個總數(更多參考:https://blog.csdn.net/qq_42254088/article/details/81904819)
注:with rollup 與group by一起使用,可以獲得額外的行,提供了更高一層的求和結果。group by 子句:代表分組
0X02
$key['pwd'] == $_POST['pwd']
接下來想辦法繞過第三層,這裡是個if判斷,隻要為true 就可以過,于是可以利用group by with rollup來繞過,用with rollup 來獲得NULL值,然後在pwd裡不寫值,if就為true了。
構造: 1' or 1 group by pwd with rollup limit 1 offset 2#
(注:這裡為什麼用2是因為,在前面的測試中我們知道interest表有兩行資料,那麼利用1' or 1 group by pwd with rollup 又得到了一個pwd為null的額外的行,隻要我們密碼為空,即可查詢成功, null==空字元串 為true)