CTF必看~ PHP反序列化漏洞6:绝妙

您所在的位置:网站首页 反序列化漏洞是什么 CTF必看~ PHP反序列化漏洞6:绝妙

CTF必看~ PHP反序列化漏洞6:绝妙

2023-06-01 19:38| 来源: 网络整理| 查看: 265

作者:Eason_LYC 悲观者预言失败,十言九中。 乐观者创造奇迹,一次即可。 一个人的价值,在于他所拥有的。可以不学无术,但不能一无所有! 技术领域:WEB安全、网络攻防 关注WEB安全、网络攻防。我的专栏文章知识点全面细致,逻辑清晰、结合实战,让你在学习路上事半功倍,少走弯路! 个人社区:极乐世界-技术至上 追求技术至上,这是我们理想中的极乐世界~(关注我即可加入社区)

本专栏CTF基础入门系列打破以往CTF速成或就题论题模式。采用系统讲解基础知识+入门题目练习+真题讲解方式。让刚接触CTF的读者真正掌握CTF中各类型知识点,为后续自学或快速刷题备赛,打下坚实的基础~

目前ctf比赛,一般选择php作为首选语言,如读者不了解php的基本语法,请登录相关网站自学下基本语法即可,一般5-7天即可掌握基础。

本文是系列文章,知识点环环相扣,难度依次递增,请首先阅读之前的文章后,再阅读本文效果更加~

目录 1. __wakeup()介绍2.__wakeup()绕过3. 绕过应用举例4. 真实赛题4.1 赛题一赛题2 攻防世界 Web_php_unserialize赛题三:极客⼤挑战 2019 PHP(综合题目)

1. __wakeup()介绍

__wakeup() 是 PHP 中一个特殊的魔术方法。它在反序列化一个对象时被自动调用,允许开发者在对象从序列化格式还原为可用的 PHP 对象之前对其进行某些特殊处理。这个方法可以接受任意的参数,但在实际使用中,它通常不需要参数。

下面是一个简单的示例,它演示了如何在一个 PHP 对象中使用 __wakeup() 方法:

class Example { public $a = 1; public $b = 2; public function __wakeup() { $this->a *= 2; $this->b *= 2; } } $serialized = serialize(new Example()); $unserialized = unserialize($serialized); var_dump($unserialized);

在这个例子中,我们定义了一个名为 Example 的类,它具有两个公共属性 $a 和 $b。在 __wakeup() 方法中,我们将 $a 和 $b 的值各自乘以 2。然后我们序列化一个 Example 对象,并使用 unserialize() 函数将其还原为 PHP 对象。最后,我们使用 var_dump() 函数输出这个对象。运行这个脚本,输出将是:

object(Example)#2 (2) { ["a"]=> int(2) ["b"]=> int(4) }

正如预期的那样,我们的 __wakeup() 方法成功地修改了 $a 和 $b 的值。

在安全编程中,__wakeup() 方法经常用于控制对象的反序列化过程,以避免攻击者能够在反序列化期间执行恶意代码。这是因为反序列化操作本质上是在将一个字符串转换为可执行的代码,因此如果反序列化的对象包含恶意代码,那么它可能会在反序列化过程中执行。

2.__wakeup()绕过

然而,攻击者可以通过多种方式绕过这种保护机制。当反序列化字符串中,表示属性个数的值大于真实属性个数时,会绕过 __wakeup() 函数的执行,是因为 PHP 在反序列化过程中,会忽略掉多出来的属性,而不会对这些属性进行处理和执行。

具体来说,当 PHP 反序列化一个对象时,它首先读取对象的类名,并创建一个新的对象。然后,PHP 会读取对象的属性个数,并将每个属性的名称和值读入对象中。如果属性个数比实际属性个数多,则 PHP 会忽略这些多余的属性,直接将对象反序列化到一个不完整的状态。这将绕过 __wakeup() 函数的执行,因为 PHP 无法通过未知的属性来检查对象的完整性。

攻击者可以利用这个漏洞来绕过 __wakeup() 函数中的安全检查,从而执行任意代码。攻击者可以使用 O 类型的序列化字符串来创建一个新的对象,并在其中添加任意数量的属性。然后,攻击者可以修改序列化字符串中属性的数量,使其比实际属性数量多。由于 PHP 会忽略多余的属性,攻击者可以绕过 __wakeup() 函数的安全检查,并执行恶意代码。

以下是一个漏洞利用的示例代码:

class Example { private $a = 1; private $b = 2; public function __wakeup() { if ($this->a != 1 || $this->b != 2) { die("Invalid values for a and b"); } } } $payload = 'O:7:"Example":3:{s:1:"a";i:2;s:1:"b";i:3;s:1:"c";i:4;}'; $serialized = serialize(new Example()); $serialized = str_replace('s:3:"Example":3', 's:3:"Example":2', $serialized); $unserialized = unserialize($serialized); var_dump($unserialized);

在这个例子中,我们定义了一个名为 Example 的类,它有两个私有属性 $a 和 $b。__wakeup() 方法检查 $a 和 $b 的值是否为 1 和 2。然后我们手动序列化了一个 Example 对象,并使用 O 类型的序列化字符串将其包装起来。在这种情况下,我们添加了一个新属性 $c,并将属性数量设置为 3。然后,我们使用 str_replace() 函数将序列化字符串中属性的数量修改为 2,从而绕过了 __wakeup() 函数的安全检查。因此,运行这个脚本,输出将是:

object(Example)#2 (2) { ["a":"Example":private]=> int(2) ["b":"Example":private]=> int(3) } 3. 绕过应用举例

当反序列化字符串中,表示属性个数的值⼤于真实属性个数时,会绕过 __wakeup 函数的执⾏。

漏洞影响范围 PHP5 < 5.6.25 PHP7 < 7.0.10

标准序列化结果 O:4:"User":2:{s:8:"username";s:4:"Lxxx";s:8:"password";s:4:"lxxx";} 将2改为3 绕过__Wakeup魔法函数 O:4:"User":3:{s:8:"username";s:4:"Lxxx";s:8:"password";s:4:"lxxx";}

4. 真实赛题 4.1 赛题一 源码


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3