‘Prototype 오염’ 공격 확산에 ‘경각심’ 증폭
자바스크립트, ‘클래스’ 대신 ‘프로토타입 체인’ 상속 악용 특정 로직 우회 RCE 실행, ‘.canDelete’ 값 변경 ‘삭제․제어권 탈취’ 사용자 입력값 검증, 최신‘npm’모듈, ‘Object.freeze() 메서드’로 예방
[애플경제 전윤미 기자] 자바스크립트의 ‘Prototype Pollution’(프로토타입 오염)의 취약점을 악용한 사이버공격에 대한 경각심이 새삼 고조되고 있다.
파이썬이나 C++ 등과 같이 자바스크립트 역시 객체지향언어다. 그러나 전자는 ‘클래스’가 있으나 후자는 그게 없다는게 차이점 중 하나다. 그래서 파이썬이나 C++는 ‘상속’, 즉 ‘클래스’를 이용해 새로운 ‘클래스’를 생성하는 기법으로 기존 코드를 재활용한다. 그러나 ‘클래스’가 따로 없는 자바스크립트는 ‘프로토타입’이라는 객체를 사용해서 상속을 구현한다.
그런 과정에서 ‘Prototype Pollution’이 일어난다. 즉, 자바스크립트 내부에서 ‘클래스’가 없는 대신, ‘프로토타입 체인’으로 상속을 구현한 점을 이용해, 특정 로직을 우회하거나 코드가 해커가 원하는 방향으로 RCE(원격코드실행)가 이뤄지도록 하는 것이다.
사용자엔 DOM XSS, 서버엔 원격코드실행(RCE)
국내 대표적인 사이버보안업체로 꼽히는 이글루코퍼레이션은 “‘Prototype-Pollution’이 독립형 취약점으로 악용된 사례는 적지만, 이를 통해 공격자가 접근할 수 없는 개체의 속성을 제어할 수 있게 하는게 문제”라고 했다. 즉, 공격자가 제어할 수 있는 속성을 사전에 소홀히 처리하는 경우 이는 다른 잠재적 취약점을 유발한다는 지적이다. 그 결과 사용자측에선 주로 DOM XSS(Document Object Model, Cross Site Scripts, 웹 제어 공격)로 나타나고, 서버 측에서는 원격 코드 실행(RCE)로 이어지는 결과를 초래할 수 있다.
이글루코퍼레이션은 “자바스크립트의 다이내믹한 동적 특성과 타사 라이브러리의 광범위한 사용으로 인해 공격 표면이 증가하는 중”이라고 짚었다.
이에 따르면 주로 객체를 합병(merge)하거나 병합된 객체를 생성하는 데 사용되는 ‘재귀 병합 함수’가 취약해질 가능성이 크다. 사용자가 입력이나, 외부 데이터를 받아들일 때 주의하지 않기 때문이다. 특히 “사용자 입력에 의해 생성된 객체가 프로토타입을 오염시키는 경우나, 입력한 객체에 ‘proto’를 통해 프로토타입을 지정할 경우, 지정된 객체가 병합되거나 복제될 때 등의 경우 ‘프로토타입 오염’이 발생한다.
특히 사용자가 제어할 수 있음에도 불구하고, 입력을 할 때 철저한 검증이 이뤄지지 않을 때가 문제다. 이 경우 사용자가 ‘proto’ 경로를 임의로 지정함으로써 ‘prototype-pollution’을 유도할 수 있다는 지적이다.
또 객체를 복제하는 ‘클론 함수’와, 여러 객체를 병합하는 ‘merge 함수’가 사용자 입력을 처리할 때도 마찬가지다. 이 경우 충분한 검증 없이 동작하면, 악의적인 사용자가 입력 값을 조작, ‘prototype-pollution’ 공격을 할 수 있다.
“사용자 입력 오류나 부주의가 가장 큰 원인”
실제로 이글루코퍼레이션이 사례로 든 ‘CVE-2018-16487’ 취약점이 그런 경우다. 이는 인기있는 라이브러리인 로다쉬(lodash)에서 발견된 취약점이다. 로다쉬는 문자열, 숫자, 배열, 함수, 개체 프로그래밍을 단순화한 라이브러리다. 프로그래머가 자바스크립트 코드를 좀더 효율적으로 작성하고 유지/관리하는데 유용하다는 평판 속에 인기가 높다.
‘CVE-2018-16487’는 로다쉬 4.17.5 ~ 4.17.11 버전이 영향을 받은 취약점이다. 이는 ‘merge’ 함수가 객체를 병합할 때 적절한 검증을 수행하지 않은 탓에 생긴 것이다. 즉 악의적인 사용자가 예상치 못한 속성을 추가하거나, 기존 속성을 변경할 수 있는 취약점이다. 공격자는 이 취약점을 악용, 개체 동작에 따라 권한을 상승하거나, 잠재적으로 RCE(원격코드실행) 공격을 초래할 수 있는 개체 프로토타입 속성을 응용 프로그램 내에 추가할 수 있다.
새 메시지 페이로드로 공격, ‘.canDelete’ 값 ‘true’로 변경
공격자들은 이런 취약점을 파고든 후 시험삼아 새로운 메시지를 게시하는 페이로드를 전송하면서 공격을 시작한다. 특히 삭제가 가능한 ‘.canDelete’ 값을 ‘true’로 변경시킴으로써 관리자만 사용할 수 있는 기능을 획득한다. 그리곤 이처럼 속성 값을 변경하는 페이로드를 전송한다. 그 결과 ‘canDelete’ 값이 존재하지 않는 ‘user’ 객체는 프로토타입 체인에 의해 ‘Object’ 객체의 canDelete 속성을 상속받게 된다. 결국 별도의 관리자 기능 없이도 관리자에게만 주어졌던 메시지 삭제 기능을 공격자도 정상적으로 사용할 수 있게 된 것이다. 사실상 공격자에게 네트워크에 대한 삭제나 제어권을 빼앗긴 셈이다.
이같은 ‘Prototype-Pollution’ 취약점을 예방하려면 어떤 방안이 필요할까. 이에 대해 역시 이글루코퍼레이션 등 전문가들은 무엇보다 ‘사용자 입력 값 검증’을 강조한다. 즉, “사용자의 입력 값 검증을 수행하기 위해서는 사용자로 입력 받은 후 해당 입력을 검증하는 코드를 추가하거나 수정해야 한다”는 것이다.
예를 들어 ‘Object.prototype’와 ‘proto’ 등의 특정 키워드를 필터링하고, 안전한 데이터만 허용하는 코드를 사용해야 한다. 사용자 입력을 받아 지정된 키워드를 필터링하고, 안전한 입력만 반환하는 ‘validateInput’ 함수도 그런 경우다. 또 “각종 환경을 고려해 데이터 타입이나 길이 등을 확인하는 추가적인 검증 규칙을 적용할 것”을 권하기도 한다.
‘Object.freeze() 메서드’도 방법이다. 매서드는 일종의 ‘연산’을 뜻한다. 즉, ‘Object.freeze() 메서드’를 이용해 객체를 동결함으로써 다른 제3가자 변경할 수 없도록 하는 것이다. 동결된 객체는 새로운 속성을 추가하거나, 기존 속성을 제거하는 것을 방지함으로써 속성의 불변성이 변경되지 않게 한다. 또한 프로토타입이 변경되는 것도 막는다.
키워드 필터링, 속성 불변, 기본 프로토타입 상속 차단 등 대응
‘Object.create()메서드’로 지정된 프로토타입 객체와 속성(property)을 갖는 새 객체를 만드는 것도 방법이다. 이때 프로토타입이 ‘null’인 객체를 생성할 경우, 기본 프로토타입을 상속 받지 않게 되는게 핵심이다.
본래 자바스크립트에서 객체를 생성할 때는 ‘object’를 프로토 타입으로 상속한다. 이에 따라 메서드와 속성을 사용할 때 프로토타입 체인을 통해 해당 객체, 즉 ‘ Object.prototyp’의 프로토타입 체인을 따라가게 된다. 그러나 ‘Object.prototype(null)’를 사용할 경우 기본적인 프로토타입 체인에서 벗어나게 됨으로써 좀더 안전하게 되는 것이다.
‘npm’ 모듈 최신화도 대응방안으로 꼽힌다. npm(node package manager)은 . ‘https://www.npmjs.com’ 에 등록된 라이브러리들을 쉽게 설치, 삭제할 수 있게 해주는 도구다. 자바스크립트나 ‘Node.js’ 환경에서 패키지를 관리하고 공유하는 툴이며, 자바스크립트 생태계에서 널리 사용되고 있다. 그런 ‘npm모듈’을 최신화 함으로써 ‘Prototype-Pollution’ 등 보안 위협 및 버그를 방지할 수 있다. ‘npm 모듈’의 최신 버전은 깃허브 레포지토리나, npm 공식 웹사이트(‘https://www.npmjs.com’, 또는 npm 명령어를 통해 확인할 수 있다.