コードのセキュリティ監査を実施したところ、コードはXML外部エンティティ(XXE)攻撃に対して脆弱であることがわかりました。
説明
XML外部エンティティ攻撃は、処理時にドキュメントを動的に構築するXML機能の恩恵を受けます。 XMLエンティティにより、特定のリソースからのデータを動的に含めることができます。外部エンティティにより、XMLドキュメントに外部URIからのデータを含めることができます。別の方法で構成されていない限り、外部エンティティは、XMLパーサーにURIで指定されたリソース(ローカルマシンまたはリモートシステム上のファイルなど)へのアクセスを強制します。この動作により、アプリケーションがXML外部エンティティ(XXE)攻撃にさらされ、ローカルシステムのサービス拒否の実行、ローカルマシン上のファイルへの不正アクセスの取得、リモートマシンのスキャン、およびリモートシステムのサービス拒否の実行が可能になります。 。
次のXMLドキュメントは、XXE攻撃の例を示しています。
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE foo [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
この例では、XMLパーサーがエンティティを/ dev/randomファイルの内容に置き換えようとすると、サーバー(UNIXシステム)がクラッシュする可能性があります。
勧告
XMLアンマーシャラーは、外部エンティティを着信XMLドキュメントの一部として許可しないように安全に構成する必要があります。
XXEインジェクションを回避するには、XMLソースを
Java.io.File
、Java.io.Reader
、またはJava.io.InputStream
として直接処理する非整列化メソッドを使用しないでください。安全に構成されたパーサーを使用してドキュメントを解析し、次の例に示すように、XMLソースとしてセキュアなパーサーを使用する非整列化メソッドを使用します。DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false); DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse(<XML Source>); Model model = (Model) u.unmarshal(document);
以下のコードは、監査でXXE攻撃が見つかった場所です。
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
System.out.println("outputing to : " + outputLocation);
File outputFile = new File(outputLocation);
StreamResult result = new StreamResult(outputFile);
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
上記の推奨事項をコードに実装するにはどうすればよいですか?どこに物が足りないの?
DocumentBuilderFactory
でも同じアプローチを使用できます。
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
...
全員がこれを自動的に使用できるようにするには、独自の実装を作成する必要があります(現在使用している実装を拡張し、デバッガを使用して調べます)。コンストラクターで機能を設定します。
次に、使用する新しいファクトリをシステムプロパティjavax.xml.parsers.DocumentBuilderFactory
でJava VMに使用すると、誰でも使用できます。
FEATURE_SECURE_PROCESSINGを単独で使用するだけでは十分ではないようです( blackhat-pdf から):
... Oracleの推奨にもかかわらず、FEATURE _SECURE_PROCESSINGが有効な場合、XMLパーサーは実際に外部接続を制限しません。
[〜#〜] owasp [〜#〜] ACCESS_EXTERNAL_DTDおよびACCESS_EXTERNAL_STYLESHEETを推奨します。
これにより、次のことが可能になります。
TransformerFactory trfactory = TransformerFactory.newInstance();
trfactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
trfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
実際、この質問は次の複製です: TransformerFactoryでのXML外部エンティティインジェクションを防ぐ方法
TransformerFactory
で安全な処理機能を有効にする必要があります。悪意のある特定の事態の発生を制限します(DOS攻撃など)。
TransformerFactory tf = TransformerFactory.newInstance();
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer transformer = tf.newTransformer();
Java 8
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>
そして、以下の例外がありました:
Caused by: org.xml.sax.SAXParseException: External Entity: Failed to read external document 'logs', because 'file' access is not allowed due to restriction set by the accessExternalDTD property.
市場には多数のXML解析エンジンがあるため、XXE攻撃を防ぐ方法はエンジンごとに異なります。エンジンのドキュメントを参照してください。ここでの基本は、外部DOCTYPE宣言を防ぐことです。外部のDOCTYPE宣言が必要な場合、外部の一般エンティティと外部パラメーターエンティティを無効にすると、コードに対するXXE攻撃を防ぐことができます。以下は、SAXパーサーを使用するときにXXEを防ぐためのサンプルコードです。
public class MyDocumentBuilderFactory{
public static DocumentBuilderFactory newDocumentBuilderFactory(){
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
try{
documentBuilderFactory.setFeature("http://Apache.org/xml/features/disallow-doctype-decl",true);
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities",false);
documentBuilderFactory.setfeature("http://xml.org/sax/features/external-parameter-entities",false)
}catch(ParserConfigurationException exp){
exp.printStackTrace();
}
return documentBuilderFactory;
}
}