[CISCN2019 華北賽區 Day1 Web1]Dropbox之愚見

今天在BUUctf上做了此題,正好想找機會加深一下對phar相關知識的理解,


登錄界面

一打開是個登陸界面,簡單試了下好像沒法注入,而且可以注冊,并不一定要強行登錄什么,不妨注冊一下,


此處我為了簡單填的kendo: kendo,

然后就會跳轉回登錄頁面,我們輸入賬號密碼登錄,進入主頁,是一個可以上傳文件的版面,

按常理是只讓上傳圖片類型,這里我們簡單對服務端的上傳過濾做個簡單測試,看看他的過濾有多嚴格,



這里我們把一個php文件的后綴改為jpg之后上傳,也沒做什么別的處理,


發現上傳成功,看來這個題目比較友好,

接下來我們點擊下載,


通過抓包可以看到,這個filename直接裸露在我們面前,促使我們去考慮文件任意下載,但是服務端是否對filename做了過濾,還有待嘗試,


這里需要注意一個細節,按照慣例和經驗,我們上傳的文件是放在 網站主目錄/sandbox/hash 目錄下的,所以要想下載php文件必須跳轉到上級目錄,


成功下載


既然這樣,我們可以再點一下刪除,這里的delete.php一定也存在任意文件刪除漏洞。如此我們可以順藤摸瓜,下載下來這個網站的所有php文件,這里我們已知的除了index.php,還有已經遇見的upload.php, register.php, login.php, download.php, delete.php,再加上這些php文件中include的class.php,我們都下載下來。


在本地搭建了這樣一個環境,既然有源碼,接下來就是審計的問題。

應該先看的就是config.php、class.php或function.php這類文件,對于此題來說我們先看class.php,此處先是和數據庫建立連接,而后分別是User類,FileList類,File類,


參數綁定

我們可以發現,這里和數據庫交互的語句全部進行了參數綁定,也就是說,SQL注入我們可以不想了,應該考慮別的知識點,

在download.php里,我們發現了一個暗示,雖然filename我們可控,導致任意了任意下載,但是它不讓我們下載文件名里有flag的文件,暗示我們本題中要讀取文件名里有'flag'的文件,

講真,這個提示即使作為暗示,也是比較晦澀的(我也是看了大佬的wp才知道是'/flag.txt',或許大佬們有更高大上的操作,望不吝賜教),只能在后面嘗試網站根目錄下有沒有flag.txt(php),或者逐級讀取直到根目錄下有沒有flag.txt(php),

向下走,我們在FileList類中發現了一個有意思的函數,這是一個魔術方法,

PHP5 的對象新增了一個專用方法 __call(),這個方法用來監視一個對象中的其它方法。如果你試著調用一個對象中不存在的方法,__call 方法將會被自動調用

這個方法在這里很突兀,內容也很強硬、直接、粗暴,應該來講,它的出現就是提醒我們,該考慮使用phar了。

phar文件是php的壓縮文件,它可以把多個文件歸檔到同一個文件中,而且不經過解壓就能被 php 訪問并執行,phar://與file:// ,php://等類似,也是一種流包裝器。至于深層次的知識點,網上有很多大佬寫的非常詳細,有的甚至深入到底層代碼,貼出鏈接:

關于phar的格式:https://blog.csdn.net/u011474028/article/details/54973571

關于phar://的利用:https://xz.aliyun.com/t/2715

所以我就不再班門弄斧,只對幾個小問題簡單談下自己淺顯的理解。

一是為什么phar協議讀取phar文件會觸發反序列化操作,

先說一下phar文件結構:

1、stub

一個供phar擴展用于識別的標志,格式為xxx<?php xxx; __HALT_COMPILER();?>,注意此處必須以__HALT_COMPILER();?>結尾,但前面的內容沒有限制,也就是說我們可以在前面輕易偽造一個圖片文件的頭如GIF98a來繞過一些上傳限制;

2、manifest

phar文件本質上是一種壓縮文件,每個被壓縮文件的權限、屬性等信息都放在這部分。另外,這部分還會以序列化的形式存儲用戶自定義的meta-data,這就是觸發反序列化的點,當文件操作函數通過phar://偽協議解析phar文件時就會將數據反序列化。至于為什么會這樣,有大佬深入了底層源代碼進行分析,我也不懂。
3、contents

被壓縮文件的內容,不是主要的點。

4、signature

簽名,放在文件末尾,不用我們操心

二是為什么使用phar協議讀取改為其他后綴名的phar文件也能觸發反序列化,

底層的原因我不知道,我只能舉個例子進行類比:

我們先寫一個1.php,內容為<?php phpinfo();然后改名為1.jpg


在index.php里面include它,

結果我們發現成功讀取了phpinfo


我們在php.net上可以看到,


就算說包含一個圖片文件沒毛病,運行一個圖片文件多少有些不妥,所以我猜測,include會將被包含文件作為php文件運行,類比來看,將demo.phar改名為demo.jpg之后,phar://協議也會將demo.jpg作為phar文件處理,所以我們也可以通過phar://demo.jpg正常訪問demo.phar。雖然是類比,不具有很強的說服力,但php的文件函數都是以流的形式讀取文件,這些多少都是相通的,從代碼邏輯上本就應該具有較高的相似性。

三是為什么加上phar://就能以phar文件的格式讀取文件,類似的,為什么print(file_get_contents("php://input"))就能打印出post的內容,

我太菜了,不懂底層實現,這里還是舉例子做類比,在我們使用Python讀取文件的時候,寫的是with open('1.txt', 'r') as f:,那么問題來了,'1.txt'不過是一個字符串而已,為什么能能讀取出1.txt的內容呢,類似的例子在PHP里也有,比如include "1.php",最終也是將1.php包含并運行,而'1.php'也不過是個字符串而已,我們echo '1.php'也好,echo"php://input"也好,都不會有任何作用。

我個人的理解是,'1.php'本身是個字符串,'php://input'本身也是字符串,但是include、file_get_contents都是進行的文件流操作,會把字符串的實際意義和文件流關聯起來,使其不再是簡單的字符串。個人認為這樣理解問題不大,至于正確與否,日后一定會補上。

四是舉個實際應用的例子,雖然別的大佬寫的很多了,但我總覺得自己不寫一下不完整,

先是一個index.php,里面聲明了兩個類,

而后在demo.php里通過控制參數來生成可利用的phar文件(需要配置php.ini的phar.readonly = Off后重啟Server),

最后在demo1.php里file_get_contents一下,

雖然有個警告(也不知啥原因,有知道的同志望不吝賜教),但代碼還是執行成功了。

這只是一個很簡單的例子,實戰價值不大,畢竟現實情況下,每個類都是在服務端寫好的,服務端不傻,不能保證我們每次都能遇到里面直接有eval($s)這樣對選手十分友好的類,也很難保證直接在__destruct里面就能觸發相應函數,可能需要去尋找其他魔術方法,畢竟非魔術方法我們是幾乎沒可能直接調用的。比如本題中就沒有任何代碼執行或命令執行語句可供使用,迫使我們只能去想文件讀取。但總的來說,基本思路就是這樣:上傳phar文件,利用類中的可利用的方法,找到服務端文件操作函數并以phar://協議讀取phar文件。

有大佬總結的利用條件:

1)phar文件要能夠上傳至服務器

2)要有可用的魔術方法為跳板

3)文件操作函數的參數可控,且:、/、phar等特殊字符沒有被過濾

對于本題而言,第一條滿足,第二條有一個魔術方法__call()和FileList類、User類的__destruct(),恐怕想不利用它們也不行,第三條后半部分沒問題,前半部分則需要我們找一找。

既曰文件操作函數,就應該在本題的File類(至多也在FileList類)的方法中尋找,畢竟整個題目基本上都是在面向對象的基礎上編程,對文件的操作也都是對File類的對象的操作,

我們看到,open()方法調用了file_exists()和is_dir()函數(注意name方法里的basename函數不算),size()方法調用了filesize()函數,delete()方法調用了unlink()函數,close()方法file_get_contents()函數。

我們前面提到了,本題要讀取/flag.txt文件,故剛剛列舉的這些函數中,雖然文件操作函數不少,可以用來觸發反序列化,對讀取文件有用的只有close()方法中的file_get_contents()函數這一個,所以我們可以對它分析,

這個時候,如果想不到__call()方法和__destruct()方法,基本上就可以放棄了,在phar題目里,魔術方法一般來講是必須要用的,

這里我們看到,FileList的__call()方法語義簡單,就是遍歷files數組,對每一個file變量執行一次$func,然后將結果存進$results數組,

接下來的__destruct函數會將FileList對象的funcs變量和results數組中的內容以HTML表格的形式輸出在index.php上(我們可以看到,index.php里創建了一個FileList對象,在腳本執行完畢后觸發__destruct,則會輸出該用戶目錄下的文件信息),

User對象的__destruct()方法,


無非就是 腳本執行完畢后,執行$db的close()的方法(來關閉數據庫連接),但話說回來,沒有括號里的話,這句話依然成立,而且這個'close'與File類中的close()方法同名。所以,當db的值為一個FileList對象時,User對象析構之時,會觸發FileList->close(),但FileList里沒有這個方法,于是調用_call函數,進而執行file_get_contents($filename),讀取了文件內容。整個鏈的結構也很簡單清晰:在我們控制$db為一個FileList對象的情況下,$user->__destruct() => $db->close() => $db->__call('close') => $file->close() => $results=file_get_contents($filename) => FileList->__destruct()輸出$result。

接下來,我們開始著手構造POP鏈,


這里的類都是簡化了寫的,類的成員由屬性和方法構成,序列化一個對象將會保存對象的所有變量,但不會保存對象的方法,只會保存類的名字。因此,反序列化的主要危害在于我們可以控制對象的變量來改變程序執行流程。在這個過程中,我們無法調用對象的普通方法,故我們這里只能利用可以調用的魔術方法。

上傳后,在刪除文件時抓包,修改filename

即可得到flag.

這里要注意一個細節:

download.php中的ini_set

ini_set(“open_basedir”, getcwd() . “:/etc:/tmp”); 這個函數執行后,我們通過Web只能訪問當前目錄、/etc和/tmp三個目錄,所以只能在delete.php中利用payload,而不是download.php,否則訪問不到沙箱內的上傳目錄。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容

  • EZcms https://www.cnblogs.com/wfzWebSecuity/p/11527392.ht...
    Err0rzz閱讀 1,427評論 0 1
  • 4.1.1. 后門 4.1.1.1. php.ini構成的后門 ??利用 auto_prepend_file 和 ...
    最酷的崽_ec69閱讀 590評論 0 0
  • 什么是composer 在之前的PHP開發中,我也僅僅是使用composer來進行依賴的管理,沒有深度去理解到底什...
    橙知閱讀 6,016評論 0 4
  • 前言 這道題思路其實就是,如果在php中遇到了模版注入,但是限制了不允許執行php代碼的時候,怎么通過模版注入達到...
    f1ight閱讀 1,323評論 0 1
  • 一、Python簡介和環境搭建以及pip的安裝 4課時實驗課主要內容 【Python簡介】: Python 是一個...
    _小老虎_閱讀 5,790評論 0 10