
حذف متوقع للكود delete_code عبر rand() في PictShare < 3.7.1 (CWE-338). إثبات المفهوم + تقرير استشاري.
delete_code قابل للتنبؤ عبر rand() في PictShareبحث أمني مصرّح به. إثبات مفهوم (PoC) لأغراض دفاعية وتعليمية فقط.
يولّد PictShare رمز التفويض delete_code
عبر getRandomString()، الذي يستمد كل حرف من دالة rand() غير التشفيرية في PHP. ولأن
rand() ليست مولّد أرقام شبه عشوائية آمن تشفيريًا (CSPRNG) — ونفس المولّد ينتج تجزئة
الملف العامة الظاهرة في كل رابط مشاركة — فإن delete_code قابل للتنبؤ بدلًا من أن يكون
سرًّا، مما يسمح بحذف الملفات المستضافة دون تصريح ودون قراءة الرمز من نقطة النهاية info.
| CVE | CVE-2026-104356 |
| المنتج | PictShare (مضيف صور/وسائط مستضاف ذاتيًا) |
| المتأثر | >= 2.0.0، < 3.7.1 |
| تم الإصلاح في | v3.7.1 |
| الثغرة | استخدام مولّد أرقام شبه عشوائية ضعيف تشفيريًا (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 الذي يصرّح بالحذف.ولأن كلا الرمزين يأتي من نفس تدفق المولّد غير الآمن تشفيريًا، فإن المهاجم الذي يراقب
التجزئة العامة يحصل على معلومات حول حالة المولّد — ولم يعد delete_code يمتلك العشوائية
التي يوحي بها طوله البالغ 32 حرفًا. لا تحمل rand() أي ضمان بعدم قابلية التنبؤ
التشفيري، لذا فإن استخدامها لرمز أمني هو الخلل (CWE-338)، بغض النظر عن أي تقنية محددة
لاستعادة الحالة.
random_int().rand() تلقائيًا
(المرتبطة بمسار Mersenne-Twister) لكل عملية، لذا فإن أي متنبئ جاهز عن بُعد يعتمد على
النشر (إعادة استخدام العملية، عدد المخرجات القابلة للمراقبة، بناء PHP). لذلك فإن إثبات
المفهوم هذا يوضّح مبدأ قابلية التنبؤ بشكل حتمي في بذرة (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، الأملاح) باستخدام مولّد أرقام عشوائية آمن تشفيريًا
— random_int() / random_bytes() في PHP — وليس أبدًا rand() أو mt_rand() أو
uniqid().
ملاحظة: رموز الحذف الصادرة قبل الإصلاح لا يتم تدويرها، لذا تبقى الملفات المرفوعة قبل الإصلاح قابلة للتنبؤ حتى إعادة رفعها.
| التاريخ | الحدث |
|---|---|
| 2026-10-01 | إفصاح عام، حجز ونشر CVE (VulnCheck)، تم الإصلاح في v3.7.1 |
تم الإفصاح عنه بمسؤولية إلى المورّد والتنسيق عبر VulnCheck. تم الإصلاح قبل إصدار إثبات المفهوم هذا. نُشر لأغراض دفاعية وتعليمية.