Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2024-27198 — CVE-2024-27198 详细分析:JetBrains TeamCity 中的身份验证绕过漏洞可导致远程代码执行,包含代码级解释和漏洞利用演示。 | Kitploit
工具/GitHubGitHub/hpt-intern-task-submission/cve-2024-27198
漏洞分析漏洞利用Web应用程序漏洞利用渗透测试身份验证学习与教育
GitHubhpt-intern-task-submission/cve-2024-27198

CVE-2024-27198

CVE-2024-27198 详细分析:JetBrains TeamCity 中的身份验证绕过漏洞可导致远程代码执行,包含代码级解释和漏洞利用演示。

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
查看仓库
12年前尚未审核
分享

CVE-2024-27198:Jetbrain TeamCity 身份验证绕过导致远程代码执行

概述

TeamCity 是一个持续集成和部署服务器,提供开箱即用的持续单元测试、代码质量分析以及构建问题的早期报告

该漏洞出现在一个库中,允许攻击者访问任意未经身份验证的端点。

代码分析

漏洞代码位于 web-openapi.jar 库中,路径为 lib 目录

类 jetbrains.buildServer.controllers.BaseController 负责处理请求和响应,但实现不当。让我们看看代码长什么样:

root@kitploit:~
public abstract class BaseController extends AbstractController {
//////
public final ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {  
    try {  
        ModelAndView modelAndView = this.doHandle(request, response);  
        if (modelAndView != null) {  
            if (modelAndView.getView() instanceof RedirectView) {  
                modelAndView.getModel().clear();  
            } else {  
                this.updateViewIfRequestHasJspParameter(request, modelAndView);  
            }  
        }

ModelAndView 方法的主要用途是将请求的页面渲染到 UI。这就是 bug 的起点。注意,如果我们的请求没有被重定向,updateViewIfRequestHasJspParameter 将会被调用。为了找到漏洞的根本原因,我们需要深入研究以理解。

root@kitploit:~
private void updateViewIfRequestHasJspParameter(@NotNull HttpServletRequest request, @NotNull ModelAndView modelAndView) {  
    boolean isControllerRequestWithViewName = modelAndView.getViewName() != null && !request.getServletPath().endsWith(".jsp");  
    String jspFromRequest = this.getJspFromRequest(request);  
    if (isControllerRequestWithViewName && StringUtil.isNotEmpty(jspFromRequest) && !modelAndView.getViewName().equals(jspFromRequest)) {  
        modelAndView.setViewName(jspFromRequest);  
    }  
  
}

该方法用于在满足特定条件时更新 ModelAndView 对象的视图名称。isControllerRequestWithViewName 在 modelAndView 对象有名称且 URL 中的 path 不以 .jsp 结尾时为 True。例如,满足这些条件的 URL 是 http://localhost:8111/random_string,而不满足的 URL 比如 http://localhost:8111/admin/admin.html 或 http://localhost:8111/admin.jsp。如上所述,我们不能访问触发重定向的内容,通常这些是需要授权的页面。程序随后会分配一个名为 jspFromRequest 的变量,该变量会调用 getJspFromRequest() 方法。现在让我们转到那个方法,我稍后会解释剩余代码。有一个 if 语句会检查 isControllerRequestWithViewName 是否为真,调用方法 getJspFromRequest() 的结果是否非空,并且 modelAndView 对象的名称不能等于我们通过 请求的页面。

root@kitploit:~
protected String getJspFromRequest(@NotNull HttpServletRequest request) { String  jspFromRequest  = request.getParameter("jsp"); return  jspFromRequest  == null || jspFromRequest.endsWith(".jsp") && !jspFromRequest.contains("admin/") ? jspFromRequest : null; }

该函数首先获取名为 jsp 的请求参数的值。检查确保 jsp 必须以 .jsp 结尾并且不能包含 /admin。结合上面的 if 语句:

root@kitploit:~
if (isControllerRequestWithViewName && StringUtil.isNotEmpty(jspFromRequest) && !modelAndView.getViewName().equals(jspFromRequest)) {  
        modelAndView.setViewName(jspFromRequest);  
    }  

我们将全面了解 URL 的构成方式:

  1. 路径既不能触发重定向,也不能包含 .jsp
  2. jsp 请求参数的值不能等于 path。例如,/random?jsp=/random 无效
  3. 最重要的是,jsp 必须以 .jsp 结尾

TeamCity 提供了一个 REST API,用于集成外部应用以及与 TeamCity 服务器进行脚本交互。它允许通过 URL 路径访问资源。 你可以通过在浏览器中打开 http://<TeamCity Server host>:<port>/app/rest/server URL 开始使用 REST API:此页面提供了一些探索 API 的指针。

TeamCity 提供了一个 REST API,如果我们能绕过身份验证,就可以访问敏感资源。在本例中,我们将尝试访问 /app/rest/server。

未授权请求

像往常一样,当我们请求 /app/rest/server 时,服务器会将我们重定向到 /login.html。我们来构造一个完美的 URL 以绕过此限制。首先,我们的路径可以是任何内容,只要它返回 404 状态码甚至 200,例如 login.html。接下来,我们将使用 jsp 请求 /app/rest/server,但它必须以 .jsp 结尾。在这种情况下,我们甚至可以使用两种技巧来绕过这个检查。我们可以使用分号 ; 作为参数分隔符:/app/rest/server;.jsp,此时 .jsp 将被视为第二个参数。第二种绕过方法是使用 URI 片段 #:/app/rest/server%23.jsp。URI 片段之后的内容不会用于路由,仅用于页面内导航。注意,该字符需要进行 URL 编码,否则浏览器会先忽略它。

未授权请求绕过

利用这种技术,我们甚至可以创建具有 管理员权限 的新用户。TeamCity 文档指出,我们可以通过端点 /app/rest/users 创建新用户。

创建新用户

让我们进入管理面板,检查是否有任何新用户被创建。

确认

正如预期,创建了一个具有 管理员权限 的新用户。拥有了管理员权限,我们就能完全控制服务器。然而,我们还可以更进一步,实现远程代码执行。该 CVE 影响所有早于 2023.11.4 的版本,但此 RCE 仅对 2023.11 之前的版本有效。存在一个未记录的端点 /app/rest/debug/processes,允许具有管理员权限的用户执行任意命令。我们将发送一个 POST 请求,在请求 URL 中包含两个请求参数。对于 Windows,参数为 ?exePath=cmd.exe&params=/c%20[我们的命令];对于 Linux,参数为 ?exePath=/bin/sh&params=-c%20[我们的命令]。我运行的是 Windows 上的 TeamCity,因此完整路径为 /app/rest/debug/processes?exePath=cmd.exe&params=/c%20whoami

失败尝试

服务器返回 403 错误,指出请求缺少 csrf token。TeamCity 文档也提供了获取 token 的端点:/authenticationTest.html?csrf。

获取 token 后,我们将其添加到请求头 X-TC-CSRF-Token 或 HTTP 参数 tc-csrf-token 中,这里我选择 X-TC-CSRF-Token。

完成

提供 csrf token 后,我们成功远程执行了命令,从而完全控制服务器。

在此 CVE 中,安全缺陷并非在于输入验证,而是代码逻辑。此应用非常复杂,开发人员难免会犯错。我们还学到了一种绕过身份验证的新技术。希望你能从这次分析中学到一些有用的东西。Happy hacking!!!

下载工具