
إثبات مفهوم ومختبر لـ CVE-2026-75827، وهو ثغرة كتابة ملف عشوائي في Grav عبر Blueprint dynamic-data error_log، مع سكربت إعادة إنتاج ومختبر Docker.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · CVE-2026-75827
grav 2.0.13 — getgrav
يحتوي Grav قبل 2.0.15 على ثغرة كتابة ملفات عشوائية في التحقق من الدوال المجردة للبيانات الديناميكية في Blueprint، والتي تستخدم قائمة حظر غير كاملة بدلاً من قائمة سماح إيجابية. يمكن للمهاجمين الذين يمتلكون صلاحية تحرير الصفحات أو إعداد Blueprint استدعاء دالة error_log عبر توجيه بيانات لإلحاق حمولات PHP بملفات يمكن الوصول إليها عبر الويب، مما يحقق تنفيذ التعليمات البرمجية عن بُعد.
| CVE | CVE-2026-75827 · CVE.org |
| CWE | CWE-94 |
| CVSS | High: 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Product | grav |
| Affected | جميع الإصدارات حتى 2.0.13 (شاملة) |
| Patched | 2.0.15 وما بعده |
| Auth | لا يوجد (انظر خريطة المصدر) |
| Lab | 127.0.0.1 فقط · حزمة إفصاح للمورّد/العميل، وليست أداة فحص |
كتابة الملفات العشوائية تتم عبر error_log من خلال data-options@ في مخطط نموذج، وليس عبر إجراء upload action=. بروتوكول HTTP هو GET /poc-form ثم GET /poc-witness.txt.
GET/poc-formLab seed: admin user + Form plugin + page 03.poc-form with data-options@: error_logGET /poc-form → Form::getBlueprint() → Blueprint::dynamicData → isSafeDynamicCall('error_log') true → error_log(witness, 3, poc-witness.txt)GET /poc-witness.txt → POCWitness75827يحتوي جسم GET /poc-witness.txt على POCWitness75827. صفحة HTML الرئيسية أو خطأ 404 فارغ ليسا شاهداً على كتابة الملف.
افعل هذا أولاً: حدّث grav إلى 2.0.15 أو أحدث.
تحقق بعد الترقية
CVE-2026-75827-Abraxas-Labs.py مقابل البناء المُرقّع: يجب ألا يظهر الشاهد المُعيَّن.إذا لم تستطع التحديث فوراً
استهدف فقط http://127.0.0.1:8088 (أو عنوان loopback الذي ربطته). لا توجّه هذا السكربت إلى الإنترنت.
python3 CVE-2026-75827-Abraxas-Labs.py
النجاح هو الشاهد المذكور أعلاه في جسم الاستجابة. صفحة HTML عامة بحالة 200 ليست كذلك.
حزمة loopback المستخدمة لإعادة الإنتاج. صور رسمية ما لم يبنِ Dockerfile في هذا المجلد من المصدر.
cd lab
docker compose up --force-recreate
اربط شجرة المنتج المتأثر بجانب Compose إذا كان ملف YAML يربط دليلاً محلياً (ملف إضافة مضغوط / وسم المصدر من جدول الإصدارات). لا تنشر شيئاً باستثناء 127.0.0.1.
# CVE-2026-75827 (structured records)
- input: `https://nvd.nist.gov/vuln/detail/CVE-2026-75827`
- CWE: CWE-94
- published: 2026-08-18T12:19:32.553
## NVD description
Grav before 2.0.15 contains an arbitrary file write vulnerability in the Blueprint dynamic-data bare-function validation that uses an incomplete denylist instead of a positive allowlist. Attackers with page-edit or blueprint-config access can invoke the error_log function through a data directive to append PHP payloads to web-accessible files, achieving remote code execution.
## MITRE description
Grav before 2.0.15 contains an arbitrary file write vulnerability in the Blueprint dynamic-data bare-function validation that uses an incomplete denylist instead of a positive allowlist. Attackers with page-edit or blueprint-config access can invoke the error_log function through a data directive to append PHP payloads to web-accessible files, achieving remote code execution.
## Affected
- getgrav grav 0 affected, 2.0.15 unaffected
- OSV:
## References (JSON sources only)
- https://github.com/getgrav/grav/security/advisories/GHSA-f8wv-xp27-6gq7
- https://www.vulncheck.com/advisories/grav-before-arbitrary-file-write-via-error-log
- https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/75xxx/CVE-2026-75827.json
- https://nvd.nist.gov/vuln/detail/CVE-2026-75827
- https://github.com/advisories/GHSA-f8wv-xp27-6gq7
## GitHub advisory
Grav: Blueprint dynamic-data bare-function branch is denylist-gated and omits error_log, giving arbitrary file write
## Affected versions and vulnerable location
- Confirmed on grav core at `78ebfc1` (tag 2.0.13).
- Sinks:
- `system/src/Grav/Common/Data/Blueprint.php:455-458` `call_user_func_array($o, $params)` (bare-function dynamic-data provider).
- Twin: `system/src/Grav/Framework/Flex/FlexDirectory.php:936-938` `call_user_func_array($function, $params)`.
- Validation gate: `Blueprint::isSafeDynamicCall()` at `Blueprint.php:514-536`.
- `Class::method` branch (`:514-527`) uses a strict positive allowlist `self::$allowedDynamicCallables`.
- Bare-function branch (`:530-534`) uses only a denylist: `if (is_string($function) && Utils::isDangerousFunction($function)) return false; return !self::paramsContainDangerousCallable($params);`.
- Denylist: `Utils::isDangerousFunction()` (`system/src/Grav/Common/Utils.php`, list around `:2020-2270`).
## Root cause
GHSA-7pgq/CVE-2026-64850 hardened the `Class::method` half of the dynamic-callable validation to a positive allowlist because a page-edit account could otherwise name any static method as a provider and reach file/secret gadgets. The bare-function half was left on a denylist (`isDangerousFunction`). Any bare PHP function not on that list executes.
`error_log` is not on the denylist (verified: no occurrence in `Utils.php`). `error_log($message, 3, $destination)` appends attacker-controlled `$message` to attacker-controlled file `$destination`, an arbitrary-file-append primitive. `paramsContainDangerousCallable()` (`:587-603`) only scans params for dangerous callable strings, so a PHP payload string and a destination path both pass. (`stream_socket_client`, `dl`, and `mb_send_mail` are likewise absent, giving SSRF/other primitives.)
## Attacker model
The same surface the published dynamic-data advisories accept as reachable: a `data-*@` directive in a form blueprint the Form plugin assembles from page frontmatter (GHSA-fj2p), or a `data@` field in a Flex directory/pages/users blueprint (GHSA-c4wf). A page-edit / blueprint-config account, no shell.
## Reachability trace
1. Author a blueprint field with a bare-function data directive, e.g.
`data-options@: ['error_log', '<?php system($_GET[0]); ?>', 3, 'user/data/x.php']`.
2. `Blueprint::init()` resolves the directive; `isSafeDynamicCall('error_log', $params)` reaches the bare-function branch (`:530`), `isDangerousFunction('error_log')` is false, `paramsContainDangerousCallable([...])` is false (no callable strings),
هذه الحزمة مخصصة للمورّد، ومالك الموقع، والمختبرات المرخّصة. يتواصل السكربت مع 127.0.0.1. استخدامه ضد أنظمة لا تملكها غير مصرّح به من Abraxas Labs. لا ضمان.