JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

admin 2024年3月12日10:06:34评论37 views字数 5419阅读18分3秒阅读模式

一、环境搭建

单纯的验证的话,使用docker就可以了:

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
# sudo ufw disable

这里我们使用windows+IDEA远程调试的方式来调试代码。

先去官方下载exe文件:

https://www.jetbrains.com/teamcity/download/other.html

我选择的版本是2023.11.3,如果是2023.05.x的版本的话,一些文件位置会不对,一些文件会没有(例如web-openapi.jar)。

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

然后直接解压,并拖到IDEA里面打开:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

conf文件夹下新建server.xml

<?xml version='1.0' encoding='utf-8'?>
<Server port="8105" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
    <GlobalNamingResources>
        <Resource name="UserDatabase" auth="Container"
                  type="org.apache.catalina.UserDatabase"
                  description="User database that can be updated and saved"
                  factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
                  pathname="conf/tomcat-users.xml" />

    </GlobalNamingResources>
    <Service name="Catalina">
        <Connector port="8111" protocol="org.apache.coyote.http11.Http11NioProtocol"
                   connectionTimeout="60000"
                   redirectPort="8543"
                   useBodyEncodingForURI="true"
                   tcpNoDelay="1"
                   maxHttpHeaderSize="16000"
        />

        <Engine name="Catalina" defaultHost="localhost">
            <Realm className="org.apache.catalina.realm.LockOutRealm">
                <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                       resourceName="UserDatabase"/>

            </Realm>
            <Host name="localhost"  appBase="webapps"
                  unpackWARs="true" autoDeploy="true">


                <Valve className="org.apache.catalina.valves.ErrorReportValve"
                       showReport="false"
                       showServerInfo="false" />

            </Host>
        </Engine>
    </Service>
</Server>

打开TeamCity-2023.11.3bincatalina.bat,在第一行插入如下代码:

SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8188

并进行远程JVM调试的配置:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

完事之后进入刚才的bin目录,通过teamcity-server start启动teamcity server;如果是第一次启动的话需要配置数据库位置、admin的账号密码等。

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

弄完这些之后去idea里面打个断点开启调试,并通过yakit等发包测试是否配置成功进入调试:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

二、漏洞分析

你需要把一些文件夹里面的lib文件夹右键Add as Libriary...来添加到依赖之中,以避免大量的报错影响阅读。建议可以先F8配合F7一步步调试完整个代码,对途径的函数名称有所熟悉。

TeamCity中负责请求处理分发的功能点位于TeamCity-2023.11.3webappsROOTWEB-INFlibweb-openapi.jar!jetbrainsbuildServercontrollersBaseController.class,看到handleRequest函数的最后调用了handleRequestInternal,因此我们在handleRequestInternal函数这里打下断点,开启调试:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

F7步入即可看到,由于我们请求的/hax不存在,因此直接分发至PageNotFoundController来处理:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

如果我们请求的是/app/rest/server,那么就就会分发至UnauthorizedErrorController

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

F8接着往下走,经过函数updateViewIfRequestHasJspParameter的时候应该警觉起来,从函数的名字来看,意思就是看请求是否有JSP字段也就是有没有?jsp=xxx,如果有,那就更新view

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

果断F7进去看看,程序从requestjsp字段拿到了一个viewName也就是/app/rest/server;.jsp

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

继续F8,我们希望看到的是获取到了新的View之后的渲染过程,因此我们步入processDispatchResult这个函数:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

继续F8即可看到我们期待的render函数:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

步入之后F8继续走,我们希望了解的是/app/rest/server;.jsp是如何被处理的,因此我们步入resolveViewName函数:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

出现两个紫色快,左键点击第一个即可步入resolveViewName

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

里面的逻辑比较简单,就不细说了,返回结果是一个JstlViewview

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

官网里面讲的很清楚,内部资源视图解析器InternalResourceViewResolver会将视图名称viewName解析为JSP文件的路径,并将其包装在一个RequestDispatcher对象中,然后将请求发送到该RequestDispatcher,从而执行JSP的渲染过程;比如我们之前所看到的404.jsp解析成404.html

https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-servlet/viewresolver.html

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

继续F8往下走,我们还是点击render步入:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

继续走,F7步入renderMergedOutputModel函数:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

步入getRequestDispatcher函数,字面意思就是获取RequestDispatcher的过程:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用
JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

左键单击第二个步入:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

接着一步步按F7,来到org.apache.catalina.core.ApplicationContext#getRequestDispatcher,可以看到就是在这一步传入的路径进行了处理,把本来不存在的/app/rest/server;.jsp变成了存在的/app/rest/server,这样就可以更改正在处理urlDispatcherServlet,从而实现可以访问任意端点:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

但是分析到这里,还是没有说清楚一个关键的事情,那就是为什么我们访问一个不存在的uri,例如这里的/hax,他就会不进行鉴权呢?要搞明白这个事情就得去调试jetbrains.buildServer.controllers.interceptors.RequestInterceptors#preHandle这个方法,我调试的时候访问了不存在的uri,这里显示var4.size() == 1,然后进入多个interceptorprehandle方法。

调试的时候发现,由于反编译失败,很多代码都看不了,但是可以确定的是,uri不存在导致它们的判断的结果都为true,导致最终applyPreHandle的结果为true。这个地方后面需要再研究,如果有想法的师傅也可以直接留言交流,谢谢指教。

三、漏洞利用

主要有两个RCE方法,一个是请求/app/rest/debug/processes,另一个是后台构造上传恶意插件传webshell

但是由于之前的CVE-2023-42793,因此官方直接删除了这个端点,也就是2023.11.x之后的版本都只能考虑第二个方法,参考:

https://youtrack.jetbrains.com/issue/TW-85379

这部分通过抓包就可以写出来。但是当我传完behinder3.0shell后,发现无法连接,抓包发现提示403

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

尝试替换:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

发现没用,还是403

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

尝试删除X-Tc-Csrf-Token,还是403:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

继续删除Cookie,直接500

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

这时候我还没看代码调试,从之前的报错CSRF Header X-TC-CSRF-Token does not match CSRF session value猜想是session对应一个csrf token。尝试从浏览器访问目标,然后获取自动生成的TCSESSIONID

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

然后拿到403报错后的csrf_token

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

进行替换,发现冰蝎3连上去了:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

到这里我以为再添加个自定义请求头应该就可以访问了,结果还是不行:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

原来这冰蝎3没给你加cookie,我尝试手动添加,发现还是不行:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

原来这里会有两个,一个是识别到cookie字段后冰蝎加的,另一个是我们自定义的。

由于之前我一直没关注冰蝎4,所以这个地方我想了挺久,准备自己动手改冰蝎源码了,直到我看到了冰蝎4的changelog

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

结束!

我写的脚本地址如下:

https://github.com/W01fh4cker/CVE-2024-27198-RCE

到此,就可以实现任意版本的TeamCity漏洞存在即可打了:

JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用
JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用
JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

rapid7的博客中说,插件即使删除也会因为只有先禁用才能删除这个特性导致插件会在disabled-plugins.xml中留下永久的一条,比如C:ProgramDataJetBrainsTeamCityconfigdisabled-plugins.xml

<?xml version="1.0" encoding="UTF-8"?>
<disabled-plugins>
  <disabled-plugin name="WYyVNA6r" />
</disabled-plugins>

我测试之后发现不太对,可以直接删除,但是需要对teamcity进行重启,而先禁用再删除则不需要重启。

关于teamcity的后渗透的东西,可以参考:

https://github.com/kacperszurek/pentest_teamcity


原文始发于微信公众号(追梦信安):JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月12日10:06:34
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JetBrains TeamCity权限绕过(CVE-2024-27198)分析与利用https://cn-sec.com/archives/2568559.html

发表评论

匿名网友 填写信息