PictShare < 3.7.1 中通过 rand() 实现的可预测 delete_code(CWE-338)。PoC + 安全公告分析。
rand() 生成可预测的 delete_code经授权的安全研究。PoC 仅供防御和教育用途。
PictShare 使用 getRandomString() 生成 delete_code
授权令牌,该函数从 PHP 的非加密 rand() 中提取每个字符。由于 rand() 不是 CSPRNG——而且同一个生成器
还产生每个共享 URL 中显示的公开文件哈希——delete_code 是可预测的,而非保密的,从而允许在从未从
info 端点读取代码的情况下未经授权删除托管的文件。
| CVE | CVE-2026-104356 |
| 产品 | PictShare(自托管图片/媒体托管服务) |
| 受影响版本 | >= 2.0.0, < 3.7.1 |
| 修复版本 | v3.7.1 |
| 漏洞 | 使用加密强度不足的 PRNG(CWE-338)→ 可预测的授权令牌 |
| 所需权限 | 无(未认证) |
| CVSS 3.1 | 5.9 MEDIUM — AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H |
| CVSS 4.0 | 8.2 HIGH — AV:N/AC:H/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H |
| 发现者 | Alisher Qarshibayev |
| 安全公告 | VulnCheck |
// src/inc/core.php (< 3.7.1)
function getRandomString($length=32, $keyspace='0123456789abcdefghijklmnopqrstuvwxyz')
{
$str = '';
$max = (function_exists('mb_strlen') ? mb_strlen($keyspace,'8bit') : strlen($keyspace)) - 1;
for ($i = 0; $i < $length; ++$i) {
$str .= $keyspace[rand(0, $max)]; // <-- rand() is NOT cryptographically secure
}
return $str;
}
这一个函数同时产生两者:
delete_code。由于两个令牌都来自同一个非 CSPRNG 流,观察到公开哈希的攻击者就获得了关于生成器状态的信息——
delete_code 不再具有其 32 字符长度所暗示的熵。rand() 不提供任何加密不可预测性保证,
因此将其用于安全令牌就是缺陷所在(CWE-338),与任何特定的状态恢复技术无关。
random_int()。rand()(别名到
Mersenne-Twister 路径),因此一个开箱即用的远程预测器取决于部署情况(进程复用、可观察输出的数量、
PHP 构建版本)。因此本 PoC 在受控种子下确定性地演示了可预测性原理,而不是声称一个通用的
一次性远程破解。这就是该发现的诚实范围——也正是厂商仍将其视为漏洞并加以修复的原因。demo.php 复现了厂商的原始 getRandomString(),并表明一旦 PRNG 状态已知/被恢复,
第一个输出(公开哈希)就完全决定了第二个输出(delete_code)——即观察到哈希即可预测代码:
php demo.php
预期输出:
[*] Reproducing PictShare getRandomString() with rand()
[*] Seed used by victim process : 1337 (unknown to attacker a priori)
public file hash (output #1): k3f9... (visible in the shared URL)
secret delete_code(output #2): 8a1c...
[*] Attacker recovers seed by matching the OBSERVED public hash:
[+] Seed recovered: 1337
[+] Predicted delete_code: 8a1c...
[+] MATCH — delete_code predicted from the public hash alone (no info API needed)
参见 demo.php。它是自包含的(无服务器、无网络),并证明了使 rand() 在此处
不适用的哈希→代码确定性。
升级到 PictShare 3.7.1(修复提交 ce5fc47),
该版本将 rand() 替换为 random_int()(CSPRNG)。一般性指导:使用加密安全的 RNG 生成每一个
安全令牌(删除代码、重置令牌、API 密钥、盐值)——在 PHP 中使用 random_int() / random_bytes()——
绝不要使用 rand()、mt_rand() 或 uniqid()。
注意:修复之前签发的删除代码不会被轮换,因此修复前的上传内容在被重新上传之前仍然可预测。
| 日期 | 事件 |
|---|---|
| 2026-10-01 | 公开披露,CVE 预留并发布(VulnCheck),已在 v3.7.1 中修复 |
已负责任地披露给厂商,并通过 VulnCheck 进行协调。在本 PoC 发布之前已修复。出于防御和教育目的发布。