信息安全实践:课程总结
1. 题目描述
结合选择的漏洞(见附后的分配表),根据课程学习的内容和网上查询资料,整理漏洞总结。总结主要包含以下内容:
-
漏洞的原理
-
漏洞的基本利用方式和可能导致的危害思路
-
检索查找一个较新(尽量 2020 年之后)的真实漏洞案例(附漏洞编号或相关链接),并根据搜索的信息分析说明其形成原因和可能的修补或者加固方式(可以有多种思路)
-
测试时寻找漏洞的思路
-
漏洞的防御方法
-
漏洞防御的绕过思路
-
针对漏洞的其他想法内容
由于我的学号尾号是 8,所以我的漏洞分配是 反序列化。
2. 反序列化漏洞分析
2.1. 漏洞的原理
-
序列化
对象的状态信息转换为可以存储或传输的形式的过程在序列化期间,对象将当前的状态写入到临时或持久性的存储区(将状态信息保存为字符串)。
-
反序列化
将字符串转换为状态信息:序列化<—>反序列化。
序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码。暴露或间接暴露反序列化API,导致用户可以操作传入数据,攻击者可以精心构造反序列化对象并执行恶意代码。
2.2. 漏洞的基本利用方式和可能导致的危害
PHP 通过 serialize() 与 unserialize() 实现序列化与反序列化。
反序列化漏洞利用方式通常可以分为直接利用和间接利用。
-
直接利用:
- 主要是利用反序列化对象数据过程中,必定会执行的魔术方法,利用他们在对变量处理过程中的疏漏。
__construct()当一个对象创建时被调用。__destruct()当一个对象销毁时被调用。__wakeup()如果有,在反序列化之前调用。
-
间接利用:
- 一般是在直接利用的情况下无法达到目的采用的备选方案;这种方案通常会巧妙使用到多个类的魔术方法,进行迂回利用。
- 比如程序中通常会使用到反序列化的变量,如果开发者预想变量是字符串,但攻击者却传递了一个对象进来,便会触发对象的
__tostring()魔术方法。 __toString()当一个对象被当作一个字符串时使用。__get()用于从不可访问的属性读取数据。__call()在对象上下文中调用不可访问的方法时触发。
-
可能导致的危害
危害等同于可以通过反序列化构造和调用的可利用的任何其他漏洞的危害。当存在反序列化漏洞时,不直接使用请求参数的类调用也可能导致问题。
2.3. 真实漏洞案例
-
漏洞编号:
CVE-2020-15148。 -
漏洞介绍
Yii 是一套基于组件、用于开发大型 We b应用的高性能 PHP 框架。Yii2 2.0.38 之前的版本存在反序列化漏洞,程序在调用反序列化函数时,攻击者可通过构造特定的恶意请求执行任意命令。
-
形成原因
如果在使用 yii 框架,并且在用户可以控制的输入处调用了
__unserialize()并允许特殊字符的情况下,会受到反序列化远程命令命令执行漏洞攻击。该漏洞只是 php 反序列化的执行链,必须要配合反序列化函数才可以达到任意代码执行的危害。 -
修补或加固方式
官方通过给
yii\db\BatchQueryResult类加上__wakeup()函数,禁用了yii\db\BatchQueryResult的反序列化,阻止了应用程序对任意用户输入调用__unserialize()造成的远程命令执行。
2.4. 测试时寻找漏洞的思路
-
寻找
unserialize()函数的参数是否有可控点。 -
寻找反序列化的目标,重点寻找存在
wakeup()或destruct()魔法函数的类。 -
一层一层地研究该类在魔法方法中使用的属性和属性调用的方法,看看是否有可控的属性能实现在当前调用的过程中触发的。
-
找到我们要控制的属性了以后就将要用到的代码部分复制下来,然后构造序列化,发起攻击。
2.5. 漏洞的防御方法
-
严格的把控
unserailize()函数的参数,不要给攻击者任何输入的可能。 -
在文件系统函数的参数可控时,对参数进行严格的过滤。
-
严格检查上传文件的内容,而不是只检查文件头。
-
在条件允许的情况下禁用可执行系统命令、代码的危险函数。
2.6. 漏洞防御的绕过思路
-
__wakeup( )绕过反序列化时,如果表示对象属性个数的值大于真实的属性个数时就会跳过
__wakeup( )的执行。__wakeup()在__destruct()函数之前执行。说明,只要存在了反序列化操作,__wakeup()函数的优先级高。当属性个数值大于真实属性个数值时,可绕过__wakeup()函数。 -
注入对象构造方法
当目标对象被 private、protected 修饰时的构造方法。public 属性可以被外部修改而private、proctected 属性无法被对象外部修改。
__toString()函数,把类当做字符串使用时触发,也就是使用 echo 打印对象时触发该函数。序列化后,private变量和 protected 变量的结果与 public 不一样。 -
Session反序列化漏洞
PHP中的 Session 经序列化后存储,读取时再进行反序列化。不同处理器的格式不同,当不同页面使用了不同的处理器时,由于处理的 Session 序列化格式不同,就可能产生反序列化漏洞。
-
PHAR利用
PHAR (“Php ARchive”) 是PHP里类似于JAR的一种打包文件,在PHP 5.3 或更高版本中默认开启,这个特性使得 PHP也可以像 Java 一样方便地实现应用程序打包和组件化。一个应用程序可以打成一个 Phar 包,直接放到 PHP-FPM 中运行。
phar 文件包在生成时会以序列化的形式存储用户自定义的 meta-data。
meta-data 是用serialize()生成并保存在 phar 文件中。当内核调用
phar_parse_metadata()解析 meta-data 数据时,会调用php_var_unserialize()对其进行反序列化操作,因此会造成反序列化漏洞。
2.7. 针对漏洞的其他想法内容
反序列化漏洞依赖几个条件:
-
__unserialize()函数的参数可控。 -
脚本中存在一个构造函数(
__construct())、析构函数(__destruct())、__wakeup()函数中有向 php 文件中写数据的操作的类。 -
所写的内容需要有对象中的成员变量的值。
预防措施:和大多数漏洞一样,反序列化的问题也是用户参数的控制问题引起的,所以好的预防措施就是不要把用户的输入或者是用户可控的参数直接放进反序列化的操作中去。
931

被折叠的 条评论
为什么被折叠?



