
Exclusão previsível de delete_code via rand() no PictShare < 3.7.1 (CWE-338). PoC + relatório de advisory.
delete_code previsível via rand() no PictSharePesquisa de segurança autorizada. PoC apenas para uso defensivo e educacional.
O PictShare gera o token de autorização
delete_code com getRandomString(), que obtém cada caractere do rand() não
criptográfico do PHP. Como o rand() não é um CSPRNG — e o mesmo gerador produz o
hash público do arquivo exibido em cada URL compartilhada — o delete_code é previsível
em vez de secreto, permitindo a exclusão não autorizada de arquivos hospedados sem nunca
ler o código a partir do endpoint de informações.
| CVE | CVE-2026-104356 |
| Produto | PictShare (host de imagens/mídia auto-hospedado) |
| Afetado | >= 2.0.0, < 3.7.1 |
| Corrigido em | v3.7.1 |
| Vulnerabilidade | Uso de PRNG Criptograficamente Fraco (CWE-338) → token de autenticação previsível |
| Privilégios | Nenhum (não autenticado) |
| 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 |
| Descoberto por | Alisher Qarshibayev |
| Advisory | 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;
}
Esta única função produz ambos:
delete_code que autoriza a exclusão.Como ambos os tokens vêm do mesmo fluxo não-CSPRNG, um atacante que observa o hash público
obtém informações sobre o estado do gerador — o delete_code deixa de ter a entropia que
seu comprimento de 32 caracteres sugere. O rand() não oferece nenhuma garantia de
imprevisibilidade criptográfica, portanto usá-lo para um token de segurança é o defeito
(CWE-338), independentemente de qualquer técnica específica de recuperação de estado.
random_int().rand() (alias para o caminho Mersenne-Twister) por processo, então um preditor remoto
pronto para uso depende da implantação (reutilização de processo, número de saídas
observáveis, build do PHP). Este PoC, portanto, demonstra o princípio de previsibilidade
de forma determinística em uma semente controlada, em vez de alegar uma quebra remota
universal de um único disparo. Esse é o escopo honesto da descoberta — e é exatamente por
isso que o fornecedor ainda a tratou como uma vulnerabilidade e a corrigiu.demo.php reproduz exatamente o getRandomString() do fornecedor e mostra que, uma vez que
o estado do PRNG é conhecido/recuperado, a primeira saída (o hash público) determina
completamente a segunda saída (o delete_code) — ou seja, observar o hash prevê o código:
php demo.php
Saída esperada:
[*] 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)
Veja demo.php. É autocontido (sem servidor, sem rede) e prova o
determinismo hash→código que torna o rand() inadequado aqui.
Atualize para o PictShare 3.7.1 (commit de correção ce5fc47),
que substitui rand() por random_int() (CSPRNG). Orientação geral: gere todo token de
segurança (códigos de exclusão, tokens de redefinição, chaves de API, salts) com um RNG
criptograficamente seguro — random_int() / random_bytes() em PHP — nunca rand(),
mt_rand() ou uniqid().
Nota: códigos de exclusão emitidos antes da correção não são rotacionados, então uploads anteriores à correção permanecem previsíveis até serem reenviados.
| Data | Evento |
|---|---|
| 2026-10-01 | Divulgação pública, CVE reservado e publicado (VulnCheck), corrigido na v3.7.1 |
Divulgado de forma responsável ao fornecedor e coordenado através da VulnCheck. Corrigido antes do lançamento deste PoC. Publicado para fins defensivos e educacionais.