簡體   English   中英

如何預防XXE攻擊

[英]How to prevent XXE attack

我們對代碼進行了安全審核,並提到我們的代碼容易受到XML EXternal Entity(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.Filejava.io.Readerjava.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);
...

為了使每個人都自動使用此功能,您需要創建自己的實現(通過擴展當前使用的實現;使用調試器進行查找)。 在構造函數中設置功能。

然后,您可以將要在System屬性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;
 }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM