
تحليل فني وإثبات مفهوم الاستغلال لـ CVE-2021-26084، وهي ثغرة حقن OGNL في خادم Atlassian Confluence. يتضمن تحليل السبب الجذري، تعيين المعلمات الضعيفة، ودليل الكشف.
نطاق التأثير
الإصدار < 6.13.23
6.14.0 ≤ الإصدار < 7.4.11
7.5.0 ≤ الإصدار < 7.11.6
7.12.0 ≤ الإصدار < 7.12.5
السبب وطريقة الاستغلال
يستخدم Confluence إطارًا لربط عناوين URL بفئات Java، مما ينتج ما يُسمى بـ "الإجراء". تنتهي عناوين URL الخاصة بالإجراءات بـ ".action" ويتم تعريفها في ملف xwork.xml في confluence-.jar وفي ملفات atlassian-plugin.xml داخل ملفات JAR للملحقات المرفقة. يحتوي كل إجراء على سمة name واحدة على الأقل تحدد اسم الإجراء، وسمة class تحدد فئة Java التي تنفذ الإجراء، وعنصر result واحد على الأقل يحدد قالب Velocity الذي سيتم عرضه بعد استدعاء الإجراء بناءً على نتيجته. القيم الشائعة التي يتم إرجاعها من الإجراءات هي "error"، "input"، "success"، ولكن يمكن استخدام أي نتيجة إذا تطابقت مع عنصر result في XWork XML. يمكن أن تحتوي الإجراءات على سمة method تسمح باستدعاء طريقة معينة من فئة Java المحددة. عندما لا يتم تحديد أمر، يتم استدعاء طريقة doDefault(). أدناه هو إدخال الإجراء لعملية createpage-entervariables:

تقوم طريقة doEnter() للفئة com.atlassian.confluence.pages.actions.PageVariablesAction بمعالجة الطلبات الواردة إلى doenterpagevariables.action وإرجاع القيم "error"، "input"، "success". يؤدي هذا إلى عرض قالب Velocity.
هنا، تتوافق قيمة سمة "name" لعنصر الإجراء مع مسار /.action ويتم عرض القالب الذي يحتوي على أخطاء/نجاح كجزء من الاستجابة. لذلك، وفقًا لهذا المثال، مجرد الوصول إلى /pages/doenterpagevariables.action سيعرض ملف قالب Velocity.

يمكننا رؤية كيفية عرض قالب Velocity في صفحة HTML

إدخال اسم العلامة في القالب كمعامل وملاحظة أن القيم يتم أخذها من معامل الطلب وإرجاعها في الاستجابة.

استخدام #tag : #tag ("attribute1"، "attribute2"، "attribute3")
يتم أخذ هذه السمات أثناء التقديم بواسطة AbstrctTagDirective.applyAttributes()

#tag ("Hidden" "name='queryString'" "value='ahihihi'")
بعد استخراج السمات بواسطة طريقة AbstrctTagDirective.applyAttributes()، يتم تمريرها إلى AbstrctUITag.doEndTag() AbstractUITag.evaluateParams()

ثم يتم تمريرها إلى WebWorkTagSupport.findValue() OgnlValueFinder.findValue() على شكل تعبير

ثم تمريرها إلى SafeExpressionUtil.isSafeExpression()

هنا، تم تمرير التعبير إلى compile، والتحقق من القائمة السوداء، ووضعه في ذاكرة التخزين المؤقت. بعد خطوة compile، يتم تجميعه إلى الشكل ASTConst الذي عند تقييمه سيعيد السلسلة التي تم تجميعها مسبقًا.

عند إضافة علامة الاقتباس المفردة "'" من الإدخال إلى التعبير، تم الهروب منها إلى شكل كيان HTML

نقطة الهروب موجودة في HtmlAnnotationEscaper.annotatedValueInsert()

هنا، يتم استدعاء طريقة ognl.JavaCharStream.readChar() وتقييم أحرف Unicode الهاربة، لذلك عند تمرير "\u0027" فإنه يحولها إلى "'". ومن ثم يمكن الهروب وإضافة تعبير OGNL

ولكن يجب تجاوز القائمة السوداء لـ OGNL على النحو التالي

يمكن تجاوزها باستخدام مصفوفة الوصول بدلاً من استخدام طريقة "getClass" أو الخاصية ".class".
queryString=aaa\u0027%2b#{\u0022\u0022[\u0022class\u0022]}%2b\u0027bbb

طريقة الاكتشاف
مراقبة جميع طلبات حركة HTTP حيث يحتوي مكون المسار من URI للطلب على إحدى السلاسل في عمود "مسار URI" من الجدول التالي:
مسار URI | المعلمات القابلة للاستغلال
/users/darkfeatures.action | featureKey
/users/enabledarkfeature.action | featureKey
/users/disabledarkfeature.action | featureKey
/login.action | token
/dologin.action | token
/signup.action | token
/dosignup.action | token
/pages/createpage-entervariables.action | queryString, linkCreation
/pages/doenterpagevariables.action | queryString
/pages/createpage.action | queryString
/pages/createpage-choosetemplate.action | queryString
/pages/docreatepagefromtemplate.action | queryString
/pages/docreatepage.action | queryString
/pages/createblogpost.action | queryString
/pages/docreateblogpost.action | queryString
/pages/copypage.action | queryString
/pages/docopypage.action | queryString
/plugins/editor-loader/editor.action | syncRev
إذا تم العثور على مثل هذا الطلب، فيجب فحص طريقة HTTP الخاصة بالطلب. إذا كانت طريقة الطلب هي POST، فابحث عن المعلمات القابلة للاستغلال المقابلة من الجدول أعلاه في نص طلب HTTP، وإذا كانت طريقة الطلب هي GET، فابحث عن المعلمات في URI-الطلب لطلب HTTP. افحص ما إذا كانت قيمة أي من المعلمات القابلة للاستغلال تحتوي على السلسلة "\u0027" أو شكلها المشفر URL. إذا كان الأمر كذلك، فسيتم اعتبار حركة المرور ضارة وقد يكون هجوم لاستغلال هذه الثغرة جاريًا.