
Jellyfin Media Server의 치명적인 경로 순회(path traversal)로 인한 RCE 취약점(CVSS 9.9). 개념 증명(PoC) 익스플로잇, 기술 분석 및 탐지 도구를 포함합니다.
Jellyfin Media Server의 심각한 경로 순회 취약점으로 인해 "자막 업로드" 권한이 있는 인증된 사용자가 디스크의 임의 위치에 파일을 업로드할 수 있습니다. 자막 업로드 엔드포인트의 검증되지 않은 Format 필드를 악용하면 공격자는 민감한 위치에 파일을 쓰고, 민감한 데이터를 추출하고, 권한을 상승시키고, 궁극적으로 LD_PRELOAD 주입을 통해 루트 권한으로 임의 코드를 실행할 수 있습니다.
Jellyfin은 개인 미디어 컬렉션을 관리하고 스트리밍할 수 있도록 설계된 무료 오픈소스 미디어 서버입니다. 상용 미디어 서버와 유사한 기능을 제공하지만 완전한 소스 코드 투명성과 커뮤니티 통제를 갖추고 있습니다.
Jellyfin Media Server (Port 8096)
/ | \
/ | \
Web UI REST API Media Streams
(Browser) (Authenticated) (Subtitle Upload)
|
/System/Info/Public (unauthenticated)
/Videos/{itemId}/Subtitles (vulnerable)
/Library/Collections (admin)
Client Devices > Network > Jellyfin Server > Database + Storage | /var/lib/jellyfin/ /etc/ld.so.preload (writable via vulnerability)
---
## 취약점 심층 분석
### 근본 원인 분석
이 취약점은 자막 업로드 엔드포인트(`/Videos/{itemId}/Subtitles`)에 존재하며, 파일 업로드를 허용하고 디스크에 저장합니다. 핵심 결함은 Format 필드 매개변수의 검증이 충분하지 않다는 점입니다.
#### 취약한 코드 패턴
이 엔드포인트는 Format 필드를 제대로 검증하거나 정화하지 않은 채 자막 업로드를 처리합니다:```
POST /Videos/{itemId}/Subtitles HTTP/1.1
Content-Type: multipart/form-data
[Binary subtitle data]
Format: /../../../etc/ld.so.preload
Language: en
Format 매개변수는 자막 형식(srt, vtt, ass 등)을 지정하기 위한 것이지만, 대신 파일 경로의 일부로 처리됩니다:``` Base Path: /var/lib/jellyfin/subtitles/ User Input: /../../../etc/ld.so.preload Result: /var/lib/jellyfin/subtitles/../../../etc/ld.so.preload Resolved: /etc/ld.so.preload (via path traversal)
### 공격 체인 분석
이 취약점은 여러 약점을 연쇄적으로 연결하여 root 권한으로 원격 코드 실행을 달성합니다:```
Step 1: Subtitle Upload with Path Traversal
POST /Videos/{itemId}/Subtitles
Format: /../../../etc/ld.so.preload
|
v
Step 2: Arbitrary File Write
Write attacker-controlled data to /etc/ld.so.preload
|
v
Step 3: File Read via .strm Files
Create .strm files pointing to sensitive paths
Extract database contents and credentials
|
v
Step 4: Database Extraction
Access /jellyfin/jellyfin.db via .strm
Extract admin user hashes
|
v
Step 5: Admin Privilege Escalation
Reset admin password or create new admin account
|
v
Step 6: RCE via LD_PRELOAD Injection
LD_PRELOAD=/path/to/malicious.so java
Arbitrary code execution as root
Input Validation Failure:
Format Field Validation: Expected: srt | vtt | ass | ssa | sub | subrip Actual: /../../../etc/ld.so.preload Result: NO VALIDATION > PATH TRAVERSAL ALLOWED
File Write Operation: String Concatenation: "/subtitles/" + user_format + ".srt" | NO CANONICALIZATION: Path component not resolved before write NO WHITELIST: Format values not restricted NO BOUNDS CHECK: ".." sequences not filtered | v Final Path: /etc/ld.so.preload (EXPLOITED)
### LD_PRELOAD 악용
LD_PRELOAD 기법은 Linux 시스템에서 강력한 권한 상승 및 코드 실행 방법입니다:```
LD_PRELOAD Injection Flow:
1. Attacker writes malicious .so (shared object) to /etc/ld.so.preload
/etc/ld.so.preload contents:
/path/to/attacker.so
2. Java process starts (Jellyfin runs on Java):
kernel > execve("java", ...) > glibc initialization
|
v
Check /etc/ld.so.preload
|
v
Load attacker.so FIRST
|
v
Execute attacker code
(BEFORE Java main())
3. Code Execution Context:
Process Owner: root (Jellyfin typically runs as root)
Permissions: Full system access
Timing: Before application initialization
Detection: Minimal (malicious code runs early)
4. Attacker Capabilities:
> Create reverse shell with full root privileges
> Extract sensitive data before application starts
> Modify Java application behavior
> Persist via cron jobs or systemd services
> Establish C2 communication
User Level Access > Path Traversal > Write /etc/ld.so.preload | v (Next process execution) | Kernel reads /etc/ld.so.preload > Loads attacker .so | v Malicious code executes in root context | v Full system compromise
---
## 영향 분석
### 기밀성
**치명적** - 완전한 정보 공개
- 데이터베이스 추출: 관리자 자격 증명, 사용자 비밀번호, API 키
- 자막 파일 및 미디어 메타데이터 노출
- 민감한 데이터가 포함된 구성 파일 접근
- 추가 악용을 위한 시스템 정보 수집
### 무결성
**치명적** - 시스템 전체 파일 변조
- 디스크의 임의 위치에 임의 파일 쓰기
- 애플리케이션 바이너리 변조
- 시스템 구성 변경
- 데이터베이스 손상 또는 조작
### 가용성
**치명적** - 서비스 중단 및 거부
- LD_PRELOAD의 악성 .so를 통한 시스템 종료 또는 충돌
- 대용량 파일 쓰기를 통한 디스크 공간 고갈
- 프로세스 종료 또는 리소스 고갈
- 완전한 서비스 불가
### 영향을 받는 구성 요소
- Jellyfin 미디어 서버 프로세스 (대부분의 배포에서 root로 실행됨)
- 운영 체제 커널 및 라이브러리
- 저장된 미디어 및 메타데이터
- 사용자 인증 시스템
- glibc에 링크된 시스템 전체 프로세스
### 비즈니스 영향
- **데이터 유출:** 저장된 모든 자격 증명 및 사용자 데이터가 손상됨
- **서비스 중단:** Jellyfin 및 잠재적으로 다른 서비스도 사용 불가능해짐
- **측면 이동:** 손상된 시스템이 네트워크 공격의 거점이 됨
- **규정 위반:** PII가 노출되면 GDPR, CCPA, HIPAA 위반
- **공급망 위험:** Jellyfin이 공유 또는 엔터프라이즈 미디어를 제공하는 경우
---
## 영향을 받는 버전
| 버전 | 상태 | 참고 |
|---------|--------|-------|
| < 10.8.0 | 취약 | 원래 취약점 존재 |
| 10.8.0 - 10.11.6 | 취약 | 경로 탐색 및 RCE 가능 |
| 10.11.7+ | 패치됨 | Format 필드가 올바르게 검증됨 |
| 10.12.0+ | 패치됨 | 보안 수정 사항이 포함된 최신 버전 |
### 버전 탐지
취약점은 `/System/Info/Public` 엔드포인트의 버전 문자열을 확인하여 탐지할 수 있습니다:```
GET /System/Info/Public HTTP/1.1
Host: jellyfin-server:8096
Response:
{
"ServerName": "MyJellyfin",
"Version": "10.10.3", < Vulnerable
"ProductName": "Jellyfin",
"StartupWizardCompleted": true
}
CVE-2026-35031_Jellyfin_RCE_detector.py 스크립트는 자동화된 취약점 탐지를 제공합니다.
pip install requests urllib3
#### 사용법```bash
python CVE-2026-35031_Jellyfin_RCE_detector.py -t 10.0.0.5:8096
python CVE-2026-35031_Jellyfin_RCE_detector.py -t http://10.0.0.0/24
python CVE-2026-35031_Jellyfin_RCE_detector.py -t targets.txt -o results.json
-t, --target HOST[:PORT] or CIDR or FILE Single target, IP range, or file with targets -p, --port PORT Custom port (default: 8096) --timeout SECONDS Connection timeout (default: 10) -o, --output FILE Save results to JSON file -v, --verbose Enable verbose logging --no-ssl-verify Disable SSL certificate verification
#### 예제 출력```
[*] CVE-2026-35031 Jellyfin RCE Detection Scanner
[*] Target: http://10.0.0.5:8096
[*] Scan Time: 2026-04-15T12:00:00Z
[*] Detection method: /System/Info/Public version check
[*] Vulnerable: Jellyfin < 10.11.7
======================================================================
Target: http://10.0.0.5:8096
Scan Time: 2026-04-15T12:00:00Z
Risk Level: CRITICAL
======================================================================
Is Jellyfin: YES
Jellyfin Version: 10.10.3
Server Name: MediaServer
Operating System: Linux
Subtitle Endpoint: Accessible
Vulnerable: YES
*** VULNERABLE: Path traversal in subtitle upload ***
*** Chains to arbitrary file write and RCE as root via ld.so.preload ***
*** Upgrade to Jellyfin 10.11.7 immediately ***
======================================================================
Summary:
Total Targets: 1
Vulnerable: 1
Patched: 0
Unknown: 0
======================================================================
스캐너는 다음 검사를 수행합니다:
/System/Info/Public 엔드포인트를 쿼리합니다.Version 필드를 파싱합니다.CVE-2026-35031_Jellyfin_RCE.nse 스크립트는 취약점 스캐닝을 위해 Nmap과의 통합을 제공합니다.
sudo cp CVE-2026-35031_Jellyfin_RCE.nse /usr/share/nmap/scripts/
sudo nmap --script-updatedb
#### 사용법```bash
# Basic scan
nmap -p 8096 --script CVE-2026-35031_Jellyfin_RCE 10.0.0.5
# Comprehensive scan with service detection
nmap -sV -p 8096 --script CVE-2026-35031_Jellyfin_RCE 10.0.0.5
# Scan entire subnet
nmap -sV -p 8096 --script CVE-2026-35031_Jellyfin_RCE 10.0.0.0/24
# Aggressive scanning with timing
nmap -sV -p- --script CVE-2026-35031_Jellyfin_RCE -T4 10.0.0.5
# Export results to XML
nmap -sV -p 8096 --script CVE-2026-35031_Jellyfin_RCE -oX results.xml 10.0.0.5
PORT STATE SERVICE VERSION 8096/tcp open http Jellyfin Media Server 10.10.3 | CVE-2026-35031_Jellyfin_RCE: | VULNERABLE: | Jellyfin Subtitle Path Traversal to RCE (CVE-2026-35031) | State: VULNERABLE | Risk level: CRITICAL | CVSS Score: 9.9 | Jellyfin Version: 10.10.3 | Fixed Version: 10.11.7 | Description: | Jellyfin 10.10.3 is vulnerable to CVE-2026-35031. The subtitle | upload endpoint (/Videos/{itemId}/Subtitles) does not validate | the Format field, allowing path traversal and arbitrary file write. | This chains into remote code execution as root via LD_PRELOAD. | Vulnerability Chain: | 1. POST /Videos/{itemId}/Subtitles with Format=/../../../etc/ld.so.preload | 2. Arbitrary file write to /etc/ld.so.preload | 3. Database extraction via .strm files | 4. Admin privilege escalation | 5. RCE as root via LD_PRELOAD injection | Affected Endpoint: /Videos/{itemId}/Subtitles | Authentication Required: YES (non-admin user) | References: | https://nvd.nist.gov/vuln/detail/CVE-2026-35031 | https://github.com/jellyfin/jellyfin/security/advisories/GHSA-9p5f-5x8v-x65m |_ https://github.com/jellyfin/jellyfin/releases/tag/v10.11.7
#### 스크립트 매개변수```bash
# Custom timeout for slow networks
nmap --script CVE-2026-35031_Jellyfin_RCE --script-args timeout=30 10.0.0.5
# Debug mode for troubleshooting
nmap --script CVE-2026-35031_Jellyfin_RCE -d 10.0.0.5
# Aggressive version detection
nmap -sV --version-intensity 9 --script CVE-2026-35031_Jellyfin_RCE 10.0.0.5
Jellyfin 서버 로그 (/var/log/jellyfin/jellyfin.log)```
[ERR] Error processing subtitle upload: Invalid path characters detected
[ERR] Exception in subtitle handling: DirectoryNotFoundException
[ERR] Unauthorized file system access attempt
[WARN] Unusual subtitle format detected: /../../../
[ERR] Security violation: Path traversal attempt blocked
**시스템 로그** (`/var/log/syslog` or `/var/log/messages`)```
subtitle upload process: segmentation fault (core dumped)
kernel: [security] Attempted to load from LD_PRELOAD: /etc/ld.so.preload
ld.so.preload: permission denied or file corrupted
Java process crashed after LD_PRELOAD initialization
Unexpected behavior from root-level Java process
수정된 시스템 파일``` /etc/ld.so.preload - Should not contain any paths if not configured /lib/x86_64-linux-gnu/ - Look for suspicious .so files created recently /var/lib/jellyfin/subtitles - Check for files outside normal naming /etc/passwd - Verify no unauthorized access or modification /var/lib/jellyfin/db - Database timestamps may indicate extraction
**자막 디렉토리의 의심스러운 파일 경로**```
/../../../etc/ld.so.preload
/../../../root/.ssh/authorized_keys
/../../../var/lib/jellyfin/jellyfin.db
../../../proc/self/environ
의심스러운 HTTP 요청``` POST /Videos/[0-9]+/Subtitles
Encoded Payloads: %2e%2e%2f (URL encoded ../) ..%252f (Double encoded ../) ....// (Bypass patterns)
**Jellyfin 프로세스의 아웃바운드 연결**```
Reverse shells to external IPs
Connections to known C2 infrastructure
DNS requests to anomalous domains
Sudden spike in network traffic after failed subtitle upload
Jellyfin 프로세스 이상``` java process executing system commands java process spawning shell processes (/bin/bash, /bin/sh) java process opening connections to unusual ports java process reading system files like /etc/shadow Unusual CPU or memory usage spikes Child processes with different UID than parent
### 데이터베이스 지표
**Jellyfin 데이터베이스 변경 사항** (`jellyfin.db`)```
New admin user created outside normal workflow
Admin password changed without admin action
API keys/tokens created unexpectedly
Unusual activity in audit logs
즉시 Jellyfin을 업그레이드하세요 ```bash
docker pull jellyfin/jellyfin:latest docker-compose down docker-compose up -d
sudo apt-get update sudo apt-get install --only-upgrade jellyfin
sudo dnf upgrade jellyfin
Jellyfin 서비스 중지 ```bash sudo systemctl stop jellyfin
악용 여부 확인 ```bash
ls -la /etc/ld.so.preload cat /etc/ld.so.preload
find /var/lib/jellyfin/subtitles -type f -newer /proc -ls
find /var/lib/jellyfin -type f -newermt "2026-04-14" -ls
자막 업로드 권한 제한 ``` Jellyfin Web UI > Settings > Users Disable "Upload Subtitles" for all non-admin users Review all users with this permission
네트워크 분할 ```
sudo ufw allow from 192.168.1.0/24 to any port 8096 sudo ufw deny from any to any port 8096
파일 시스템 권한 ```bash
sudo usermod -s /usr/sbin/nologin jellyfin
sudo chmod 644 /etc/ld.so.preload sudo chmod 644 /etc/ld.so.conf
sudo chown -R jellyfin:jellyfin /var/lib/jellyfin sudo chmod 750 /var/lib/jellyfin
악용 시도 모니터링 ```bash
tail -f /var/log/jellyfin/jellyfin.log | grep -i subtitle
웹 애플리케이션 방화벽(WAF) 구현 ``` Block requests containing:
보안 모듈 활성화 ```bash
sudo aa-enforce /etc/apparmor.d/usr.bin.java
sudo semanage fcontext -a -t jellyfin_home_t "/var/lib/jellyfin(/.*)?" sudo restorecon -R /var/lib/jellyfin
Jellyfin을 루트가 아닌 사용자로 실행 ```bash
sudo useradd -r -s /usr/sbin/nologin jellyfin
sudo sed -i 's/User=.*/User=jellyfin/' /etc/systemd/system/jellyfin.service sudo systemctl daemon-reload sudo systemctl restart jellyfin
정기 백업 구현 ```bash
sudo crontab -e
curl -s http://localhost:8096/System/Info/Public | jq .Version
cat /etc/ld.so.preload | wc -l # Should be 0 or contain only legitimate entries
ps aux | grep jellyfin | grep -v grep
sudo ufw status
---
## 참조
### 공식 출처
- **NVD 항목:** https://nvd.nist.gov/vuln/detail/CVE-2026-35031
- **GitHub 권고:** https://github.com/jellyfin/jellyfin/security/advisories/GHSA-9p5f-5x8v-x65m
- **Jellyfin 릴리스 v10.11.7:** https://github.com/jellyfin/jellyfin/releases/tag/v10.11.7
- **Jellyfin 문서:** https://docs.jellyfin.org
### 관련 취약점 및 연구
- CWE-22: 경로 탐색 - https://cwe.mitre.org/data/definitions/22.html
- LD_PRELOAD 악용: https://www.gnu.org/software/libc/manual/html_node/Dynamic-Linker.html
- Java 프로세스 권한 상승 패턴
- 자막 파일 형식 사양 (RFC 표준)
### 보안 도구 및 리소스
- Nmap: https://nmap.org
- Metasploit Framework: https://www.metasploit.com
- OWASP 경로 탐색 가이드: https://owasp.org/www-community/attacks/Path_Traversal
---
## 작성자
**취약점 발견 및 문서화:**
**Kerem Oruc** (@keraattin)
- GitHub: https://github.com/keraattin
- Twitter/X: https://twitter.com/keraattin
### 기여
이 문서나 탐지 도구에 대한 개선 사항이 있으면 풀 리퀘스트를 제출하거나 이슈를 열어 주세요.
---
**면책 조항:** 이 문서는 교육 및 허가된 보안 테스트 목적으로만 제공됩니다. 컴퓨터 시스템에 대한 무단 접근은 불법입니다. 보안 평가를 수행하기 전에 항상 적절한 승인을 받으십시오.
**최종 업데이트:** 2026-04-15 | **상태:** 게시됨
| 속성 | 값 |
|---|
| CVE ID | CVE-2026-35031 |
| CVSS 점수 | 9.9 (치명적) |
| CWE | CWE-22: 제한된 디렉터리의 경로명에 대한 부적절한 제한 ('Path Traversal') |
| 영향받는 제품 | Jellyfin Media Server |
| 영향받는 버전 | < 10.11.7 |
| 수정 버전 | 10.11.7 이상 |
| 취약점 유형 | 경로 순회 + 임의 파일 쓰기 + RCE |
| 인증 필요 | 예 (비관리자 사용자) |
| 필요한 권한 | "자막 업로드" 권한 |
| 기본 포트 | 8096/TCP |
| GitHub 보안 권고 | GHSA-9p5f-5x8v-x65m |
| 패치 상태 | 제공 및 배포됨 |
| 공개 익스플로잇 | 예 |
auditctl -w /etc/ld.so.preload -p wa -k ld_preload_changes
tar -tzf /backup/jellyfin-$(date +%Y%m%d).tar.gz > /dev/null
감사 로깅 활성화 ```bash
auditctl -w /etc/ld.so.preload -p wa -k ld_preload_audit auditctl -w /var/lib/jellyfin -p wa -k jellyfin_audit
auditctl -a always,exit -F exe=/usr/bin/java -F arch=b64 -S execve -k jellyfin_exec