最近接觸到了xctf的OJ后,不得不感慨,有牌面就是不一樣。整個界面做的賞心悅目,而且題目也更接近滲透過程(也許吧)。
新手區很快ak暫且不表,這里就不間斷更新一下高手進階區的題目吧。
鏈接:https://adworld.xctf.org.cn/task/task_list?type=web&number=3&grade=1
ics-06
不得不說這道題就是個坑。首先進去看到是個常見的管理系統的平臺前端,當然頁面上各種xx中心的button都是假的,果斷先試試admin.php嘗試找后臺,無果。于是轉而輸入index.php,發現到了一個表單頁面。
這不就很清楚了嘛,id都在 url里面,當然是,當然是。。。。。。注入了!于是就陷入了id可以注入的誤區。然而,手工試了下1, 1' , 1" 以及其他標準盲注手段,全都沒有回顯或報錯。。。。。。這種時候,與其考慮是不是進行了各種過濾,不如換個思路:底下送分題三個大字暗示著我們這個id也許不是用來注入的,只是用來爆破的呢?
于是用bp抓包,考慮到初始id為1 ,選擇直接用數字序列來爆破。果然id=2333時有結果出flag了。
//不得不說這腦洞真的可以,作為一道簡單題成功在思路上把人引向了注入。
NewsCenter
這道題相比起來就簡單許多了,進入后有一個很顯眼的提交框,盲猜sql注入且是post提交。因此直接在所給的提交框里構造語句就很簡單了。本題沒有任何為難人的過濾(發現#沒被過濾但是--+被過濾了,有點難堪),一步步用union select 爆出庫,表,列,字段值即可。
NaNNaNNaNNaN-Batman
這道題老實說有點蒙,因為題目所給的附件解壓后得到的文件內容web100是這樣的:
<script>_='function $(){?e=?getEle?ById("c").value;?length==16?^be0f23?233ac?e98aa$?c7be9?){?tfl?s_a?i?e}?na?_h0l?n?rg{?e?_0?iit\'?_?n?s=[t,n,r,i];for(?o=0;o<13;++o){ ?[0]);?.splice(0,1)}}} \'<input id="c">< onclick=$()>Ok</>\');delete _????var ?","?docu?.?)?match(/?"];??/)!=null=[" ?write(?s[o%4]button?if(e.?ment';for(Y in $='??? ???????')with(_.split($[Y]))_=join(pop());alert(_)</script>
顯然這是段js代碼,但是中間出現的各種亂碼讓我不太理解。可能是因為編碼方式出現了亂碼?于是我嘗試用記事本打開修改編碼方式卻無濟于事。
所以其實js代碼中的<0x..>之類的標簽用其他方式打開都是亂碼,那么怎樣才能看到真實正確的代碼呢?
這里我在網上求助了下,發現首先應該將web100改為html后綴,打開后執行發現是一個提交框。
這里進行代碼審計可以發現,最后一句eval()執行的變量是也就是上述包括了一個函數 $()的一大串字符串。所以這里是把這個字符串解釋為代碼執行,但因為亂碼的緣故不能正確執行,只顯示了提交框。所以,把eval()改為alert(),就能成功看到完整的源碼。
function $(){
var e=document.getElementById("c").value;
if(e.length==16)
if(e.match(/^be0f23/)!=null)
if(e.match(/233ac/)!=null)
if(e.match(/e98aa$/)!=null)
if(e.match(/c7be9/)!=null)
{var t=["fl","s_a","i","e}"];
var n=["a","_h0l","n"];
var r=["g{","e","_0"];
var i=["it'","_","n"];
var s=[t,n,r,i];
for(var o=0;o<13;++o){
document.write(s[o%4][0]);s[o%4].splice(0,1)}}}
document.write('<input id="c"><button onclick=$()>Ok</button>');
delete _
仔細閱讀源碼,發現有兩種getflag方式,一種是按正則執行,所以構造符合要求的字符串:
1.開頭要有be0f23
2.結尾要是e98aa
3.整個字符串能匹配到233ac與c7be9子串
所以構造e=be0f233ac7be98aa即可
第二種方式就很簡單了,因為源碼其實已經告訴你了flag就是后面正則繞過后這段代碼執行的結果,甚至不需要執行,直接看這幾個字符列表里字母順序,從上到下就是flag也能知道要按什么規則求flag的值。當然,最簡單的還是直接執行這段js代碼,可以放在chorme控制臺中運行或者自己用編輯器也可以。
PHP2
這道題自己還是吃了沒水平的虧。開始上來就問你能否向網站進行身份驗證?然后我操起常規操作,先看index.php,再上Fiddler抓包,再用御劍掃描,結果一無所獲。。。。。。難道還有別的辦法獲取有用信息嗎?老實說我一時想不到,直到看了網上題解才知道可以直接輸入index.phps查看index.php的源碼。。。 `76TRTD
<?php
if("admin"===$_GET[id]) {
echo("<p>not allowed!</p>");
exit();
}
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin")
{
echo "<p>Access granted!</p>";
echo "<p>Key: xxxxxxx </p>";
}
?>
略顯熟悉的代碼。。。仔細一想,誒我好像還做過。無非就是“==”的繞過,那么進行審計吧,首先get傳參id,要求不能是id嚴格等于admin,但是得在經歷一次url解碼后=admin......那就好辦了,還記得之前說瀏覽器輸入內容會先進行一次解碼,而函數又會再解一次碼,所以這里只需編碼兩次就好
tip:這里有一個小技巧:實際上大家應該都有所體會,那就是你實際輸入的字符串在各種textwizard中進行urlencode后還是原字符串,按照這種規則,我們在需要對字符串進行url編碼時,最好是寫腳本或者搜索十六進制轉字符串(url編碼規則實際上是對其進行10進制轉16進制,比如a的ascii碼是97,十六進制為61)因此構造payload就是對admin編碼兩次為%2561%2564%256d%2569%256e......
等等,真的需要編碼這么多嗎?其實不然,相信有很多人明白了,其實只需對其中一個字母編兩次碼就可以繞過強相等判斷了,后面解碼其實不影響字符串內容。所以最簡單的payload應該是id=%2561dmin
unserialize3
相比上題,這道題可謂提示的仁至義盡了。上來標題告訴我們肯定跟php序列化有關,且打開后有代碼:
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
定義了一個類,變量已經告訴我們是flag了,以及一個魔術方法退出程序,最后還有一個暗示get傳參code的。到這里如果做過一兩次php序列化的題目的應該就很熟悉了,肯定是php腳本運行得到flag序列化后的值傳參。
但是,這道題難點在于怎么解決 __wakeup()函數的問題.百度發現,__wakeup()函數與反序列化函數一起使用,反序列化函數執行前,就會檢查這個魔術方法的存在與否,有則執行。但它同樣也有漏洞,那就是當序列化值的屬性大于類本身的屬性值時,會跳過這個魔術方法。
所以,我們只需先寫腳本
<?php
class xctf
{
public $flag = '111';
public function __wakeup()
{
exit('bad requests');
}
}
$a=new xctf();
echo(serialize($a));
?>
得到O:4:"xctf":1:{s:4:"flag";s:3:"111";}
序列化字符串各部分簡單釋義:
O代表結構類型為:類:4表示類名長度:接著是類名:屬性(成員)個數
大括號內分別是:屬性名類型;長度:名稱:值類型:長度:值
因此,把屬性從1 改為2 ,成功拿到flag。
mfw
這道題老實說我肯定不會做,因為自己對git源碼泄露沒有概念。en一開始進頁面時就忽略了,因此它提示了可能是git源碼泄露(當前大量開發人員使用git進行版本控制,對站點自動部署。如果配置不當,可能會將.git文件夾直接部署到線上環境。這就引起了git泄露漏洞),輸入/.git/可以看到
這時可以在linux系統下使用GitHack-master還原源代碼。
這時先看index.php源碼(cat index.php),如下:
<?php
if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
}
$file = "templates/" . $page . ".php";
// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");
根據php源碼,肯定要在assert()函數上下手了,同時注意是get傳參page進行繞過,,,這里又是我一大盲區,通過題解得知,有一個通過system()函數繞過的方法,payload如下
?page=').system("cat templates/flag.php");//
當然良好的習慣是先檢查system()函數能否使用,構造page=').phpinfo();//即可
打開flag.php后查看源碼得flag
lottery
本來很簡單一道題的,不過自己之前因為沒裝好githack就沒做。下面簡單提一下流程
首先,目標是最終頁面里claim you prize 中9990000的獎勵,估計就是flag了。首先開始沒什么信息提示,嘗試了下robots.txt發現/.git/被ban了。那么這里就要用到githack將.git泄露源碼下載下來。這里還是建議直接下載在虛擬機里的kali上吧。因為githack是python2寫的,自己win10系統上裝的3。基于python2今年之后就不再更新,還是老老實實在虛擬機里用現成的2吧。
之后下載下源碼,在api.php中可以發現存在弱類型比較的漏洞:
用戶輸入的數據: {"action":"buy","numbers":"1234567"}
用于比較的數字是隨機生成的數字字符串,且只是==弱類型比較。那么只需給numbers傳七個true就行了。
payload:
{"action":"buy","numbers":{true,true,true,true,true,true,true}}
把錢攢夠了就可以買flag了。
bug
又是一道之前自己不知怎么沒做出來的題。。。這一會再做感覺比較輕松。不過查看了題解才發現仍然很有的位置套路滿滿。首先經過幾番嘗試后發現可以在首頁的改密碼處抓包,發現傳值包括username與password。那么把username改為admin就可以用自己改好的密碼登錄進去了。進去后一無所獲,然后發現提示ip不匹配,于是老套路改xff頭尾127.0.0.1。 從返回源碼處發現提示要改do參數,這里正確答案是令do=upload。不過我也不知道為什么要upload?zhiji