반응형
!! 현재 문제는 경북소프트웨어고등학교의 CTF 사이트에서 출제된 문제입니다.
문제는 참고만 부탁드립니다. !!
[문제]
const http = require('http')
const crypto = require('crypto')
const fs = require('fs')
const { clearSolution } = require('./hidden')
const user = {
STUDENT: {
orolsarang: {
password: '1234'
}
},
TEACHER: {
pmh_only: {
isAdmin: true,
password: createRandomPassword()
}
}
}
http
.createServer((req, res) => {
const url = new URL(req.url, `http://example.com`)
const type = url.searchParams.get('type')
const id = url.searchParams.get('id')
const password = url.searchParams.get('password')
if (url.pathname === '/create') {
res.setHeader('Content-Type', 'text/html;charset=utf-8')
if (user[type][id] !== undefined) {
res.end('<p>사용중인 아이디입니다.</p><p><a href="/">돌아가기</a></p>')
return
}
user[type][id] = { password }
res.end('<p>유저를 생성했습니다!</p><p><a href="/">돌아가기</a></p>')
}
if (url.pathname === '/flag') {
res.setHeader('Content-Type', 'text/html;charset=utf-8')
if (user[type][id] === undefined || user[type][id].password !== password) {
res.end('<p>없는 유저거나 비밀번호가 잘못되었습니다.</p><p><a href="/">돌아가기</a></p>')
return
}
if (!user[type][id].isAdmin) {
res.end('<p>관리자 권한이 없습니다.</p><p><a href="/">돌아가기</a></p>')
return
}
clearSolution()
res.end(`<p>Flag: <code>${getFlag()}</code></p>`)
}
if (url.pathname === '/') {
res.setHeader('Content-Type', 'text/html;charset=utf-8')
res.end(getIndex())
}
if (url.pathname === '/source') {
res.setHeader('Content-Type', 'text/plain;charset=utf-8')
res.end(getSource())
}
})
.listen(56030)
function createRandomPassword () {
return crypto.randomBytes(8).toString('hex')
}
function getFlag () {
return fs.readFileSync('./flag').toString('utf-8')
}
function getIndex () {
return fs.readFileSync('./index.html').toString('utf-8')
}
function getSource () {
return fs.readFileSync('./index.js').toString('utf-8')
}
[풀이]
이번 문제는 Prototype Pollution 공격 기법을 사용하여 푸는 문제이다.
공격방법은 인터넷에 찾으면 쉽게 찾아볼 수 있다.
소스코드를 보면
const user = {
STUDENT: {
orolsarang: {
password: '1234'
}
},
TEACHER: {
pmh_only: {
isAdmin: true,
password: createRandomPassword()
}
}
}
이러한 코드가 있다.
계정 정보를 담아 놓은 듯 하다.
orolsarang/1234로 제출하면 관리자 권한이 없다고 출력한다.
isAdmin이 True인 pmh_only로 시도해 보려면 password를 알아야 한다.
하지만 password는 랜덤으로 할당되어 확인할 수 없다.
그렇기에 나는 user.orolsarang에 어드민 권한을 넣어줄 것이다.
isAdmin을 True로 바꾸면 된다.
user[type][id] = { password }
url.pathnmae === '/create' 부분을 보면
위 코드를 확인할 수 있다.
이 부분을 프로토타입 폴루션 기법으로 공격한다면
user[__proto__][isAdmin] = { true }
이런 식으로 공격할 수 있다.
url 파라미터를 수정해서 공격한다.
정상적으로 공격이 성공했다.
제출하면 정상적으로 Flag 값을 얻을 수 있다.
[FLAG]
rceCTF{n0D3js_protOType_pol1uTion}
반응형