Pentester Lab是一款老外编写的Web渗透练习环境。
XML是一种可扩展标记语言,可以理解为HTML的扩展语言,一般用于数据存储、数据传输、数据共享,其中DTD文档来解释XML文档。XML必须包含根元素,所有的标签都要闭合,对大小写敏感,并且属性值需要加引号。
XML注入即XXE(XML外部实体注入),是指利用可控的参数或入口来加载不可控的参数或代码,造成不可控的运行结果。
ENTITY实体:如果在XML文档中需要频繁使用某一条数据,可以预先给这个数据起一个别名。即一个ENTITY,然后再在文档中调用它。
XML定义了两种类型的ENTITY,一种在XML文档中使用,另一种在为参数在DTD文件中使用。
定义语法: ] >
定义好的ENTITY在文档中通过“&实体名;”来使用。
正常来说,DTD分为内部DTD与外部DTD,内部DTD包含在XML文档中,外部DTD则通过URL引用。一个DTD文件是以.dtd结尾的文本文件 。前面还要加上SYSTEM,但是如果此处没有任何过滤,我们完全可以引用系统敏感文件的,前提是页面有回显,否则你只引用了文件但不知道文件内容。
漏洞产生原因:Xfire使用了STAX解析XML导致XML实体注入发生。
1、直接引入XML外部实体
2、未加任何过滤直接parse
漏洞危害:
1、任意文件读取:通过外部实体引用,可以获取文件内容
2、URL请求,SSRF
3、DoS
4、远程代码执行:在PHP开启expect扩展的前提下
源码:
simplexml_load_string() 函数转换形式良好的XML字符串为SimpleXMLElement对象。
print_r()可以把字符串和数字简单地打印出来。
访问该页面:
先尝试构造进行简单的输出:
出现报错,然后换为URL编码后的再进行测试:
没问题,正常输出。
接着直接运行payload:
xml=]>
可以看到passwd文件被成功读取了。
也可以扫描内网主机端口:
源码:
list()函数用于在一次操作中给一组变量赋值。
each()函数返回当前元素的键名和键值,并将内部指针向前移动。
xpath()函数运行对XML文档的XPath查询。
可以看到源代码先定义了一个$x变量,里面包含了一个xml。然后把的XML字符串转换为SimpleXMLElement对象,并赋值给$res,然后查询了users里user里的name值为$name的,并返回其所有父节点的message里面的值。然后执行查询,最后while循环显示查询的值。
整个XML格式如下:
hacker
Hello hacker
pentesterlab
admin
Hello admin
s3cr3tP4ssw0rd
可以看到,用户名和密码都保存在该XML文件中,即可以利用XML注入漏洞来获取保存在该XML文件中的敏感信息,途径是通过xpath语句。
提取出关键的xpath语句:$xpath = "users/user/name[.='".$_GET['name']."']/parent::*/message";
然后尝试注入该xpath语句,其中注释符使用%00:
没有正常显示,发现语句写到中括号外面了,改过来即可:
可以看到正常显示。
接着换成or语句看看是否显示所有内容:
可以看到全部显示出来。
接着,查看是否存在子节点:
一样的显示,即不存在子节点。注:child::node()查询当前节点的所有子节点。
接着查询当前节点兄弟节点的所有数据:
至此,已经将保存在XML文件中的敏感数据都读取了出来,为了使输出更好看,就只输出密码字段的内容:
盲测:判断request的XML请求是否被解析,可以根据请求头中的“SOAP”字段来判断,也可以根据错误返回中有“SAX”字样。
漏洞挖掘总结:一般为Xfire开发的或者某些wsdl结尾的文件。
1、Service为Xfire
2、明显的XML作为内容的输入点
3、某些以JSON格式的Request
1、禁用外部实体
2、过滤和验证用户提交的XML数据
3、不允许XML中含有任何自己声明的DTD
4、有效的措施:配置XML parser只能使用静态DTD,禁止外来引入;对于Java来说,直接设置相应的属性值为false即可