1. 程式人生 > >暑期練習web6:因缺思汀的繞過(實驗吧) 程式碼審計 with rollup

暑期練習web6:因缺思汀的繞過(實驗吧) 程式碼審計 with rollup

題目的hint:主要涉及程式碼審計和mysql方面
解題連結: http://ctf5.shiyanbar.com/web/pcat/index.php
拿到題目,好吧,這題我完全沒轍。。。,這裡寫圖片描述
檢視一下原始碼:
這裡結合了一下@GETF對原始碼的註釋,對程式碼進行了一定的解讀

<?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,值賦給變數$value AttackFilter($key,$value,$filter);//然後這裡呼叫了之前的那個函式,如果輸入了$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); //執行mysql語句 if (mysql_num_rows($query) == 1) { #該函式返回一個整數,表示記錄中有多少行資料 $key = mysql_fetch_array($query);//mysql_fetch_array() 的作用是:從結果集中取得一行作為關聯陣列,同時產生關聯和數字陣列 if($key['pwd'] == $_POST['pwd']) {//key鍵值對中和post鍵值對中鍵名為‘pwd’的鍵值如果相等則輸出flag print "CTF{XXXXXX}";//很明顯,這是我們需要的 }else{ print "亦可賽艇!"; } }else{ print "一顆賽艇!";//payload只能輸入一行 } mysql_close($con);

這裡我們得知的是:

  1. 我們需要輸入一個和資料庫裡相同的uname
  2. 不能包括被過濾的那些關鍵詞
  3. 且要求為一行

首先想規範行數的話我們需要了解一下limit offset

① select * from table limit 2,1;

//含義是跳過2條取出1條資料,limit後面是從第2條開始讀,讀取1條資訊,即讀取第3條資料

② select * from table limit 2 offset 1;

//含義是從第1條(不包括)資料開始取出2條資料,limit後面跟的是2條資料,offset後面是從第1條開始讀取,即讀取第2,3條

注意它的查詢語句是 select * from interest where uname = ‘{$_POST[‘uname’]}’於是構造:

1’ or 1=1 limit 1 offset 0#

1’ or 1=1 limit 1 offset 1#

1’ or 1=1 limit 1 offset 2#

我們從第一條資訊開始讀、每次只讀一條資料,直到2#時返回“一顆賽艇!” 其他都是“亦可賽艇!”———–說明資料庫只有兩條資訊
然後利用group by語句可以一行輸出
現在再要解決兩個‘pwd’相等的問題,比較常見的想法那就是令他們都為NULL,因為我們輸入的pwd為空就行了,而在group up 語句的最後加上with rollup 會統計所有結果並返回一個NULL值具體用法可以看這個MySQL中with rollup的用法
而我們知道不存在第三條資料,所以我們還是從第三條開始查,及limit 1 offset 2,最後的#註釋後面的單引號’

所以最後我們的payload就是:1’ or 1=1 group by pwd with rollup limit 1 offset 2#
password不輸入東西,flag就出來了
這裡寫圖片描述
總結:這題程式碼擺的明明白白的,也是考程式碼審計,需要我們理解它的三重過濾,並分別做出不同的應對,思路清晰一點這個題應該還算比較好做(雖然我沒做出來555)