본문 바로가기
Web/개념정리

[개념정리] Prototype Pollution

by jh117jh 2024. 6. 5.
728x90

Prototype 이란

자바스크립트에서 모든 객체들이 메서드와 속성을 상속받기 위한 객체

 

객체를 생성할 때 기본적으로 상속되며 여러 메소드를 포함한다. 새로운 인스턴스가 생성될 때, 생성된 인스턴스는

상위 객체의 프로토타입을 상속받아 생성되고, 인스턴스의 상위 객체 또한 더 위의 상위 객체로부터 프로토타입

객체를 상속받아 생성되는데 이렇게 프로토타입 객체를 상속받고 또 상속받는 것을 '프로토타입 체인'이라고 한다.

prototype-pollutions이란

North Sec 2018, 보안 연구자 Olivier Arteau의 “Prototype pollution attacks in NodeJS applications“라는 발표를 했다.

공격자가 JS언어 고유의 프로토타입 체인 동작 원리를 이용해 웹 서버를 공격하는 방법을 prototype-pollutions이라 한다.

 

 

상위 객체에서 상속되어 오는 프로토타입을 사용자가 접근하여 내용을 변경하거나 임의의 내용을 추가하면 그것은 하위 객체에도 그대로 상속되게 된다.

 

이러한 성질을 이용해여 객체 리터럴의 __proto__ Object.prototype과 같다는 것을 이용해 다른 객체 속성에 영향을 주는 방식이다.

 

 

function Person(height,weight){
    height:height;
    weight:weight;
};

a = new Person();
a.__proto__.weight = 123;
console.log(a.weight); //123
b = new Person();
console.log(b.weight); //123

//a의 prototype 객체 조작으로 아무 관계없는 b의 속성값 변경

 

위 코드를 보면 Person라는 object함수를 선언하면 Prototype.Object가 같이 선언된다.

 

이렇게 생성된 함수는 prototype이라는 속성을 통해  Prototype Object에 접근할 수 있고

Prototype Object의 속성 중 __proto__를 통해 함수 객체와 연결되어 있다.

 

그다음 a라는 객체를 생성하면 a의 __proto__속성은 Person Prototype에 연결되고

다른 b라는 객체를 생성한 후 __proto__ 값을 조작할 수 있다면 a, b의 속성값들을 변경할 수 있다.

 

논문에 나온 Prototype Pollution이 일어나는 3가지 경우는

속성 설정, 객체 병합, 객체 복사가 있다.

 

속성 설정

function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}
 
function setValue(obj, key, value) {
  const keylist = key.split('.');
  const e = keylist.shift();
  if (keylist.length > 0) {
    if (!isObject(obj[e])) obj[e] = {};
    setValue(obj[e], keylist.join('.'), value);
  } else {
    obj[key] = value;
    return obj;
  }
}
 
const obj1 = {};
setValue(obj1, "__proto__.polluted", 1);
const obj2 = {};
console.log(obj2.polluted); // 1

 

객체 병합

function merge(a, b) {
  for (let key in b) {
    if (isObject(a[key]) && isObject(b[key])) {
      merge(a[key], b[key]);
    } else {
      a[key] = b[key];
    }
  }
  return a;
}
 
const obj1 = {a: 1, b:2};
const obj2 = JSON.parse('{"__proto__":{"polluted":1}}');
merge(obj1, obj2);
const obj3 = {};
console.log(obj3.polluted); // 1

 

객체 복사

function clone(obj) {
  return merge({}, obj);
}
 
const obj1 = JSON.parse('{"__proto__":{"polluted":1}}');
const obj2 = clone(obj1);
const obj3 = {};
console.log(obj3.polluted); // 1
728x90

'Web > 개념정리' 카테고리의 다른 글

[개념정리] Mutation XSS  (0) 2024.06.25
[개념정리] Dompurify  (0) 2024.06.23
[개념정리] PHP Deserialization 취약점  (0) 2024.05.26
[개념정리] case mapping collision  (0) 2024.02.29
[개념정리] Click jacking  (0) 2024.01.05