본문 바로가기

1-day 취약점 분석

[ 1-Day ] Prototype pollution via console.table properties

본 포스팅은 학습 목적으로 작성되었으며, hackerone report를 기반으로 작성되었습니다.

-분석 레포트-

https://hackerone.com/reports/1431042

 

 

Summary

 

공격자의 console.table 2 번째 속성 매개변수에 대한 제어는 prototype pollution으로 이어질 수 있다. 

 

Description

 

console.table 함수의 formatting logic으로 인해 사용자가 제어하는 입력을 속성 매개변수로 전달하면서 동시에 하나 이상의 속성이 있는 일반 객체를 첫 번째 매개변수로 전달하는 것은 안전하지 않다. prototype pollution은 빈 문자열에 객체 prototype의 숫자 키만 할당할 수 있다는 점에서 매우 제한적으로 제어할 수 있다. 

 

Steps to Reproduce

 

이 취약점은 v16.7.0으로 테스트 한 Node.js REPL에서 재현할 수 있다. 

 

1. console.table({foo:'bar'}, ['__proto__']) 을 실행한다. 

2. 객체 프로토타입이 오염되었는지 확인한다. ( Object.prototype [0] === '' )

 

pollution은 첫 번째 매개변수로 전달된 객체의 속성 수에 따라 달라지며, 속성이 추가될 때마다 객체 프로토타입의 인덱스가 하나씩 더 증가한다. 즉, 첫 번째 매개변수도 공격자가 제어하는 경우 0.... n까지 빈문자열을 객체 프로토타입에 할당할 수 있다. 

 

> console.table({a: 1, b: 1, c: 1}, ['__proto__'])
Uncaught TypeError: Cannot create property '0' on string ''

> Object.prototype
[Object: null prototype] { '0': '', '1': '', '2': '' }

 

권장되는 해결 방법은 '__proto__'라는 이름의 속성을 무시하거나 다른 데이터 구조를 사용하여, 계산된 테이블 필드를 저장하는 것이다. 

 

 const keys = properties || ObjectKeys(item);
 for (const key of keys) {
+  if (key === '__proto__') {
+    continue
+  }
   if (map[key] === undefined)
     map[key] = [];

 

 console.table은 사용자 입력이 2번째 속성 배열로 전달될 위험을 예상할 이유가 없으므로 아무런 제재 없이 그렇게 할 수 있다. 예를 들어 웹 서버가 이 취약점에 노출되는 경우에도 매우 효과적인 서비스 거부 공격이 될 수 있다. 극히 드물게 프로토타입 오염이 인증 메커니즘 우회와 같은 더 심각한 공격 벡터로 이어질 수 있지만, 오염에 대한 제어가 제한되어 있기 때문에 그럴 가능성은 낮다.

 

대응

 

해당 문제를 방지하기 위해서, CLI flag를 추가하였다. 

 

node --disable-proto=delete : __proto__에 대한 특별한 의미를 갖지 않게 한다. 

node --disable-proto=throw : __proto__ 열과 함께 호출하면, console.table이 발생한다.