首页 > 技术文章 > XXE漏洞

happystudyhuan 2019-10-31 23:39 原文

代码注入(Code injection):

  1.OWASP将其定义为在客户端提交的代码在服务器端接收后当做动态代码或嵌入文件处理。

  2.Wikipedia将其定义为客户端所提交的数据未经检查就让Web服务器去执行,这个范围比OWASP定义的代码注入范围要广阔得很多。

 

XML实体注入漏洞:

  XXE漏洞全称XML External Entity Injection即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等危害。xxe漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。

  XXE漏洞是针对使用XML交互的Web应用程序的攻击方法,在XXE漏洞的基础上,发展出了Blind XXE漏洞。目前来看,XML文件作为配置文件(Spring、Struts2等)、文档结构说明文件(PDF、RSS等)、图片格式文件(SVG header)应用比较广泛,此外,网上有一些在线XML格式化工具也存在过问题。

1、本质:

  XML是一种数据组织存储的数据结构方式,安全的XML在用户输入生成新的数据时候应该只能允许用户接受的数据,需要过滤掉一些可以改变XML标签也就是说改变XML结构插入新功能(例如新的账户信息,等于添加了账户)的特殊输入,如果没有过滤,则可以导致XML注入攻击。

 

XML格式说明:

  XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。

  DTD(文档类型定义)的作用是定义XML文档的合法构建模块。DTD可以在XML文档内声明,也可以外部引用。

(1)内部声明DTD

<!DOCTYPE 根元素 [元素声明]>

 (2)引用外部DTD

<!DOCTYPE 根元素 SYSTEM "文件名">

或<!DOCTYPE 根元素 PUBLIC "public_ID" "文件名">

DTD实体用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。

 (3)DTD的实体

  DTD(文档类型定义)的作用是定义XML文档的合法构建模块。DTD可以在XML文档内声明,也可以外部引用。

  外部实体是值XML处理器必须解析的数据。它对于在多个文档之间创建共享的公共引用很用用。对外部实体进行的任何更改将在包含对其的引用的文档中自动更新。即XML使用外部实体将信息或“内容”将自动提取到XML文档的正文中。为此,我们需要在XML文档内部声明一个外部实体。

内部声明实体

  DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。一个内部实体声明  <!ENTITY 实体名称 “实体的值">

  注释:一个实体由三部分构成:一个和号(&),一个实体名称,以及一个分号(;)。

引用外部实体

  一个外部实体声明<!ENTITY 实体名称 SYSTEM "URI/URL“>或者<!ENTITY 实体名称 PUBLIC "public_ID" "URI">

  外部实体类型有:

 

(4)CDATA

  CDATA指的是不应由XML解析器解析的文本数据(Unparsed Character Data)。在XML元素中,"<"(新元素的开始)和“&”(字符实体的开始)是非法的。某些文本,比如javascript代码,包含大量“<"或”&“字符。为了避免错误,可以将脚本代码定义为CDATA。CDATA部分中的所有内容都会被解析器忽略。CDATA部分由"<![CDATA["开始,由”]]>"结束。

 

XML的实体

  XML中的实体分为以下五种:字符实体,命名实体,外部实体,参数实体,内部实体。普通实体和参数实体都分为内部实体和外部实体两种,外部实体定义需要加上SYSTEM关键字,其内容是URL所指向的外部文件实际的内容。如果不加SYSTEM关键字,则为内部实体,表示实体指代内容为字符串。

(1)字符实体

  指用十进制格式(&#aaa;)或十六进制格式(&#xaaa;)来指定任意Unicode字符。对于XML解析器而言,字符实体与直接输入指定字符的效果完全相同。

(2)命名实体

  也称为内部实体,在DTD或内部子集(即文档中<!DOCTYPE>语句中的一部分)中声明,在文档中用作引用。在XML文档解析过程中,实体引用将由它的表示替代。

 

图上 POC可以用作xxe+ssrf

(3)外部实体(XXE主要是利用了DTD引用外部实体导致的漏洞)

  外部实体表示外部文件的内容,用SYSTEM关键词表示。

  <!ENTITY test SYSTEM "1.xml">

  有些XML文档包含system标识符定义的“实体”,这些文档会在DOCTYPE头部标签中呈现。这些定义的‘实体’能够访问本地或者远程的内容。比如,下面的XML文档样例就包含了XML‘实体’。

 

   在上面的代码中,XML外部实体‘entityex’被赋予的值为:file://etc/passwd。在解析XML文档的过程中,实体'entityex'的值会被替换为URI(file:///etc/passwd)内容值(也就是passwd文件的内容)。关键字‘SYSTEM’会告诉XML解析器,‘entityex’实体的值将从其后的URI中读取,并把读取的内容替换entityex出现的地方。

  假如SYSTEM后面的内容可以被用户控制,那么用户就可以随意替换为其他内容,从而读取服务器本地文件(file:///etc/passwd)或者远程文件(http://www.baidu.com/abc.txt)

(4)参数实体

  参数实体只用于DTD和文档的内部子集中,XML的规范定义中,只有在DTD中才能引用参数实体,参数实体的声明和引用都是以百分号%。并且参数实体的引用在DTD是理解解析的,替换文本将变成DTD的一部分。该类型的实体“%”字符(或十六进制编码的%),并且仅在经过解析和验证后才用于替换DTD中的文本或其他内容:

 

 <!ENTITY % 实体名称 “实体的值”>

或者<!ENTITY % 实体名称 SYSTEM "URI">

参数实体只能在DTD文件中被引用,其他实体在XML文档内引用。即下面实例,实体参数在DOCTYPE内,其他实体在外

 

 参数实体在DTD中解析优先级高于xml内部实体,实体相当于变量“file:///etc/passwd"赋值给name

(5)内部实体

 

 (6)命名实体+外部实体写法

 

 这种命名实体调用外部实体,发现evil.xml中不能定义实体,否则解析不了。

(7)第一种命名实体+外部实体+参数实体写法

 

 (8)第二种命名实体+外部实体+参数实体写法

 

 调用过程和第一种方法类似

 

XXE的危害:

  1、读取任意文件

  2、执行系统命令

  3、探测内网端口

  4、攻击内网网站

  5、拒绝服务

POC

 

 

XXE漏洞类型:

1.基础的XXE注入——外部实体注入本地DTD

 

 

 

 

2.基于盲注的XXE注入——XML解析器在响应中不显示任何错误

(1)Blind XXE用途

  对于传统的XXE来说,要求有一点,就是攻击者只有在服务器有回显或者报错的基础上才能使用XXE漏洞来读取服务器端文件。例如:

提交请求:

 

   服务器在这个节点中返回etc/passwd的文件内容:

  <username>root:1:3......</username>

  如果服务器没有回显,只能使用Blind XXE漏洞来构建一条带外信道提取数据。

  如果目标服务器没有回显,就只能用Blind XXE了。原理就是带着获取的文件源码以get参数或其他形式去访问我们的服务器,然后再日志里就可以找到我们要获取的内容了。

  Blind XXE主要使用了DTD约束中的参数实体和内部实体。参数实体是一种只能再DTD中定义和使用的实体,一般引用时使用%作为前缀。而内部实体是指在一个实体中定义的另一个实体,也就是嵌套定义。

原理说明:

  对于传统的XXE来说,要求在服务器有回显或者报错的基础上才能使用XXE漏洞来读取服务器端文件,例如上述方式一。如果服务器没有回显,只能使用Blind XXE漏洞来构建一条带外信道提取数据(Out-Of-Band)。但直接在内部实体定义中引用另一个实体的这种方法行不通。

  最简单的无非是通过参数实体引用,发送一个http请求到我们的服务器,然后观察我们服务的日志,如果在服务日志上能接收到则说明存在漏洞。

  但是这样做行不通,原因是不能在实体定义中引用参数实体,即有些解释器不允许在内层实体中使用外部连接,无论内层是一般实体还是参数实体。

  解决方案:将嵌套的实体声明放入到一个外部文件中,这里一般是放在攻击者的服务器上,这样做可以规避错误。

思路:

(1)客户端发送payload 1给web服务器

(2)web服务器向vps获取恶意DTD,并执行文件读取payload2

(3)web服务器带着回显结果访问VPS上特定的FTP或者HTTP

(4)通过VPS获得回显(nc监听端口)

3.基于错误的XXE注入——成功解析之后,XML解析器始终显示SAME响应。(即”您的消息已被接收“),因此,我们可能希望解析器将文件的内容”打印“到错误响应中。

 

 

判断是否存在XXE漏洞:

 

 

测试:

1.任意文件读取

任意读取的代码:

 

 2)无回显的情况:可以看第一种命名实体+外部实体+参数实体写法和第二种命名实体+外部实体+参数实体写法

  访问http://localhost/test.php,这就是模拟攻击者构造XXE请求,然后存在漏洞的服务器会读出file的内容(c:/1.txt),通过带外通道发送给攻击者服务器上的1.php,1.php做的事情就是把读取的数据保存到本地的1.txt中,完成Blind XXE攻击。可以从apache的日志中看到。

  另外,数据不回显就没有问题了吗?不,可以把数据发送到远程服务器。

 

 

 修复漏洞:

 

 

Xpath注入:

本质:xpath注入是类似SQL的一种从XML结构中搜索节点数据的语言(DSL),其注入方式就是构造完整的可执行的DSL,本质与SQL注入一样。

  Xpath即为XML路径语言,Xpaht基于XML的树形结构,提供在数据结构树中找寻节点的能力。简单的说,Xpath就是选取XML节点的一门语言。

  如果程序没有验证用户查询输入,就会发生Xpath注入,攻击者可以提交恶意的请求修改查询语句,导致:事物逻辑和认证绕过,获取后端XMl数据库内容。

  不像传递的关系型数据库,可以对数据库、表、行或者列执行细粒度的访问控制,XML没有用户或者权限的概念。这意味着整个数据库都可以被用户读取,在应用中属于很严重的安全漏洞。

 

 

 

 防御方法:

 

 

JSON注入:

 

 

 

 

 CRLF注入:

  CRLF是“回车+换行”(\r\n)的简称。在HTTP协议中,HTTP Header与HTTP Body是用两个CRLF分隔的,浏览器就是根据这两个CRLF来取出HTTP内容并显示出来。所有,一旦我们能够控制HTTP消息头中的字符,注入一些恶意的换行,这样我们就能注入一些会话Cookie或者HTML代码,所有CRLF Injection又叫HTTP Response Splitting,简称HRS。

1、本质

  也叫CRLF注入攻击。CR、LF分别对应回车(%0d)、换行(%0a)字符。HTTP头由很多被CRLF组合分离的行构成,每行的结构都是“键:值”。如果用户输入的值部分注入了CRLF字符,它就有可能改变HTTP报头结构。

2、防御

  限制用户输入的CR和LF,或者对CR和LF字符正确编码后再输出

  过滤\r、\n之类的换行符,避免输入的数据污染到其他HTTP头。

 

 

HPP(参数污染):

  HPP参数污染不是一个漏洞,而是服务器端根据配置的不同所显示出的不同特性。如果网站存在SQL注入或者是XSS等漏洞,并且有响相应的防护措施,那么HTTP参数污染可能会帮助攻击者绕过这些防御措施。

  HPP参数污染,简单地讲就是给一个参数赋上两个或两个以上的值。现行的HTTP标准没有提及再遇到多个输入值给相同的参数赋值时应该怎样处理。因此web程序组件在遇到这类问题时采取的方法也不完全相同。

 

 

 

 防御:

 

推荐阅读