一
進入頁面發現一個大的滑稽臉,查看源代碼,發現提示source.php
進入該頁面,進行代碼審計,又發現一個hint.php
頁面,進入發現提示
表明 flag 在這個文件中,且這個文件名暗示要使用四層目錄
二
繼續審計代碼
發現滿足三個條件,會包含並運行指定文件file
,此處的file
可以由我們構造,爲切入點:
- 檢查
file
變量是否爲空 - 檢查
file
變量是否爲字符串 - 通過自定義的
checkFile
函數來檢查
由於我們要構造payload,前兩點直接滿足,直接查看checkFile
函數代碼:
發現包含四個if語句:
- 第一個 if 語句對變量進行檢驗,要求
$page
爲字符串,否則返回 false - 第二個 if 語句判斷
$page
是否存在於$whitelist
數組中,存在則返回 true - 第三個 if 語句,截取傳進參數中首次出現
?
之前的部分,判斷該部分是否存在於$whitelist
數組中,,存在則返回 true - 第四個 if 語句,先對構造的 payload 進行 url 解碼,再截取傳進參數中首次出現
?
之前的部分,並判斷該部分是否存在於$whitelist
中,存在則返回 true
以上四個滿足一個即可返回 true,若均未滿足,則返回 false
三
我們利用第三個 if 語句構造參數:
?file=source.php?/../../../../ffffllllaaaagggg
第一個?
表示傳參,第二個?
用來滿足截取
四
- 爲什麼
include source.php(或hint.php)?/../../../../ffffllllaaaagggg
能執行成功
因爲我們的參數是有/../../../../
這樣的路徑,所以符合最後一段話如果定義了路徑,就會忽略/
前的字符串而去找/../../../../ffffllllaaaagggg
這個文件 - 網上大多數 writeup 用到的 url 編碼繞過發現並沒有用到,這一方法的思路是將
?
進行兩次 url 編碼,變爲%253f
,在服務器端提取參數時自動解碼一次,checkFile
函數中解碼一次,仍會解碼爲?
,可以繞過第四個 if ,但是實測只編碼一次也可以得到 flag