일주일 동안 우연치 않게 연속으로 Prototype Pollution
에 대한 문제를 몇 개 풀어보았는데 글로 정리해야지를 실천하지 못하다가 오늘 적어봅니다…
Prototype
프로토타입(prototype)은 객체입니다. 자바스크립트의 모든 객체들은 최소 하나 이상의 다른 객체로 부터 상속을 받게되는데, 이때 상속되는 정보를 제공하는 객체를 프로토타입이라고 합니다. 쉽게 예시를 들면 알리오 올리오
라는 객체가 있다면 이것의 프로토타입은 파스타(알리오올리오.prototype)
가 될 수 있죠. 하지만 프로토타입을 가지지 않는 객체도 존재하는데요. 바로 최상단에 위치한다고 볼 수 있는 Object.prototype
이 그렇습니다. 이 글에서 한가지 기억해둬야 할 것은 만약 아래에 있는 코드처럼 객체 리터럴
의 형태로 객체를 생성하면 그 객체의 부모는 __proto__
로 접근할 수 있고, 그 객체의 프로토타입은 Object.prototype
이 된다는 것입니다.
1
2
const obj1 = {};
console.log(obj1.__proto__ === Object.prototype); // true
Prototype Chain
자바스크립트는 이처럼 프로토타입을 이용해서 상속을 표현하는데, 만약 어떤 속성을 객체에서 찾는데 그 속성이 없다면 프로토타입에서 속성을 검색합니다. 만약 거기서도 없다면 프로토타입의 프로토타입에서 검색을 하겠죠? 이런 특성을 Prototype Chain
이라고 합니다. 위 코드에서 우리가 obj1
의 속성으로 toString
메서드를 정의하지 않아도 obj1.toString()
을 불러올 수 있는 이유이기도 하죠. 이어서 설명하겠지만 Prototype Chain
은 Prototype Pollution
에 있어서 중요한 키포인트가 됩니다.
Prototype Pollution
그렇다면 이 글의 주인공인 Prototype Pollution
이란 뭘까요? 말 그대로 프로토타입의 속성을 오염시켜 발생하는 취약점 입니다. 아래 4줄자리 코드가 위에서 말한 내용들을 대변하고 있습니다.
1
2
3
4
5
const obj1 = {};
obj1.__proto__.hoppi = 'polluted';
const obj2 = {};
console.log(obj2.hoppi); // polluted
또한 __proto__
이라는 key
를 통한 접근도 가능합니다. 같은 말을 반복하는 것이지만 사용자가 객체의 key
를 설정할 수 있고 value
에 대한 핉터링이 없으면 아래처럼 PP
가 가능해집니다.
1
2
3
4
const obj1 = {};
obj1['__proto__']['is_admin'] = true;
const obj2 = {};
console.log(obj2.is_admin); // true
Mitigation
간단하게 예방하는 방법은 아래와 같습니다.
__proto__
,prototype
,constructor
와 같은 키워드는 필터링Object.freeze(Object.prototype)
를 사용하여 프로토타입을 freeze
Conclusion
짧지만 굵게 Prototype Pollution
에 대해서 적어봤습니다. 드림핵에서 적용해볼 수 있는 문제로는 NSS, Environment Pollution, filestorage가 있겠네요. 이미 PP
에 대해서 검색해보신 분이면 알겠지만 구글에 좋은 자료들이 많이 넘쳐나기 때문에 오염이 발생할 수 있는 패턴과 더 자세한 설명은 레퍼런스를 참고하시면 되겠습니다.
Comments powered by Disqus.