漏洞名称:
XML注入
描述:
可扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML是标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。发现目前一些普遍使用xml的场景中都存在一种古老的XML实体注入漏洞,这可能导致较为严重的安全问题,使得攻击者可能可以任意访问服务器以及应用所在网络的任何资源;
检测条件:
1.被测网站使用可扩展标记语言。
检测方法:
通过手工篡改网站中xml实体中的头部,加入相关的读取文件或者是链接,或者是命令执行等,如 file:///path/to/file.ext;http://url/file.ext;php://filter/read=convert.base64-encode/resource=conf.php,类似如下代码所示:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE nsfocus-sec [ <!ELEMENT methodname ANY > <!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <methodcall> <methodname>&xxe;</methodname> </methodcall>
篡改以后,如果可读取file文件或者达到植入的命令效果,则说明存在该漏洞。
XML主要的漏洞是XXE,但和它相关的漏洞不止这一个,比如:
1) XEE:XML Entity Expansion,主要试图通过消耗目标程序的服务器环境来进行DOS攻击;
2) XSLT:可扩展样式表转换漏洞,XSLT是XML的推荐样式表语言;
3) XPath注入漏洞,XPath用于浏览XML文档中的元素和属性,XSLT使用XPath来查找XML文档中的信息。
修复漏洞:
- 检查所使用的底层xml解析库,默认禁止外部实体的解析。
- 增强对系统的监控,防止此问题被人利用。
- 使用第三方应用代码及时升级补丁
- 对于PHP,由于simplexml_load_string函数的XML解析问题出在libxml库上,所以加载实体前可以调用这样一个函数以进行防护,参考代码: 对于XMLReader和DOM方式解析,可以参考如下代码:
<?php // with the XMLReader functionality: $doc = XMLReader::xml($badXml,'UTF-8',LIBXML_NONET); // with the DOM functionality: $dom = new DOMDocument(); $dom->loadXML($badXml,LIBXML_DTDLOAD|LIBXML_DTDATTR); ?>
5.禁用外部实体
6.手动黑名单过滤<!DOCTYPE、<!ENTITY SYSTEM、PUBLIC
其他补充:
先认识XML
XML有两个先驱——SGML(标准通用标记语言)和HTML(超文本标记语言),这两个语言都是非常成功的标记语言。SGML多用于科技文献和政府办公文件中,SGML非常复杂,其复杂程度对于网络上的日常使用简直不可思议。HTML免费、简单,已经获得了广泛的支持,方便大众的使用。而XML(可扩展标记语言)它既具有SGML的强大功能和可扩展性,同时又具有HTML的简单性。
XML 与 HTML 的主要差异
XML 被设计为传输和存储数据,其焦点是数据的内容。
HTML 被设计用来显示数据,其焦点是数据的外观。
HTML 旨在显示信息 ,而 XML 旨在传输信息。
然后认识DTD
文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
不过,XML对于标记的语法规定比HTML要严格地多
l 区分大小写
l 在标记中必须注意区分大小写,在XML中,<TEST>和<test>是两个截然不同的标记
l 要有正确的结束标记
l 结束标记除了要和开始编辑在拼写和大小上完全相同,还必须在前面加上一个斜杠“/”
l 若开始标记<test>,结束标记则为</test>。XML严格要求标记配对,HTML中的<br>、<hr>的元素形式在XML中是不合法的。当一对标记之间没有任何文本内容时,可以不写结束标记,在开始标记的末尾加上斜杠”/”来确认,例如:<test /> 这样的标记被称为“空标记”。
l 标记要正确嵌套
l 在一个XML元素中允许包含其他XML元素,但这些元素之间必须满足嵌套性
l 有效使用属性
l 标记中可以包含任意多个属性。在标记中,属性以名称/取值对出现,属性名不能重复,名称与取值之间用等号“=”分隔,且取值用引号引起来。
l 举个例子:<衣服 品牌=“耐克” 类型=“T恤” >
XML基础XML声明:<?xml version="1.0" encoding="utf-8" ?>
内部DTD声明:<!DOCTYPE 根元素名称 [元素声明]>
在DTD中定义属性:<!ATTLIST 元素名 (属性名 属性类型 缺省值)*>
外部实体声明:<!ELEMENT 实体名称 SYSTEM “URI/URL”>
xml格式说明
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。DTD 可以在 XML 文档内声明,也可以外部引用。
(1)内部声明DTD
<!DOCTYPE 根元素 [元素声明]>
(2)引用外部DTD
<!DOCTYPE 根元素 SYSTEM "文件名">
或者
<!DOCTYPE 根元素 PUBLIC "public_ID" "文件名">
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
---------------------------------------------------------
什么是实体
再看下面一个DTD:
很容易理解,它规定了xml文件的根元素是foo,但ANY说明接受任何元素。重点是!ENTITY,这就是我们要提到的实体,实体本质是定义了一个变量,变量名xxe,值为“test”,后面在 XML 中通过 & 符号进行引用,所以根据DTD我们写出下面的xml文件:
因为ANY的属性,元素我们可以随意命令,但user值通过&xxe,实际值为test。
什么是外部实体
知道了什么是实体,再说说其实实体分为两种,内部实体和外部实体,上面的例子就是内部实体。XML外部实体是一种自定义实体,定义位于声明它们的DTD之外,声明使用SYSTEM关键字,比如加载实体值的URL:
这里URL可以使用file://协议,因此可以从文件加载外部实体。例如:
这也是产生XXE漏洞的原因。
xml外部实体注入,全称为XML external entity injection,某些应用程序允许XML格式的数据输入和解析,可以通过引入外部实体的方式进行攻击。
在后期会讲到XXE。