1、漏洞描述:
可扩展标记语言(Extensible Markup Language, XML),用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML是标准通用标记语言(SGML)的子集,非常适合Web传输。XML提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。XML注入攻击,和SQL注入的原理一样,都是攻击者输入恶意的代码来执行自身权限以外的功能。
XML是存储数据的一种方式,如果在修改或者查询时,没有做转义,直接输入或输出数据,都将导致XML注入漏洞。攻击者可以修改XML数据格式,增加新的XML节点,对数据处理流程产生影响。
2、检测条件:
被测网站使用可扩展标记语言。
3、检测方法
看一个保存注册用户信息为XML格式的例子:
final String GUESTROLE = "guest_role";
...
//userdata是准备保存的xml数据,接收了name和email两个用户提交来的数据。
String userdata = "<USER role="+GUESTROLE+">
<name>"+request.getParameter("name")+"</name>
<email>"+request.getParameter("email")+"</email>
</USER>";
//保存xml
userDao.save(userdata);
可以看到,这段代码没有进行任何的过滤操作。一个普通用户注册后,会产生这样一条数据记录:
<?xml version="1.0" encoding="UTF-8"?>
<USER role="guest_role">
<name>user1</name>
<email>[email protected]</email>
</USER>
攻击者输入自己email时,可以输入如下代码:
[email protected]</email></USER><USER role="admin_role"><name>lf</name><email>[email protected]
最终用户注册后,数据就变成了:
<?xml version="1.0" encoding="UTF-8"?>
<USER role="guest_role">
<name>user1</name>
<email>[email protected]</email>
</USER>
<USER role="admin_role">
<name>lf</name>
<email>[email protected]</email>
</USER>
可以看到,多出了一条role=“admin_role”的管理员lf。达到攻击目的。
插入元字符
单引号: 当未被过滤时,如果被注入的值是标签属性值的一部分,该字符会在XML解析过程中引发异常。<node attrib=’foo’’> //注意是一边是两个单引号。
双引号: 和单引号同义。
尖括号: 实现开放或闭合。<username>foo<</username>
注释标签: <!--/-->。注释的开始和结尾。<username>foo<!--</username>
与符号: &。在XML算法中表示实体。<username>&foo</username> //新节点被创建但文档无效
CDATA区段分隔符: <![CDATA[/]]>。如<username><! [CDATA [/] ]></username> //无效XML片段
4、修复方案:
1、常见的XML解析方法有:
DOMDocument、SimpleXML、XMLReader,这三者都基于libxml库解析XML,所以均受影响;xml_parse函数则基于expact解析器,默认不载入外部DTD,则不受影响。可以在php解析xml文件之前使用libxml_disable_entity_loader(true)来禁止加载外部实体(该方法对上述三种XML解析组件都有效),并使用libxml_use_internal_errors()禁止报错。
2、对关键字符串进行转义:
& --> &
< --> <
> --> >
" --> "
' --> '
3、在XML保存和展示之前,对数据部分,单独做转义即可:
String userdata = "<USER role="+GUESTROLE+">
<name>"+StringUtil.xmlencode(request.getParameter("name"))+"</name>
<email>"+StringUtil.xmlencode(rrequest.getParameter("email"))+"</email>
</USER>";