
phpMyAdmin 5.2.3 - عالي - عن بُعد - XSS - Designer Visual Query Builder
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-vqb-xss
التقرير: https://abraxaslabs.tech/research/phpmyadmin-vqb-xss
الفئة: XSS مخزّن الوصول: عن بُعد
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
js/src/designer/history.js يبني سجل الاستعلام المرئي باستخدام innerHTML. أسماء الأعمدة تمر عبر $('<div/>').text(...).html(). أسماء الجداول لا تمر. TableName ما زال يسمح بـ < و >. حساب ذو صلاحيات منخفضة يملك CREATE TABLE على قاعدة بيانات مشتركة يزرع معرّف HTML. عندما يفتح مستخدم ذو صلاحيات أعلى المصمم، يكون getTableName() موجودًا في الصفحة ويقوم DesignerHistory.display() بكتابته في #ab.
XSS مخزّن في أصل phpMyAdmin. نفس فئة PMASA-2025-1، لكن بميزة مختلفة. عناوين جداول الفحص كانت مُهرَّبة. هذا المسار لم يكن كذلك.
| المعرّف | لا يوجد CVE بعد |
| الفئة | XSS مخزّن |
| الوصول | عن بُعد (مصادقة CREATE TABLE؛ الضحية يفتح المصمم) |
| CWE | CWE-79 |
| CVSS | مرتفع: 8.0 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N |
| المنتج | phpMyAdmin |
| المتأثر | 5.2.3 الوسم RELEASE_5_2_3 (962857e4f63d42e38f11ff4d63f5e722018add76) |
| المصادقة | مطلوبة. المهاجم يحتاج CREATE TABLE على قاعدة بيانات يفتحها الضحية في المصمم |
| الترخيص | GNU Affero GPL v3.0 |
| المختبر | 127.0.0.1 فقط |
زرع اسم جدول HTML، ثم انتظار مستخدم ذي صلاحيات أعلى لفتح المصمم على قاعدة البيانات تلك وعرض سجل الاستعلام المرئي.
| الصلاحية | الطريقة / المصرف | الاستطلاع / السلامة / التوافر | مثبت معمليًا أم مستنتج |
|---|---|---|---|
| حقن ترميز في أصل phpMyAdmin | DesignerHistory.display() يدمج getTab() في #ab innerHTML | سلامة أصل الضحية | مثبت معمليًا. history.js مباشر على phpmyadmin:5.2.3. <h3> احتوى <i id="pma-vqb"> |
الخروج من خاصية table_name في المصمم | database_tables.twig small_tab_pref_1 يستخدم designerTable.getTableName() | استطلاع اسم MySQL الخام في DOM المصمم | مثبت معمليًا قابل للقراءة كمعرّف خام |
قراءة كوكي جلسة الضحية ورمز CSRF token | سكربت من نفس الأصل بمجرد عرض السجل | استطلاع جلسة PMA الخاصة بالضحية | مستنتج من XSS المخزّن في أصل PMA. هذا المختبر يستخدم علامة <i>، وليس سكربتًا |
| تشغيل SQL، إدارة المستخدمين، التصدير، كحساب MySQL الخاص بالضحية | POST مدعوم بالرمز /sql، /server/privileges، تصدير | سلامة كل ما يمكن لحساب MySQL ذلك لمسه | مستنتج. نفس فئة التأثير مثل PMASA-2025-1 |
| تغيير 2FA / إعدادات المستخدم | POST /config/set كالضحية | سلامة مخزن تفضيلات الضحية | مستنتج. بقايا شقيقة، ليست هذا المختبر |
أُغلق على هذه البقايا: الوصول غير المصادق، RCE على نظام التشغيل، ومسار زر OK في VQB. .small_tab_pref_click_opt يهرّب مسبقًا table_name وTwig يهرّبه تلقائيًا مرة أخرى، لذا تلك النقرة حاليًا تغذي كيانات إلى getTab(). هذا ليس إصلاحًا لـ history.js. خلايا الأعمدة تبقى مُهرَّبة نصيًا (c<b id=pma-col>y، بدون عقدة <b id="pma-col">).
نفس التثبيت: بقايا WebAuthn CustomServer.
ثبّتُّ phpMyAdmin RELEASE_5_2_3. PMASA-2025-1/2/3 موجودة بالفعل في 5.2.2. المصمم ما زال يبني HTML سجل VQB يدويًا.
js/src/designer/history.js (يُشحن كـ js/dist/designer/history.js):
temp = historyArray[i].getTab();
str += '<h3 class="tiger"><a href="#">' + temp + '</a></h3>';
// ...
'<td width="175" style="padding-left: 5px">' + $('<div/>').text(historyArray[i].getColumnName()).html() + '<td>';
libraries/classes/Dbal/TableName.php يتحقق فقط من أن الاسم غير فارغ، وبحد أقصى 64 حرفًا، وبدون مسافة في النهاية. < و > مسموحان. يقبلهما MySQL داخل معرّف محاط بعلامات اقتباس.
templates/database/designer/database_tables.twig ينسخ designerTable.getTableName() إلى table_name على .small_tab_pref_1. تستخدم خلية خيار VQB نسخةً مُهرَّبة مسبقًا من الاسم نفسه.
مسارات خاطئة سُجّلت بالفعل: التعامل مع سمة زر الخيار المزدوجة التهريب على أنها الإصلاح (وهي ليست كذلك - لا يزال small_tab_pref_1 يكشف الاسم الخام، وhistory.js هو نقطة الوصول)؛ والتعامل مع مساعد العمود على أنه يغطي أسماء الجداول؛ والادعاء بوجود XSS غير مصادَق عليه؛ وصدفة عكسية. مسرح.
python3 phpmyadmin-vqb-xss-Abraxas-Labs.py
# or: cd lab && ./run.sh
استهدف فقط http://127.0.0.1:19250. الصور phpmyadmin:5.2.3 و mysql:8.0. مشروع Compose phpmyadmin-vqb-xss. Playwright Chromium في خدمة poc. يتم تفكيك الحزمة بعد التشغيل.
مستخدمان، shareddb مشتركة. المستخدم منخفض الصلاحيات creator ينفّذ CREATE TABLE \tx` (`cy` INT). المستخدم الأعلى صلاحيات victimيسجّل الدخول إلى phpMyAdmin ويفتح Designer معquery=1. ملف history.js المباشر هو النسخة من الحاوية (h3-unescaped=yes، ومساعد العمود موجود). يستدعي Chromium الدالة DesignerHistory.display()باسم الجدول منgetTableName()` في الصفحة.
النتيجة: #ab h3.tiger innerHTML هو <a href="#">t<i id="pma-vqb">x</i></a>. نص td الخاص بالعمود هو c<b id=pma-col>y دون وجود عقدة b#pma-col.
SUCCESS phpmyadmin-vqb-xss h3-markup=yes col-escaped=yes how=live PMA-VQB-XSS-WITNESS
قم بتهريب getTab() باستخدام $('<div/>').text(temp).html() أو Functions.escapeHtml قبل دمجها في <h3>. لا تعتمد على الترميز المزدوج لـ Twig لسمة واحدة. احتفظ بمساعد اسم العمود كنموذج.
962857e4f63d42e38f11ff4d63f5e722018add76)js/src/designer/history.jslibraries/classes/Dbal/TableName.phpGNU Affero GPL v3.0. راجع LICENSE. مختبر الاسترجاع المحلي فقط. دون أي ضمان.