이 글은 아래 글을 번역한 후 이해를 바탕으로 작성한 글입니다.

https://book.hacktricks.xyz/pentesting-web/deserialization/nodejs-proto-prototype-pollution

 

NodeJS - __proto__ & prototype Pollution - HackTricks

function (container, depth0, helpers, partials, data) { return ((stack1 = (lookupProperty(helpers, "undefined") || (depth0 && lookupProperty(depth0, "undefined")) || container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}

book.hacktricks.xyz

 


1. Prototype?

C++, java 같은 객체지향언어에는 class라는 개념이있다.

하지만 javascript 에는 class 대신 prototype을 쓴다.

한마디로 자바스크립트에서 prototype == class  인셈 

 

 

2. Prototype의 기본

 

1.

function person(fullName, age) {
    this.age = age;
    this.fullName = fullName;
    }
var person1 = new person("test", 70);

 

* 함수.prototype 은 함수 본체만 사용 가능하고, 함수.__proto__ 는 함수에 의해 생성된 객체에 사용하는 것이다.

 ( 편의를 위해 함수 본체를 모체함수로 명명하고, 본체 함수로 부터 생성된 객체는 생성함수라고 하겠다.)

* 함수 본체는 바뀌지 않는다.

 

 

2.

* 모체함수.prototype.변수명을 써서 변수를 추가하면 이미 만들어진 객체에도 추가가 된다.

* 객체를 찍어보면 추가한 변수는 나오지 않지만(myFriend1 에 "gender"라는 변수가 x)  실제로 값을 찍어보면 값이 들어있다.(myFriend1.gender = male 이 나온다.)

 

 

3.

function person(fullName) {
    this.fullName = fullName;
}
var person1 = new person("Satoshi");

person1.__proto__.__proto__.printHello = function(){console.log("Hello");}
person1.printHello() 

var person2 = new person("test");

person2.printHello()

* 물론 다음과 같이 생성함수.__proto__.변수명 으로도 오염시킬 수 있다.

* 예시에선 왜 __proto__를 두번씩 썼는지 모르지만 실제로는 한번만 써도 됨

 

 

4.

function person(fullName) {
    this.fullName = fullName;
}
var person1 = new person("Satoshi");

person.prototype.sayHello = function(){console.log("Hello");}
person.prototype.newConstant = true

person1.__proto__.sayHello = function(){console.log("Hello");}
person1.__proto__.newConstant = true

person1.__proto__["sayHello"] = function(){console.log("Hello");}
person1.__proto__["newConstant"] = true

person1.constructor.prototype.sayHello = function(){console.log("Hello");}
person1.constructor.prototype.newConstant = true

* 위에 코드는 전부 같은 말이다. 특정 단어가 필터링 된다고 생각할때 유동적으로 쓰면 된다.

 

 

5.

* 헷갈리면 안되는게 prototype 은 함수 뿐만이 아니다.

* 위와 같이 Object.protptype.변수명 을 정해놓으면 모든 객체가 변수명을 가지게 된다.

 

 

 

> 취약점 점검 사례

1. highcharts 취약한 버전에서의 prototype pollution

 

highcharts 9.0.0 이하의 버전애서 prototype pollution 취약점이 존재함

let obj = JSON.parse('{"__proto__" :{"polluted":"yes"}}');
Highcharts.merge({}, obj);
document.write('Polluted : ' + polluted);

- 출처 : https://security.snyk.io/vuln/SNYK-JS-HIGHCHARTS-1018906

 

 

1.1 점검 방법

해당 npm 모듈이 깔려 있는 홈페이지 개발자도구 console 에서 상단에 있는 poc를 입력

 

1.2 결과

홈페이지가 Polluted : yes 로 바뀜

 

 

해당 취약점은 server에서 나오는게 아닌 client 단에서 발생하는 취약점이라 DOS, XSS의 취약점이 존재 할 수 있음.

홈페이지에서 차트를 표시할 때 사용자입력을 받아 사용한다면 그 부분을 이용해서 RCE 등 더 영향력이 강한 취약점을 발생시킬 수 있음.

만약 사용자 입력을 받지 않는다면 취약 라이브러리 사용으로 잡는다.

 

 


 

출처:

- Prototype Pollution XSS POC (Vue.js, Google Analytics 등)

https://github.com/BlackFan/client-side-prototype-pollution

 

- Prototype Pollution 이해

https://www.neuralegion.com/blog/prototype-pollution/

 

- Prototype Pollution 이해 2

https://research.securitum.com/prototype-pollution-and-bypassing-client-side-html-sanitizers/

 

- 특정 템플릿 사용시 Prototype Pollution을 이용한 RCE (Handlebars, Pug)

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

 

- 실제 사례를 기반으로 설명

https://slides.com/securitymb/prototype-pollution-in-kibana/#/64

복사했습니다!