
كاشف سلوكي لحالة التصحيح لثغرة Citrix NetScaler CVE-2026-8452. يرسل طلبات SAML مُعدّة خصيصًا لتحديد ما إذا كان فحص حجم قائمة PrefixList موجودًا، دون استغلال الذاكرة أو إتلافها.
فحص آمن وغير تدميري لحالة التصحيح لـ CVE-2026-8452، وهو تجاوز سعة الكومة قبل المصادقة
في مُطبيع توقيع SAML الخاص بـ Citrix NetScaler ADC / NetScaler Gateway
(CTX696604،
CVSS 8.8). تؤدي قائمة PrefixList كبيرة الحجم في التوحيد الحصري إلى تجاوز سعة مخزن ثابت الحجم أثناء
التطبيع، وهو ما ينفذه NetScaler قبل التحقق من التوقيع الذي يحملها — لذا
فإن المسار بأكمله يمكن الوصول إليه دون بيانات اعتماد، دون جلسة، ودون توقيع صالح. أُبلغ عنه مايكل
تاكر من فريق XOR في JPMorgan Chase؛ ويعود الفضل في تحليل السبب الجذري والاستغلال إلى
مختبرات watchTowr.
لا يستغل هذا السكربت الثغرة ولا يفسد الذاكرة. إنه يجيب عن سؤال واحد لكل هدف: هل التصحيح موجود على هذا الجهاز؟ — يُحدد سلوكيًا، عبر ملاحظة التصحيح بدلاً من تخمين الإصدار.
نعم. صُمم للاستخدام في الإنتاج والتقييم:
PrefixList بحجم 512 بايت وترفض 513 أو أكثر. تم تحديد هذا الحد بدقة البايت،
وهو مطابق في فرعي الدعم، ولا يتغير مع تكوين الجهاز أو
مع شكل رسالة SAML المحيطة — كما تأكد من خلال اختبار المسارين، اللذين يغلّفان القيمة
بكميات مختلفة جوهريًا من XML، وتبيّن أنهما يغيران السلوك عند نفس
البايت. 575 يتجاوز الحد بـ63 بايتًا، لذا لا يعتمد الحكم على كيفية إعداد الهدف
بالصدفة.PrefixList تحديدًا. تضخيم الحقول الأخرى لتتجاوزه — عناوين خدمة مستهلك التأكيد،
أسماء المُصدر، معرّفات الخوارزمية، قيم التلخيص والتوقيع — لا يغيّر شيئًا في إصدار مصلّح، لذا
فإن تطبيق الإصلاح لا ينبغي أن يتسبب في فشل تكوين SAML عامل.إذا عدّلت المسبار، فلا تغيّر
PROBE_PREFIXESولا تمسح الأطوال. 575 بايتًا أمر جوهري. يمكن لأطوالPrefixListالأخرى أن تزعزع استقرار الجهاز، في حالة واحدة على الأقل على إصدار يحمل هذا الإصلاح، لذا فإن مسح الأطوال ليس طريقة آمنة لاستكشاف هذه الثغرة، والأقصر ليس أكثر أمانًا.
الإصدارات المصلّحة ترفض PrefixList كبير الحجم بشكل نظيف، مع رسالة مميزة. الإصدارات غير المصلّحة
تعبر عبر المحلل وتُرجع خطأ داخليًا عامًا. طلب واحد متطابق،
إجابتان مختلفتان:
PrefixList بحجم 575 بايت | الاستجابة |
|---|---|
| غير مصلّح | 500 Internal Server Error 43549 |
| مصلّح | 200 Malformed Assertion sent to Netscaler |
يتم تجريب مسارين، مسار IdP أولاً، ويتوقفان بمجرد أن يعطي أحدهما إجابة. أي منهما كافٍ بمفرده، ويغطيان معًا دورَي SAML:
| المسار | الطلب | يتطلب |
|---|---|---|
| 1 (الأول) | POST /saml/login — AuthnRequest موقّع، PrefixList في ds:SignedInfo | سياسة SAML IdP مرتبطة بـ vserver المستهدف |
| 2 (احتياطي) | POST /cgi/samlauth — SAMLResponse، PrefixList في توقيع التأكيد | خدمة مستهلك تأكيد SAML SP على vserver المستهدف |
مسار IdP يأتي أولاً لأنه الأكثر متانة من الاثنين. إنه غير حساس لقيمة Issuer
ولـ AssertionConsumerServiceURL، ولانحراف الساعة — فقيمة IssueInstant خارج نطاق
تحمّل الجهاز لانحراف الساعة ما زالت تميّز بشكل صحيح، لأن التطبيع يسبق فحص
الوقت وكذلك فحص التوقيع.
يجب أن يكون طلب
AuthnRequestفي المسار 1 موقّعًا. الطلب غير الموقّع يُرجع200 Malformed Assertion sent to Netscalerعلى الإصدارات المصلّحة وغير المصلّحة، وهو ما يطابق إشارة المصلّح بايتًا ببايت، لذا فإن المسبار الذي يحذف كتلة التوقيع يبلّغ عن كل جهاز على أنه مصلّح. لا يلزم أن يكون التوقيع صالحًا، وتوقيع هذه الأداة ليس صالحًا؛ يكفي فقط أن يكون موجودًا، لأنSignedInfoالخاص به هو ما يحملPrefixListإلى المُطبيع.
يغيّر فرعا الدعم سلوكهما تمامًا عند إصدار الإصلاح، على كلا المسارين:
| الإصدار | الحكم | |
|---|---|---|
13.1-63.16 | آخر 13.1 معرّض للثغرة | VULNERABLE |
13.1-63.18 | أول 13.1 مُصلَّح | PATCHED |
14.1-66.59 | 14.1 معرّض للثغرة | VULNERABLE |
14.1-72.61 | أول 14.1 مُصلَّح | PATCHED |
13.1-63.16 و63.18 إصداران متتاليان، لذا يُعزى التغيير إلى التصحيح نفسه
وليس إلى الانجراف عبر الإصدارات الوسيطة.
تلك هي الإصدارات التي ظهر فيها هذا الإصلاح بالذات أولاً، ويكتشف المسبار هذا الانتقال بدقة.
لم تعُد هي الإصدارات التي يُنصح بالترقية إليها: فالنشرات اللاحقة استبدلتها، لذا فإن 13.1-63.18 و
14.1-72.61 يُجيبان بـ PATCHED هنا بينما يظلان معرّضين لمشكلات أحدث. انظر
الإصلاح لمعرفة الإصدارات المصلّحة الحالية.
لأنها لا يمكن أن تعمل مع هذه الثغرة، حتى من حيث المبدأ. 13.1-63.16 و13.1-63.18، الإصداران
اللذان يقعان مباشرة على جانبي الإصلاح، يخدمان tmindex.html وbase.css و
resources.js متطابقة بايتًا ببايت — فالإصلاح لا يمس أي أصل ويب. كما تتطابق تجزئات الأصول الثابتة عبر الفروع، لذا
يمكن لنهج قائم على التجزئة أن يحل جهازًا معرّضًا للثغرة إلى إصدار مصلّح ويُبلغ عنه كنظيف،
وهو أسوأ نمط فشل يمكن أن تتعرض له أداة كشف. لذلك، فإن أخذ بصمة الإصدار غير مُطبَّق عمدًا.
تأتي حالة التصحيح من المسبار، أو من show ns version حيث تتوفر لديك
بيانات اعتماد.
./cve_2026_8452_check.py https://gateway.example.com
./cve_2026_8452_check.py https://gateway.example.com:9443
./cve_2026_8452_check.py -f targets.txt --brief
./cve_2026_8452_check.py -f targets.txt --json > results.json
وجّه الأداة إلى **الخادم الافتراضي Gateway أو AAA**، وليس إلى واجهة الإدارة. الشرط المسبق ينطبق لكل خادم افتراضي، لذا فإن الجهاز الذي يحتوي على عدة VIPs يتطلب اختبار كل واحد منها.
### الخيارات
| الخيار | الوصف |
| --- | --- |
| `URL` | هدف واحد أو أكثر بصيغة `https://HOST[:PORT]` |
| `-f, --targets-file FILE` | قراءة الأهداف من ملف (هدف واحد لكل سطر؛ تعليقات `#`) |
| `-b, --brief` | سطر واحد محاذى لكل هدف — الحكم، الهدف، وسم السبب — لفحص العديد من المضيفين |
| `--json` | إخراج نتائج JSON منظمة |
| `--no-color` | تعطيل الإخراج الملون (يحترم أيضاً `NO_COLOR` وغير TTY) |
| `--timeout SECS` | مهلة زمنية لكل طلب (الافتراضي: 15) |
### أمثلة
**جهاز غير محدث،** استجاب على مسار IdP وتم تأكيده مقابل عنصر التحكم:```console
$ ./cve_2026_8452_check.py https://gateway.example.com:9443
====================================================================
CVE-2026-8452 - NetScaler SAML PrefixList patch-state check
https://gateway.example.com:9443
====================================================================
>> Identifying the appliance
[ OK ] NetScaler indicators: 5 (CSP contains citrixng://)
>> Probing patch state (64 prefixes / 575 bytes, confirmed against a 35-byte control)
idp /saml/login HTTP 500 / 43549: no size check present
idp /saml/login 35-byte control: HTTP 200 "message timestamp outside the appliance's skew tolerance": a different SAML condition, not the size check
[FAIL] Size check absent (via the IDP route)
====================================================================
RESULT: VULNERABLE
====================================================================