[CISCN2019 華北賽區(qū) Day1 Web1]Dropbox之愚見

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


登錄界面

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


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

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

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



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


發(fā)現(xiàn)上傳成功,看來這個題目比較友好,

接下來我們點擊下載,


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


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


成功下載


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


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

應該先看的就是config.php、class.php或function.php這類文件,對于此題來說我們先看class.php,此處先是和數(shù)據(jù)庫建立連接,而后分別是User類,F(xiàn)ileList類,F(xiàn)ile類,


參數(shù)綁定

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

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

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

向下走,我們在FileList類中發(fā)現(xiàn)了一個有意思的函數(shù),這是一個魔術方法,

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

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

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

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

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

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

一是為什么phar協(xié)議讀取phar文件會觸發(fā)反序列化操作,

先說一下phar文件結(jié)構(gòu):

1、stub

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

2、manifest

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

被壓縮文件的內(nèi)容,不是主要的點。

4、signature

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

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

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

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


在index.php里面include它,

結(jié)果我們發(fā)現(xiàn)成功讀取了phpinfo


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


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

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

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

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

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

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

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

最后在demo1.php里file_get_contents一下,

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

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

有大佬總結(jié)的利用條件:

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

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

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

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

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

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

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

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

這里我們看到,F(xiàn)ileList的__call()方法語義簡單,就是遍歷files數(shù)組,對每一個file變量執(zhí)行一次$func,然后將結(jié)果存進$results數(shù)組,

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

User對象的__destruct()方法,


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

接下來,我們開始著手構(gòu)造POP鏈,


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

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

即可得到flag.

這里要注意一個細節(jié):

download.php中的ini_set

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容