Web Application Security: Prototype Pollution and Jailbreak Vulnerabilities
금융·건강·법률 등 민감 주제입니다. 중요한 결정 전 전문가 확인을 권장합니다. 고지·면책 안내
2026-07-12 2026-07-12 2026-07-12
목차 (0개 섹션)목차 (0개 섹션)목차 (0개 섹션)
2018년 11월, npm 패키지 매니저 생태계에 조용한 파장이 일었다. 보안 연구자들이 lodash와 jQuery를 비롯한 인기 라이브러리 수십 개에서 동일한 계열의 결함을 잇달아 찾아냈기 때문이다. 이름하여 "프로토타입 오염(Prototype Pollution)". 겉보기엔 사소한 객체 병합 버그처럼 보였지만, 실제로는 자바스크립트 언어 설계 그 자체의 특성을 파고든 취약점이었다.
자바스크립트의 모든 객체는 Object.prototype이라는 공용 원형을 상속받는다. {}로 새 객체를 만들어도, 그 객체는 보이지 않는 실에 묶여 Object.prototype과 연결돼 있다. 문제는 __proto__라는 특수 키를 통해 이 원형에 직접 접근할 수 있다는 데 있다. 공격자가 사용자 입력값을 재귀적으로 병합하는 함수(merge, extend, clone 등)에 {"__proto__": {"isAdmin": true}} 같은 JSON을 밀어넣으면, 병합 로직이 이를 그대로 처리하면서 전역 원형 객체에 isAdmin 속성을 심어버린다. 그 순간부터 애플리케이션 내 모든 객체는 별도의 선언 없이도 isAdmin: true를 상속받게 된다.
파급력은 여기서 끝나지 않는다. 2019년 카네기멜론대 CERT/CC와 스노크(Snyk)가 공동 발표한 분석에 따르면, 단순 권한 상승을 넘어 서비스 거부(DoS), 심하게는 원격 코드 실행(RCE)으로까지 이어질 수 있었다. 특히 Node.js 서버 환경에서 child_process나 템플릿 엔진(예: 오래된 버전의 handlebars, pug)과 결합될 경우, 오염된 원형 속성이 명령어 실행 경로에 개입해 임의 코드가 실행되는 사례가 실제 CVE로 다수 등록됐다. lodash는 CVE-2018-3721, CVE-2019-10744 두 차례에 걸쳐 이 문제로 패치를 냈고, 당시 주간 다운로드 2천만 건이 넘는 패키지였던 만큼 영향 범위는 사실상 전체 npm 생태계에 가까웠다.
방어책을 두고도 개발자 커뮤니티 내에서 논쟁이 있었다. 일각에서는 Object.freeze(Object.prototype)로 원형 자체를 동결하는 방법을 제시했지만, 이는 프레임워크 내부 동작을 깨뜨리는 부작용이 보고되며 실무 도입이 제한적이었다. 결국 업계 표준으로 자리잡은 대응은 Object.create(null)로 원형이 없는 객체를 만들거나, Map 자료구조로 사용자 입력을 다루는 방식, 그리고 병합 함수 내부에서 __proto__, constructor, prototype 키를 명시적으로 차단하는 방식이다. OWASP는 2021년판 Top 10 개정 논의에서 이 취약점을 "인젝션" 범주의 하위 사례로 편입하는 안을 검토하기도 했다. 정적 분석 도구만으로는 탐지가 까다로워, 실전에서는 코드 리뷰와 의존성 스캔(예: npm audit, Snyk)을 병행하는 것이 일반적인 관행으로 굳어졌다.
자바스크립트로 웹사이트나 앱을 만들 때, 프로그래머들은 종종 두 개의 데이터를 하나로 합치는 코드를 쓴다. 예를 들어 사용자가 입력한 설정값과 기본 설정값을 합쳐서 하나의 객체로 만드는 식이다. 그런데 이 "합치기" 과정에 허점이 있다면 어떻게 될까?
바로 그 허점을 파고드는 공격이 프로토타입 오염이다. 자바스크립트에서는 모든 객체가 Object.prototype이라는 공통 뼈대를 공유한다. 쉽게 말해 사이트 안에서 만들어지는 모든 객체는 보이지 않는 끈으로 이 뼈대에 연결돼 있다. 공격자가 "__proto__"라는 특수한 이름의 키를 이용해 악의적인 값을 집어넣으면, 그 값이 뼈대 자체에 새겨진다. 그러면 사이트의 다른 모든 객체가 자동으로 그 값을 물려받게 된다.
구체적으로 어떤 문제가 생길까? 만약 어떤 사이트가 "관리자인지 아닌지"를 객체 속성으로 판단한다면, 공격자는 프로토타입을 오염시켜 자신을 관리자처럼 보이게 만들 수 있다. 실제로 2018~2019년 사이 전 세계에서 가장 많이 쓰이는 자바스크립트 라이브러리인 lodash에서 이런 결함이 두 번이나 발견됐다. 이 라이브러리는 당시 매주 2천만 번 넘게 다운로드되고 있었으니, 문제가 생기면 얼마나 많은 사이트가 영향을 받을지 짐작이 갈 것이다.
더 심각한 경우엔 서버가 아예 다운되거나(서비스 거부), 공격자가 원하는 명령어를 서버에서 몰래 실행시키는 일까지 벌어질 수 있다. 그래서 개발자들은 몇 가지 방어법을 쓴다. 객체를 만들 때 아예 뼈대(프로토타입)가 없는 객체를 쓰거나, 사용자 입력값을 합칠 때 __proto__ 같은 위험한 이름을 걸러내는 방식이다. 요즘은 npm audit 같은 자동 점검 도구로 이런 취약점이 있는 라이브러리를 쓰고 있는지 미리 확인하는 게 웹 개발의 기본 절차가 됐다. 이 사례는 겉으로는 별것 아닌 듯한 코드 한 줄이 사이트 전체를 위험에 빠뜨릴 수 있다는 걸 잘 보여준다.
레고 블록으로 여러 사람이 같이 쓰는 커다란 설계도가 있다고 생각해 보자. 이 설계도에는 "모든 블록은 이렇게 생겼다"는 기본 모양이 그려져 있고, 새로 만드는 블록은 전부 이 기본 모양을 따라간다.
그런데 만약 누군가 몰래 이 설계도 자체에 낙서를 한다면 어떻게 될까? 예를 들어 "모든 블록에는 비밀 열쇠가 달려 있다"라고 써 놓으면, 그 다음부터 만들어지는 모든 블록에 진짜로 비밀 열쇠가 생겨버린다. 원래는 특별한 블록 하나에만 있어야 할 열쇠가, 설계도를 고쳐버렸기 때문에 모든 블록에 저절로 생기는 것이다.
컴퓨터 프로그램에서도 이와 비슷한 일이 일어날 수 있다. 자바스크립트라는 프로그래밍 언어에는 모든 "물건"(객체라고 부른다)이 공유하는 기본 설계도 같은 것이 있다. 나쁜 사람이 이 공용 설계도에 몰래 이상한 내용을 끼워 넣으면, 프로그램 안의 모든 물건이 그 이상한 내용을 자동으로 갖게 된다. 이걸 "프로토타입 오염"이라고 부른다. 마치 학교 급식판 하나에 몰래 소금을 잔뜩 넣었더니, 그 급식판을 찍어낸 틀 자체가 오염돼서 이후에 만드는 모든 급식판에 소금이 들어가 버리는 것과 비슷하다.
실제로 2018년과 2019년에 전 세계 수많은 웹사이트가 쓰던 유명한 프로그램 도구(lodash라는 이름)에서 이런 문제가 두 번이나 발견됐다. 그래서 프로그래머들은 이제 물건을 만들 때 아예 공용 설계도와 연결되지 않은 특별한 물건을 쓰거나, 이상한 낙서가 들어오지 못하게 미리 검사하는 방법을 쓴다. 작은 틈 하나가 큰 문제로 번질 수 있다는 걸, 이 사례가 잘 보여준다.
문서 정보
최초 작성
최종 갱신
분류
기술
HANGUL.WIKI가 정리·작성한 문서입니다. 정확성을 위해 노력하나 오류가 있을 수 있으므로, 중요한 내용은 공식 출처를 통해 확인하시기 바랍니다.
내용의 오류나 정정 요청은 오류·정정 신고로 알려주시면 검토 후 반영합니다.