国外的一个xss challenge(规定时间内做出可得一年的Burp Suite正版证书)
主要的功能逻辑代码为script.js, 如下:
var hash = document.location.hash.substr(1); if(hash){ displayReason(hash); } document.getElementById("reasons").onchange = function(e){ if(e.target.value != "") displayReason(e.target.value); } function reasonLoaded () { var reason = document.getElementById("reason"); reason.innerHTML = unescape(this.responseText); } function displayReason(reason){ window.location.hash = reason; var xhr = new XMLHttpRequest(); xhr.addEventListener("load", reasonLoaded); xhr.open("GET",`./reasons/${reason}.txt`); xhr.send(); }
代码逻辑为:
通过触发location.hash的变化来调用displayReason函数,通过ajax请求得到./reasons/${reason}.txt,然后把response的内容返回给id为reason的标签。
首先测试了下直接在URL的锚部分写上xss语句
这里可以看到这个404的页面,在response时不仅对特殊字符进行了编码处理,而且还会将%替换为_,所以直接通过xss语句触发是没戏了。
接下来尝试了一下.htaccess等403页面的触发,看下对应的response内容有没有经过处理
可以看到,在403的response中我们的xss语句是完整存在的,那么接下来只需要把这个xss带到我们之前的页面就可以触发xss了
进行尝试
这里需要注意两个地方
最终访问效果如下:
可以看到img标签成功被解析。
不过此时仍然没法弹窗,因为这个challenge是有csp进行限制的,csp规则如下:
default-src 'self';
限制了资源必须来自此站点
那么接下来就开始寻找一些可以当成js来执行的地方,我们可以通过之前的404页面返回的内容来当作我们的js语句,并且通过script标签的src属性进行引入,唯一需要注意的是要进行单引号的闭合
构造语句如下:
在控制台执行一下
成功触发,接下来把这个返回内容作为外部js引入就可以了
不过不能直接在response里面直接返回script标签,因为这里的赋值是
reason.innerHTML = unescape(this.responseText);
通过innterHTML产生的script标签并不可以执行
所以这里可以用iframe的srcdoc属性去解决这个问题,payload如下:
<iframe/srcdoc='<script src="x%27-alert(document.domain)-%27"></script>'>
将上面的payload二次编码后,放进location.hash
成功触发xss