最近 ~下班去反恐~ 下班去精進自我的時候,偶而看到 SQLi 相關的題目。因為比較熟理論和 Code Review 而不太有機會實際操作的關係,故都會花比較多時間處理。
這裏是一題初階的 SQLi CTF 題。
query : select user from chal where user='' and pw=''
<?php
include "./config.php";
include "./flag.php";
error_reporting(0);
$black_list = "/admin|guest|limit|by|substr|mid|like|or|char|union|select|greatest|%00|\'|";
$black_list .= "=|_| |in|<|>|-|chal|_|\.|\(\)|#|and|if|database|where|concat|insert|having|sleep/i";
if(preg_match($black_list, $_GET['user'])) exit(":P");
if(preg_match($black_list, $_GET['pw'])) exit(":P");
$query="select user from chal where user='$_GET[user]' and pw='$_GET[pw]'";
$result = mysql_query($query);
$result = mysql_fetch_array($result);
$admin_pass = mysql_fetch_array(mysql_query("select pw from chal where user='admin'"));
echo "<h1>query : <strong><b>{$query}</b></strong><br></h1>";
if($result['user']) echo "<h2>Welcome {$result['user']}</h2>";
if(($admin_pass['pw'])&&($admin_pass['pw'] === $_GET['pw'])){
echo $flag;
}
highlight_file(__FILE__);
?>
根據源碼最上面的提示,這看起來就是 SQLi。不過因為這東西沒辦法搞反射 SQLi (即是把結果顯示在頁面上),所以我們只能做盲注。
盲注就相當於矇眼下旗,但差在你可以用 case + sleep 或 case + benchmark() 之後計算花費時間來判斷結果是 0/1。
不過這題可以試著爆破就是了。
這題的問題是黑單了很多關鍵字,不能用 sleep 盲注,也不能下 where,總之很多東西都不行。
首先我們需要處理 user=''
的單引號。因為不能下單引號,所以沒辦法跳脫。
不過我們可以下 user='\'
來跳脫第二個單引號。
所以 user=''
-> user='\'
,第二個單引號會被當做真的單引號來處理,而不是拿來標註字串的開始和結束。整句會變成:
select user from chal where user='' and pw='
'
另外一個問題是,我們沒辦法用分號、井號或 --
截斷 pw
後面的 query。但我們是可以下 \x00 (ascii NULL) 來截斷的。(這個用法在 PHP 5.x 也可以用)。
總之,query 會變成:
select user from chal where user='\' and pw=' (我們要注入的 sql); \x00
基本上我們就可以透過這種方式,去繞過黑單機制,並暴力破解其 pw
。
BSides Delhi CTF 2018 - Old School SQL - こんとろーるしーこんとろーるぶい