安全圈 | 专注于最新网络信息安全讯息新闻

首页

一道反序列化ctf引起的思考

作者 trentadue 时间 2020-02-25
all

只有透徹地理解底層,才能創造奇跡。

這道題有一個平臺複現了出來,可供大家練習,可以訪問如下網址:

http://web.jarvisoj.com:32784/

題目原理

剛開始看到這道題目,我是懵逼的。因為整篇程式碼沒有資料登錄口,然後懷疑有其它機關,抓包、掃目錄無果之後,找到了一篇writeup如下:

https://chybeta.github.io/2017/07/05/jarvisoj-web-writeup/#PHPINFO

瞭解了思路和背景知識之後,仿佛感覺開啟了通向“新世界”的大門~

這是一道純程式碼稽核的題目,沒有其它的貓膩,但卻需要對PHP反序列化機制的理解很深,不然就像我的第一反應一樣,“這不沒漏洞嘛~”。

這個漏洞的關鍵點在於:

ini_set('session.serialize_handler','php');

PHP內寘了多種處理器,用於存取$_SESSION的時候對數據進行序列化和反序列化,這個的意思是在於設定序列化解釋格式,我的理解是和字元集相似,按照某種格式構造和解析序列化的欄位。

漏洞產生在php_serialize和php解析管道上。

如果我們通過php_serialize的管道構造序列化語句,然後通過php的管道解析序列化語句,就會出現問題。原因是在使用php_serialize構造過程中,可以在字串變數中儲存|符號,但是如果按照php的管道解析的話,會把|之前的語句當做數組的鍵,之後的語句當做值,這時我們就可以按照這個特性來構造執行對象的命令。

通過php_serialize構造的:

a:1:{s:4:“ryat”;s:20:“|O:8:”stdClass“:0:{}”;}

以php的管道解析會變為:

array(1){ [“a:1:{s:4:”ryat“;s:20:”“]=> object(stdClass)#1(0){ }}

成功執行了變數。

這時就有一個問題,在題目程式碼中,沒有某個值是用來接受我們傳入的數據,並儲存到$_SESSION中的。

魯迅說過,“沒有程式碼,創造程式碼也要上!”

其實我們是有辦法傳入$_SESSION數據的。

我們查看phpinfo頁面,可以發現,session.upload_progress.enabled是被打開了的,而當這個選項被打開時,php會自動記錄上傳文件的進度,在上傳時會將其資訊保存在$_SESSION中。

session.upload_progress.enabled $_SESSION

這時,我們可以在本地構造一個指向目標頁面的表單:

上傳之後,用burp修改filename,就可以將我們想要傳入的序列化欄位儲存進去。

傳入什麼呢?因為在php大於5.5.4的版本中默認使用php_serialize規則,所以我們可以在本地構造語句:

將想要傳入的數據,傳入即可。

題目思路

知道了原理就可以開始做題了,現時我們掌握的資訊很少,當前頁面的源碼也已經給出。一般來說,最後的flag都會在web根目錄下,或者其它頁面的源碼中,所以我們先嘗試獲取目前的目錄下的檔案清單.

傳入payload等於:

print_r(scandir(dirname(FILE)));

序列化結果為:

O:5:“OowoO”:1:{s:4:“mdzz”;s:36:“print_r(scandir(dirname(FILE)));”;}

抓包,修改filename傳過去

發現可疑檔案

這時我們查看phpinfo介面,可以發現_SESSION[“SCRIPT_FILENAME”]中標注了index.php所在的目錄/opt/lampp/htdocs/,而我們想要的檔案也在裡面,沒網了……截圖傳不到圖床上,就不做演示了,其實到這一步就很簡單了。

_SESSION["SCRIPT_FILENAME"] /opt/lampp/htdocs/

總結

這道題給我印象最深的,就是通過filename傳入$_SESSION數據。按照固有的思維,原始程式碼中都沒有接受口,那就沒辦法嘍。其實很多漏洞,都可以巧妙地通過其它頁面去構造、利用。比如二次注入,以及這次的反序列化解析差异漏洞。

如果我在程式碼稽核的時候遇到這種程式碼,肯定是不知道這裡是有漏洞的,也就錯過了一個很棒的漏洞。

綜上所述,想要成為一個優秀的安全從業人員,第一要務是解放思想,不拘束於固有的思路。第二要務是擴寬知識面,別人不知道的點你卻知道,這就是核心競爭力。

路漫漫,共勉~如果有任何問題可以加群與作者溝通想要投稿者可以加群聯系群主