
Предсказуемый delete_code через rand() в PictShare < 3.7.1 (CWE-338). PoC + advisory writeup.
delete_code через rand() в PictShareАвторизованное исследование безопасности. PoC только для защитного и образовательного использования.
PictShare генерирует авторизационный токен delete_code
с помощью getRandomString(), который берёт каждый символ из некриптографического rand() в PHP.
Поскольку 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, который авторизует удаление.Поскольку оба токена происходят из одного и того же некриптографического потока PRNG, злоумышленник,
наблюдающий публичный хеш, получает информацию о состоянии генератора — delete_code больше не обладает
энтропией, которую предполагает его 32-символьная длина. rand() не даёт никаких гарантий
криптографической непредсказуемости, поэтому его использование для токена безопасности и является дефектом
(CWE-338), независимо от какой-либо конкретной техники восстановления состояния.
random_int().rand() (псевдоним пути Mersenne-Twister) для каждого процесса, поэтому готовый удалённый предсказатель
зависит от развёртывания (переиспользование процесса, количество наблюдаемых выходных данных, сборка PHP).
Поэтому данный PoC детерминированно демонстрирует принцип предсказуемости при контролируемом seed,
а не заявляет об универсальном одноразовом удалённом взломе. Это честный масштаб находки — и именно
поэтому вендор всё равно отнёсся к ней как к уязвимости и исправил её.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). Общее руководство: генерируйте каждый
токен безопасности (коды удаления, токены сброса, API-ключи, соли) с помощью криптографически стойкого
RNG — random_int() / random_bytes() в PHP — никогда не rand(), mt_rand() или uniqid().
Примечание: коды удаления, выданные до исправления, не ротируются, поэтому загрузки до исправления остаются предсказуемыми до повторной загрузки.
| Дата | Событие |
|---|---|
| 2026-10-01 | Публичное раскрытие, CVE зарезервирован и опубликован (VulnCheck), исправлено в v3.7.1 |
Ответственно раскрыто вендору и скоординировано через VulnCheck. Исправлено до выпуска этого PoC. Опубликовано для защитных и образовательных целей.