
wp2shell (CVE-2026-63030 & CVE-2026-60137) - سلسلة RCE كاملة
إثبات مفهوم مستقل لثغرة حقن SQL عبر الالتباس في مسارات REST batch غير المصادق عليها في ووردبريس، والمرتبطة بنشرة wp2shell الأمنية الصادرة عن Searchlight Cyber.
هذا المستودع ليس أداة الفحص الرسمية لـ Searchlight Cyber. يؤكد أمر check مسار حقن SQL، ويوضح read قراءة قاعدة البيانات، بينما يفتح shell غلاف أوامر مدعومًا بإضافة، إما ببيانات اعتماد مسؤول مقدَّمة أو عبر تفعيل جسر SQLi-to-admin أولًا.
تدرج نشرة Searchlight Cyber الأمنية نطاقات التعرض لثغرة تنفيذ الأوامر (RCE) في wp2shell كما يلي:
| نطاق الإصدار | الحالة |
|---|---|
| <= 6.8.5 | غير متأثر |
| 6.9.0 – 6.9.4 | متأثر |
| 7.0.0 – 7.0.1 | متأثر |
نقطة نهاية REST batch (/batch/v1) غير مصادق عليها وتنفّذ عدة طلبات فرعية في استدعاء واحد، معتمدةً على أن كل طلب فرعي يُتحقق منه وتُفحص صلاحياته بشكل مستقل.
تبني الدالة serve_batch_request_v1() مصفوفتين متوازيتين — $matches (المعالِج المُطابَق لكل طلب فرعي) و$validation (نتيجة التحقق لكل طلب فرعي) — ثم تفهرس كلتيهما بالإزاحة نفسها عند التوزيع. أي طلب فرعي يفشل مساره في wp_parse_url() يُلحق بـ $validation دون $matches، فتفقد المصفوفتان التزامنهما ويُوزَّع طلب فرعي تحت معالِج طلب فرعي مختلف. هذا هو التباس المسار.
يُداخل إثبات المفهوم الآلية الأساسية مرتين:
POST /wp/v2/posts يحمل جسم requests تحت معالج الدفعة نفسه. وبما أنه جرى التحقق منه كطلب posts، لا تُفحص قائمة requests الخاصة به أبدًا مقابل مخطط الدفعة، لذا يمكن لطلباته الفرعية استخدام GET — أي أن القائمة البيضاء للطرق يتم تجاوزها.GET /wp/v2/posts/999999 معاملات استعلام لمجموعة المنشورات مثل author_exclude وorderby وper_page. لا يلزم أن يكون المعرّف 999999 موجودًا؛ فهو مجرد معرّف منشور غير مرجّح يُستخدم لمطابقة مسار العنصر، الذي لا يتحقق مخططه من تلك المعاملات المخصصة للمجموعة فقط. ثم يوزّع عدم التزامن الطلب نفسه تحت get_items() للمنشورات، حيث يُربط author_exclude بمتغير استعلام author__not_in في WP_Query، الذي تدرجه النسخة الهشّة في استعلام SQL كنص.النتيجة هي حقن SQL أعمى قائم على الاستجابة المنطقية والزمن، ويمكن الوصول إليه قبل المصادقة. يتضمن إثبات المفهوم هذا أيضًا آلية UNION للمنشور المزوّر المستخدمة في سلسلة SQLi-to-admin.
مسار تنفيذ الأوامر (RCE) المنفَّذ هنا هو:
wp_posts مزوّرة عبر UNION لعرض محتوى يتحكم به المهاجم من خلال مجموعة منشورات. يستخدم جسر العرض مصدر مسار العنصر /wp/v2/posts/999999 — وهو نفس المسار الذي تستخدمه قراءة SQLi للوصول إلى get_items().POST /wp/v2/users، منشئًا مسؤولًا مولّدًا.الخطوات من 1 إلى 5 تتم قبل المصادقة؛ أما خطوة تنفيذ الأمر فهي رفع إضافة عبر مسؤول مصادَق عليه.
Python 3.8+ والمكتبة القياسية. لا توجد تبعيات خارجية.
شغّله من دليل المستودع:
./wp2shell.py <command> <url> [options]
أو pip install . للحصول على أمر wp2shell في PATH الخاص بك.
يطبع أولًا مؤشرات ووردبريس السلبية وتلميحات الإصدار العامة، ثم يرسل استكشاف مؤشرات دفعة غير ضار. تعيد أي نسخة هشّة من تنفيذ الدفعة HTTP 207 مع نمط مؤشرات التباس المسار parse_path_failed وblock_cannot_read وrest_batch_not_allowed.
يستند استكشاف المؤشرات إلى الإصلاح الأساسي في ووردبريس. يُنشئ الطلب المشوّه /// الخطأ parse_path_failed؛ ويعمل طلب /wp/v2/posts كفاصل مسموح به في الدفعة؛ ومسار /wp/v2/block-renderer/... غير مسموح به في الدفعة لكنه يعيد block_cannot_read إذا وُصل إلى معالجه دون مصادقة؛ ويعطي /batch/v1 الخطأ rest_batch_not_allowed. في النسخ الهشّة، يُزيح خطأ التحليل مصفوفتي معالجات الدفعة عن التزامنهما، فيُوزَّع طلب الفاصل تحت معالج block-renderer. أما النسخ المصلَحة فتُبقي المصفوفتين متزامنتين، لذا لا ينبغي أن يظهر نمط المؤشرات الثلاثة جميعًا هذا للاستكشاف المُصمَّم.
افتراضيًا، يتوقف check عند هذا الحد ولا يرسل حمولة SQLi. استخدم --confirm-sqli عندما تريد أيضًا تأكيدًا فعّالًا لحقن SQL. يحاول التأكيد أولًا آلية قراءة UNION، ويتحول إلى استكشافات زمنية مقترنة إذا لم تكن انعكاسات UNION متاحة.
الإشارات مستقلة عن بعضها: تلميح الإصدار مجرد تلميح، ونمط المؤشرات يُظهر التباس المسار، و--confirm-sqli يُظهر وصول حمولة إلى قاعدة البيانات. يمكن لجدار حماية تطبيقات الويب (WAF) حظر الحمولة، لذا فإن فشل التأكيد لا يُثبت غياب الثغرة.
./wp2shell.py check http://target
./wp2shell.py check targets.txt # scan every URL in the file
./wp2shell.py read http://target # server fingerprint
./wp2shell.py read http://target --preset users # user logins and password hashes
./wp2shell.py read http://target --query "SELECT @@version"
افتراضيًا يكون الاستخراج بـ --technique auto، الذي يجرب الطرق المتاحة بالترتيب التالي:
WP_Post عبر UNION ويقرأ عنوانه من استجابة REST بصيغة ||HEX(value)||. تستخدم الحمولة نفس مسار المصدر /wp/v2/posts/999999 مع orderby=none وper_page=500 حتى يبقى الصف المزوّر منشورًا معروضًا. طلب واحد لكل قيمة.EXTRACTVALUE/UPDATEXML نحو 15 بايت لكل طلب، عندما يعكس الهدف أخطاء MySQL (مثل تفعيل WP_DEBUG_DISPLAY).X-WP-Total لمجموعة المنشورات كإشارة صواب/خطأ ولا يحتاج إلى أي قيمة منعكسة.افرض إحداها باستخدام --technique union|error|blind. مسارات القراءة هذه لا تكتب صفوفًا في قاعدة البيانات.
مع --user و--password، يسجّل shell الدخول ببيانات اعتماد المسؤول المقدَّمة ويستخدم سلوك رفع الإضافات في ووردبريس.
بدون بيانات اعتماد، يشغّل shell أولًا جسر SQLi-to-admin قبل المصادقة، ويسجّل الدخول كمسؤول مولّد، ثم يرفع غلاف الإضافة.
./wp2shell.py shell http://target --user admin --password '<recovered>' --cmd id
./wp2shell.py shell http://target --user admin --password '<recovered>' -i # interactive shell
./wp2shell.py shell http://target --cmd id # pre-auth bridge
./wp2shell.py shell http://target -i # pre-auth interactive
يرفع shell غلاف ويب كإضافة (مقفلًا خلف مسار عشوائي ورمز مميز لكل تشغيل) ويطبع مساره. ويتم حذف غلاف الويب المرفوع تلقائيًا. وعندما يُنشئ جسر ما قبل المصادقة مسؤولًا، يُحذف ذلك الحساب المولّد تلقائيًا بعد انتهاء جلسة الغلاف.
حدّث إلى ووردبريس 7.0.2، أو إلى 6.9.5 إذا كان الموقع على فرع 6.9. وإلى ذلك الحين، احجب كلاً من /wp-json/batch/v1 ومعامل الاستعلام rest_route=/batch/v1 على مستوى الحافة، أو اشترط المصادقة لنقطة نهاية الدفعة عبر مرشح rest_pre_dispatch.
لأغراض اختبار الأمان المصرَّح به فقط. استخدمه حصريًا ضد أنظمة تملكها أو لديك إذن كتابي صريح لاختبارها. لا تُقدَّم أي ضمانات، ولا يُقبل أي التزام قانوني عن سوء الاستخدام.
| الخيار | ينطبق على | الوصف |
|---|
--proxy URL | all | وجّه حركة المرور عبر وكيل HTTP (مثل Burp). |
--timeout N | all | مهلة الطلب بالثواني. |
--sleep N | check | التأخير المستخدم في خيار التوقيت الاحتياطي لـ --confirm-sqli. |
--samples N | check | أزواج التوقيت المستخدمة في خيار التوقيت الاحتياطي لـ --confirm-sqli. |
--confirm-sqli | check | يرسل أيضًا حمولة تأكيد فعّالة لحقن SQL. |
--preset | read | fingerprint أو users. |
--technique | read | auto (افتراضي)، union (ضمن النطاق — يزوّر منشورًا مزيّفًا)، error (ضمن النطاق — يتطلب أخطاء قاعدة بيانات ظاهرة)، أو blind. |
--query | read | تعبير SQL عددي للقراءة. |
--prefix | read | بادئة جدول قاعدة البيانات (الافتراضي wp_). |
--max-length N | read | الحد الأقصى للأحرف المقروءة لكل قيمة (الافتراضي 128). |
--user / --password | shell | بيانات اعتماد مسؤول اختيارية؛ احذفهما معًا لاستخدام جسر ما قبل المصادقة. |
--cmd | shell | الأمر المراد تشغيله (احذفه عند استخدام -i). |
-i / --interactive | shell | يفتح غلافًا تفاعليًا بعد النشر. |