
Eliminazione prevedibile di delete_code tramite rand() in PictShare < 3.7.1 (CWE-338). PoC + analisi dell'advisory.
delete_code prevedibile tramite rand() in PictShareRicerca di sicurezza autorizzata. PoC solo per uso difensivo ed educativo.
PictShare genera il token di autorizzazione
delete_code con getRandomString(), che preleva ogni carattere dal rand() non
crittografico di PHP. Poiché rand() non è un CSPRNG — e lo stesso generatore produce
l'hash pubblico del file mostrato in ogni URL condiviso — il delete_code è prevedibile
anziché segreto, consentendo la cancellazione non autorizzata dei file ospitati senza mai
leggere il codice dall'endpoint info.
| CVE | CVE-2026-104356 |
| Prodotto | PictShare (host di immagini/media self-hosted) |
| Affetto | >= 2.0.0, < 3.7.1 |
| Corretto in | v3.7.1 |
| Vulnerabilità | Uso di PRNG crittograficamente debole (CWE-338) → token di autorizzazione prevedibile |
| Privilegi | Nessuno (non autenticato) |
| 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 |
| Scoperto da | 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;
}
Questa singola funzione produce entrambi:
delete_code che autorizza la cancellazione.Poiché entrambi i token provengono dallo stesso flusso non-CSPRNG, un attaccante che osserva
l'hash pubblico ottiene informazioni sullo stato del generatore — il delete_code non ha più
l'entropia che la sua lunghezza di 32 caratteri suggerisce. rand() non offre alcuna garanzia
di imprevedibilità crittografica, quindi usarlo per un token di sicurezza è il difetto
(CWE-338), indipendentemente da qualsiasi specifica tecnica di recupero dello stato.
random_int().rand() (alias del percorso Mersenne-Twister) per processo, quindi un predittore remoto
pronto all'uso dipende dal deployment (riutilizzo del processo, numero di output osservabili,
build di PHP). Questo PoC pertanto dimostra il principio di prevedibilità in modo
deterministico in un seed controllato, anziché rivendicare una compromissione remota
universale in un colpo solo. Questo è l'ambito onesto della scoperta — ed è esattamente il
motivo per cui il vendor l'ha comunque trattata come una vulnerabilità e l'ha corretta.demo.php riproduce l'esatta getRandomString() del vendor e mostra che, una volta noto/recuperato
lo stato del PRNG, il primo output (l'hash pubblico) determina completamente il secondo
output (il delete_code) — cioè osservando l'hash si predice il codice:
php demo.php
Output atteso:
[*] 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)
Vedi demo.php. È autonomo (nessun server, nessuna rete) e dimostra il
determinismo hash→codice che rende rand() inadatto in questo caso.
Aggiornare a PictShare 3.7.1 (commit di correzione ce5fc47),
che sostituisce rand() con random_int() (CSPRNG). Indicazione generale: generare ogni
token di sicurezza (codici di cancellazione, token di reset, chiavi API, salt) con un RNG
crittograficamente sicuro — random_int() / random_bytes() in PHP — mai rand(),
mt_rand() o uniqid().
Nota: i codici di cancellazione emessi prima della correzione non vengono ruotati, quindi gli upload precedenti alla correzione rimangono prevedibili fino al nuovo upload.
| Data | Evento |
|---|---|
| 2026-10-01 | Divulgazione pubblica, CVE riservato e pubblicato (VulnCheck), corretto in v3.7.1 |
Divulgato responsabilmente al vendor e coordinato tramite VulnCheck. Corretto prima del rilascio di questo PoC. Pubblicato per scopi difensivi ed educativi.