XXE セキュリティ脅威は現在「No」です。 OWASP の Web アプリケーション セキュリティ脅威トップ 10 のリストでは 4 位にランクされているため、Java 標準 XML ライブラリがそのような攻撃を防ぐことができると期待しています。ただし、Sonar が推奨する方法で Validator クラスを使用すると、「XML パーサーは XXE 攻撃に対して脆弱であってはなりません (java:S2755)」というルールが適用されます。 (ルールへのリンク):
String xsd = "xxe.xsd";
String xml = "billionlaughs.xml";
StreamSource xsdStreamSource = new StreamSource(xsd);
StreamSource xmlStreamSource = new StreamSource(xml);
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(xsdStreamSource);
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
// validators will also inherit of these properties
Validator validator = schema.newValidator();
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // Compliant
StringWriter writer = new StringWriter();
validator.validate(xmlStreamSource, new StreamResult(writer));
Java 11 では、billionLaugh.xml が使用されます
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
次の例外が発生します:
Exception in thread "main" org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; JAXP00010001: The parser has encountered more than "64000" entity expansions in this document; this is the limit imposed by the JDK.
at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204)
at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:178)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:400)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:284)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1413)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1337)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEntityReference(XMLDocumentFragmentScannerImpl.java:1842)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2982)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:534)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:888)
at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:824)
at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.StreamValidatorHelper.validate(StreamValidatorHelper.java:176)
at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:115)
at trial.Trial.main(Trial.java:35)
そこで私の質問は、これが 10 億笑い攻撃を軽減する正しい方法と考えられるかどうかです (結局のところ、エンティティ拡張には 64000 の制限があります)。それとも、XML 解析を単に参照しないように設定する別の方法があるのでしょうか。 <!DOCTYPE ..>セクション。
パーサーは代わりに何ができるでしょうか?
– ヘンリー2020 年 9 月 3 日 11:24
@Henry は <!DOCTYPE ..> を無視します。必要に応じてセクションを参照してください。
– ジョン・ドン2020 年 9 月 3 日 11:25
stackoverflow.com/q/46282711 と重複している可能性があります
– マルコノ12342020 年 9 月 3 日 14:18
OWASP トップ 10 エントリと SonarSource ルールはどちらも XML 外部エンティティに関するものですが、「Billion Laughs」は XML 外部エンティティに関するものです。攻撃は XML 内部エンティティを使用して構築されます。内部エンティティは次のように定義されます。
[...] 個別の物理ストレージ オブジェクトはなく、エンティティの内容は宣言で指定されます。
Java では、少なくとも Java 1.5 以降、現在発生しているエンティティ拡張制限が適用されています。
ただし、それでも推奨される緩和策は必要です。XML 外部エンティティ攻撃から保護します。 OWASP サイトまたは SonarSource ルールで提供されている例の 1 つを使用して、これを自分でテストできます。たとえば、バリデーターで以下を検証させます (OS が Linux であると仮定します)。
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>
その後、コードで StringWriter ライターの値を出力させます。軽減策を適用しないと、/etc/passwd ファイルの内容が含まれていることがわかります。
OWASP XML 外部エンティティ防止チートシートで説明されているように、場合によっては、DTD (ドキュメント タイプ定義) を完全に無効にして、外部エンティティと内部エンティティの両方を禁止することもできます。
1
わかりました。重要なのは、10 億笑い攻撃は XXE ではないということです。 「...場合によっては、DTD を完全に無効にすることもできます。」 - バリデーターでそれを行う方法がわかりません。
– ジョン・ドン2020 年 9 月 3 日 16:32