PHP File Access in Windows
起源
這篇文章是打了 MMA CTF 2nd 2016 後,詢問學長產出的一篇心得文。
這場 CTF 為期 48 小時,題目也是眾多(而且主辦方是日本,一堆 ruby source code),不過第二天我什麼題目都解不出來,頗令人挫折,看來這條路沒這麼好走啊XD
唉呀呀離題了,這篇文章會探討 PHP 在 Windows 下存取檔案的一些奇怪行為,讓你分不出 Windows 的 bug 跟 feature。
首先來看一下 MMA CTF 2nd 2016 的這一題:
Rotten Uploader - 150
Find the secret file.
http://rup.chal.ctf.westerns.tokyo/
Hint1 (2016/09/04 16:31)
- The files/directories on the DOCUMENT_ROOT are below four.
- download.php
- file_list.php
- index.php
- uploads(directory)
- The number of files in the DOCUMENT_ROOT/uploads is 5. The directory have "index.html".
- You don't need scan tools.
首先進入頁面可以看到很明顯的 LFI (Local file inclusion) 漏洞:
http://rup.chal.ctf.westerns.tokyo/download.php?f=../index.php
http://rup.chal.ctf.westerns.tokyo/download.php?f=../download.php
但是要拿 file_list.php
這個檔案卻失敗,仔細看了一下 download.php
,原來被加了防護:
<?php
header("Content-Type: application/octet-stream");
if(stripos($_GET['f'], 'file_list') !== FALSE) die();
readfile('uploads/' . $_GET['f']); // safe_dir is enabled.
?>
直覺告訴我,打開 file_list
,flag 就不遠矣!
然後我就卡在這裡,直到比賽結束……
Solution 1: WinAPI feature
主要參考自 onsec whitepaper 02,假設你要讀取 1.php
這個檔案,使用 php 的 file_get_content($url)
,$url
等於下列任何一個值都會成功讀取:
1.php
1.phP
1.ph>
1.ph<
前面兩個是因為檔案系統不分大小寫的關係,後面兩個就非常詭異了,可以上網找 onsec whitepaper 02
自己看一下,這裡引用第五頁的話:
character > gets replaced with ?, character < transforms to *
當然這個 ?
就是任意單一字元,*
是任意長度字元,跟 bash 的 wildcard 字元相同。
雖然它用了不分大小寫的檢查 stripos
,讓我們無法用換成大寫的方法繞過,但可以用 wildcard 躲過他的判斷,payload 如下:
# 它會被取代成 ?
http://rup.chal.ctf.westerns.tokyo/download.php?f=../file_lis>.php
# 這樣也可,它會被取代成 *
http://rup.chal.ctf.westerns.tokyo/download.php?f=../file<.php
Reference: Fluxion’ write-up
Solution2: 8.3 Filename
8.3 filename 是早期 DOS 檔案名稱的習慣,8 的意思是在 .
前面有八個字元,.
後面的副檔名為三個字元。
重點是,為了向前兼容,現在的 Windows 系統仍然會支援這種格式,至於他是怎麼解讀呢?這就是可以下手的點了,參考 wiki 的這一節
Example:
TextFile.Mine.txt
becomesTEXTFI~1.TXT
(orTEXTFI~2.TXT
, shouldTEXTFI~1.TXT
already exist).ver +1.2.text
becomesVER_12~1.TEX
..bashrc.swp
becomesBASHRC~1.SWP
所以file_list.php
會變成 file_l~1.php
,那麼 Payload 就是 download.php?f=../file_l~1.php
Reference: Tomislav Zubcic’s blog
我感覺 Windows 的 8.3 filename
肯定會造成很多漏洞……
後記
一般遇到這種很明顯要繞過某個判斷式的題目,首先可以嘗試繞過函數,例如型態判別寫的不對,可以送 array 或是 boolean 讓它判斷出錯;再來就是研究函數漏洞,有些函數解析會有問題,例如 AIS3 2016 pre-exam web3;沒招了就往檔案系統下手,Windows 果然很多洞(bug)….阿不,是特色(feature)!
註:文章開頭問的學長是 217 的 Shik 大大喔~