
PictShare < 3.7.1 में rand() के माध्यम से अनुमानित delete_code (CWE-338)। PoC + सलाहकार लेख।
rand() के माध्यम से अनुमानित delete_codeअधिकृत सुरक्षा अनुसंधान। केवल रक्षात्मक और शैक्षिक उपयोग के लिए PoC।
PictShare delete_code प्राधिकरण टोकन को
getRandomString() के साथ उत्पन्न करता है, जो प्रत्येक वर्ण को PHP के गैर-क्रिप्टोग्राफिक
rand() से लेता है। चूँकि rand() एक CSPRNG नहीं है — और वही जनरेटर प्रत्येक साझा किए गए
URL में दिखाई देने वाला सार्वजनिक फ़ाइल हैश भी उत्पन्न करता है — delete_code गुप्त होने के
बजाय अनुमानित है, जिससे होस्ट किए गए फ़ाइलों को बिना कभी info endpoint से कोड पढ़े अनधिकृत रूप
से हटाया जा सकता है।
| CVE | CVE-2026-104356 |
| उत्पाद | PictShare (स्व-होस्टेड इमेज/मीडिया होस्ट) |
| प्रभावित | >= 2.0.0, < 3.7.1 |
| में ठीक किया गया | v3.7.1 |
| भेद्यता | क्रिप्टोग्राफिक रूप से कमज़ोर PRNG का उपयोग (CWE-338) → अनुमानित auth टोकन |
| विशेषाधिकार | कोई नहीं (अप्रमाणित) |
| 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) से प्रतिस्थापित करता है। सामान्य मार्गदर्शन: प्रत्येक
सुरक्षा टोकन (डिलीट कोड, रीसेट टोकन, API कुंजियाँ, साल्ट) को क्रिप्टोग्राफिक रूप से सुरक्षित
RNG से उत्पन्न करें — PHP में random_int() / random_bytes() — कभी rand(), mt_rand()
या uniqid() नहीं।
नोट: फिक्स से पहले जारी किए गए डिलीट कोड रोटेट नहीं किए जाते, इसलिए फिक्स-पूर्व अपलोड पुनः-अपलोड होने तक अनुमानित बने रहते हैं।
| दिनांक | घटना |
|---|---|
| 2026-10-01 | सार्वजनिक प्रकटीकरण, CVE आरक्षित और प्रकाशित (VulnCheck), v3.7.1 में ठीक किया गया |
विक्रेता को जिम्मेदारीपूर्वक प्रकट किया गया और VulnCheck के माध्यम से समन्वित किया गया। इस PoC के जारी होने से पहले ठीक किया गया। रक्षात्मक और शैक्षिक उद्देश्यों के लिए प्रकाशित।