引言:我的系列博客[网络安全学习篇]上线了,小编也是初次创作博客,经验不足;对千峰网络信息安全开源的视频公开课程的学习整理的笔记整理的也比较粗糙,其实看到目录有300多集的时候,讲道理,有点怂了,所以我就想到了通过写博客(课程笔记)的形式去学习它,虽然写博客会让我多花几倍的时间去学习它,但是当我完成一篇博客所获得的成就感和你们对于我的认同感,让我很满足,能够鼓励我一天天的坚持下去,也希望和我一起学习本期视频的"同道"们也能给一直坚持下去。我们大家一起加油。由于作者本身也是网络信息安全小白,大部分知识点都是初次接触,出现对其理解不深入,不完整,甚至也会出现错误有问题的地方,希望大家谅解、留言提出指正,同时也欢迎大家来找我一起交流学习!!!
往期博客:
第一阶段:
[网络安全学习篇1]:windowsxp、windows2003、windows7、windows2008系统部署(千峰网络安全视频笔记)
[网络安全学习篇24]:漏洞与木马(千峰网络安全视频笔记 p117-p118)
第二阶段:
[网络安全学习篇25]:初识Linux及简单命令
[网络安全学习篇32]:Linux脚本编写汇总及应用
第三阶段:
[网络安全学习篇33]:0基础带你入门python
[网络安全学习篇38]:基础环境搭建
[网络安全学习篇39]:HTML标签基础 常用的标签 表格
[网络安全学习篇42]:靶场环境搭建(ubuntu系统安装优化及vulhub安装)
[网络安全学习篇43]:PHP基础+变量 运算符 流程控制语句
[网络安全学习篇48]:JS 基础 函数 事件)
第四阶段:
[网络安全学习篇49]:渗透测试方法论
[网络安全学习篇50]:Web架构安全分析
[网络安全学习篇51]:信息收集
[网络安全学习篇52]:扫描技术
[网络安全学习篇53]:口令破解
[网络安全学习篇54]:SQL注入
[网络安全学习篇55]:SQL自动化注入
[网络安全学习篇56]:XSS
[网络安全学习篇57]:XSS(二)
[网络安全学习篇58]:PHP代码注入
[网络安全学习篇59]:OS命令注入
[网络安全学习篇60]:文件上传
[网络安全学习篇61]:文件包含
[网络安全学习篇62]:CSRF 攻击
[网络安全学习篇63]:SSRF
[网络安全学习篇64]:业务安全
[网络安全学习篇65]:提权
[网络安全学习篇66]:Metasploit(MSF)
[网络安全学习篇67]:python poc-exp
[网络安全学习篇68]:反序列化漏洞(本篇)
下期博文:
[网络安全学习篇69]:渗透测试实战-DC-1-靶机入侵
目录
反序列化
为什么要序列化
PHP 中序列化与反序列化
*简单的例子
*序列化Demo
*漏洞何在?
@ 创建一个类,一个对象并将其序列化和反序列化
@ 反序列化注入
*为什么会这样呢
class 类
obj 对象
百度百科上序列化是这样当以的将对象的状态信息转换为可以存储或传输的形式(字符串)的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
简单的说,序列化就是把一个对象变成可以传输的字符串,可以以特定的格式在进程之间跨平台、安全的进行通信。
PHP 反序列化漏洞也叫PHP 对象注入,是一个常见的漏洞,这种类型的漏洞虽然有些难以利用,但一旦利用成功就会造成非常威胁的后果。漏洞的形成的根本原因是程序员没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被恶意控制,进而造成代码执行、getshell 等一系列不可控的后果。反序列化漏洞并不是PHP 特有的,也存在于Java、Python 等语言之中但其原理基本相通。
PHP中的序列化与反序列化,基本都是围绕serialize()和 unserialize() 两个函数展开的。
我们可以用json 格式数据的编码与解码,来理解序列化与反序列化过程。虽然json 数据与反序列化漏洞没有什么关系,但是这个例子有助于我们理解。
测试代码:
'GGG','age'=>18,'SEX'=>true,'score'=>89.9);
echo $stu;
echo "
";
$stu_json=json_encode($stu);
echo $stu_json;
?>
我们定义一个数组,数组属于抽象的数据结构,为了方便跨平台传输,可以将其进行json 编码。json 格式的数据是以键值对的形式出现的。
Array{"name":"GGG","age":18,"SEX":true,"score":89.9}
序列化会将一个抽象的转换为字符串。
我们可以写一个Demo 来说明序列化的过程,首先创建一个类,代码如下
类名是Stu ,有四个变量。
下面我们创建一个对象,并给对象中变量赋值。代码如下
name = "GGG";
$stu1->sex = true;
$stu1->age = 18;
$stu1->score = 89.9;
echo serialize($stu1);
?>
我们最后使用serialize() 函数,将$stu1 这个对象序列化成一个字符串。这样的字符串,就很容易传输和存储。如下
O:3:"Stu":4: //O 代表Object 对象;3对象名有三个字符;对象中有4个变量
{s:4:"name";s:3:"GGG";
s:3:"sex";b:1;
s:3:"age";i:18;
s:5:"score";d:89.900000000000006;}
同样,我们也可以使用unserialize()函数,将字符串反序列化为一个对象。由于字符串中含有双引号,我们可以使用定界符,代码如下
运行这个脚本,我们可以看到反序列化后的对象
object(Stu)#1 (4) { ["name"]=> string(3) "GGG" ["sex"]=> bool(true) ["age"]=> int(18) ["score"]=> float(89.9) }
str);
}
}
$test = new Test();
echo serialize($test);
echo "
";
var_dump(unserialize($_GET['obj']));
?>
构造序列化字符
…/class/loudong.php?obj=O:4:"Test":1:{s:3:"str";s:10:"phpinfo();";}
会发现phpinfo() 函数被执行了
由以上代码可以发现,PHP的反序列化漏洞需要与其他漏洞配合,比如代码执行SQLi等
我们注入的字符串[phpinfo()],为什么会作为PHP 语句执行呢?我们没有调用__destruct ()函数,为什么它会被执行呢?
我们可以使用如下测试代码来测试__destruct() 函数
str);
}
}
$test = new Test();
echo serialize($test);
echo "
";
var_dump(unserialize($_GET['obj']));
?>
我们会发现,在销毁实例化类(对象)的时候,__destruct() 函数会被调用,并输出字符串
以 __ 开头的方法,是PHP 中的魔术方法,类中的魔术方法,在特定的情况下会被自动调用。主要魔术方法如下
__construct() |
创建对象时自动调用 |
__destruct() |
在销毁对象时自动调用 |
__call() |
在对象中调用一个不可访问方法时,__call() 会被调用 |
__callStatic() |
在静态上下文中调用一个不可访问方法时调用 |
__get() |
读取不可访问属性的值时,__get() 会被调用 |
__set() |
在给不可访问属性赋值时,__set() 会被调用 |
__isset() |
当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用 |
__unset() |
当对不可访问属性调用 unset() 时,__unset() 会被调用 |
__sleep() |
serialize() 函数会检查类中是否存在一个魔术方法__sleep() ,如果存在,该方法会鲜卑调用,然后再执行序列化操作 |
__wakeup() |
unserialize() 会检查是否存在一个 __wakeup() 方法,如果存在会先调用__wakeup方法,预先准备对象需要的资源 |
__toString() |
__toString() 方法用于一个类被当成字符串时应增氧回应 |
__invoke() |
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用 |
__set_state() |
字PHP 5.1.0 起调用 var_export() 导出类时,此静态 方法会被调用 |
__clone() |
当复制完成时,如果定义了 __clone 方法,则新创建的对象(复制生成的对象)中的 __clone() 方法会被调用,可用于修改属性的值。 |
__debugInfo() |
This method is called by var_dump() anobject to get the properties that should be shown .If the method isn't on an object ,then all public ,protected and private propertieswill be shown. |
参考文献:
千峰网络信息安全开源课程