- vừa được xem lúc

CVE-2023-42793-TeamCity-Authentication bypass leading to RCE

0 0 3

Người đăng: Hoan Pham

Theo Viblo Asia

Giới thiệu

TeamCity là một máy chủ tích hợp liên tục và phân phối công cụ quản lý “build”. Nó tự động hoá các quy trình thông thường, sắp xếp hợp lý quá trình phát triển, cải thiện giao tiếp nhóm. TeamCity cải thiện khả năng giao tiếp của nhóm, giúp các nhóm phát triển triển khai dự án tốt nhất.

CVE-2023-42793

CVE-2023-42793 là lỗ hổng cho phép kẻ tấn công bypass authentication và lấy được quyền admin. Từ đó có thể RCE được hệ thống. alt text

Set Up

Mình sử dụng docker và debug ở cổng 5005

docker run -dt -p 8111:8111 -p 5005:5005 -e TEAMCITY_SERVER_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 jetbrains/teamcity-server:2023.05.3

Diff

Sau khi diff 2 bản mình nhận thấy đường dẫn wildcard đã bị loại bỏ trong jetbrains.buildServer.controllers.interceptors.RequestInterceptors. alt text

Authentication Bypass

Đặt debug tại jetbrains.buildServer.controllers.interceptors.RequestInterceptors#RequestInterceptorsmình xác nhận được XmlRpcController.getPathSuffix()) có giá trị là /RPC2(nguyên nhân dẫn đến lỗi này)
alt text
alt text
Trong quá trình khởi tạo RequestInterceptors, authorizedUserInterceptor được thêm vào myInterceptors. authorizedUserInterceptor sẽ thực thi kiểm tra xác thực của request.
alt text
Sau đó, khi phân tích file webapps\ROOT\WEB-INF\buildServerSpringWeb.xml mình nhận thấy calledOnceInterceptors là 1 instance của class jetbrains.buildServer.controllers.interceptors.RequestInterceptors.
alt text
RequestInterceptors sẽ chặn các HTTP requests thông qua hàm jetbrains.buildServer.controllers.interceptors.RequestInterceptors#preHandle

 public final boolean preHandle(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse, final Object o) throws Exception { try { if (!this.requestPreHandlingAllowed(httpServletRequest)) { return true; } } catch (final Exception ex) { throw ex; } final Stack requestIn = this.requestIn(httpServletRequest); Label_0134: { try { if (requestIn.size() < 70 || httpServletRequest.getAttribute("__tc_requestStack_overflow") != null) { break Label_0134; } } catch (final Exception ex2) { throw ex2; } RequestInterceptors.LOG.warn("Possible infinite recursion of page includes. Request: " + WebUtil.getRequestDump(httpServletRequest)); httpServletRequest.setAttribute("__tc_requestStack_overflow", (Object)this); httpServletRequest.setAttribute("javax.servlet.jsp.jspException", (Object)new ServletException("Too much recurrent forward or include operations").fillInStackTrace()); final RequestDispatcher requestDispatcher = httpServletRequest.getRequestDispatcher("/runtimeError.jsp"); try { if (requestDispatcher != null) { requestDispatcher.include((ServletRequest)httpServletRequest, (ServletResponse)httpServletResponse); } } catch (final Exception ex3) { throw ex3; } return false; } if (requestIn.size() == 1) { for (final HandlerInterceptor handlerInterceptor : this.myInterceptors) { try { if (!handlerInterceptor.preHandle(httpServletRequest, httpServletResponse, o)) { return false; } continue; } catch (final Exception ex4) { throw ex4; } } } return true; }

Nếu requestPreHandlingAllowed return false thì hàm preHandle sẽ return sớm, requestPreHandlingAllowed return true thì list myInterceptors sẽ được lặp lại cho từng request, bao gồm cả authorizedUserInterceptor sẽ kiểm tra xác thực của request.
Do đó nếu ta gửi được 1 request để requestPreHandlingAllowed return false thì ta sẽ bypass được xác thực. Sau khi kiểm tra hàm requestPreHandlingAllowed, mình nhận ra PathSet myPreHandlingDisabled chứa wildcard path /**/RPC2 do đã được thêm từ quá trình khởi tạo bên trên(this.myPreHandlingDisabled.addPath("/**" + XmlRpcController.getPathSuffix());) --> requestPreHandlingAllowed return false. Từ đó có thể bypass được xác thực

 private boolean requestPreHandlingAllowed(@NotNull final HttpServletRequest httpServletRequest) { try { if (httpServletRequest == null) { $$$reportNull$$$0(5); } } catch (final IllegalArgumentException ex) { throw ex; } try { if (WebUtil.isJspPrecompilationRequest(httpServletRequest)) { return false; } } catch (final IllegalArgumentException ex2) { throw ex2; } try { if (!this.myPreHandlingDisabled.matches(WebUtil.getPathWithoutContext(httpServletRequest))) { return true; } } catch (final IllegalArgumentException ex3) { throw ex3; } return false; }

alt text

Exploitation

Theo như những phân tích trên để các API có thể bypass được xác thực thì các endpoint đó phải cho phép tùy chỉnh hậu tố. Đầu tiên hãy cùng phân tích endpoint đã biết là /app/rest/users/id:1/tokens/RPC2. Endpoint này được khai báo tại jetbrains.buildServer.server.rest.request.UserRequest#createToken

 @POST @Path("/{userLocator}/tokens/{name}") @Produces({"application/xml", "application/json"}) @ApiOperation(value = "Create a new authentication token for the matching user.", nickname = "addUserToken", hidden = true) public Token createToken(@ApiParam(format = "UserLocator") @PathParam("userLocator") String userLocator, @PathParam("name") @NotNull String name, @QueryParam("fields") String fields) { if (name == null) { $$$reportNull$$$0(1); } TokenAuthenticationModel tokenAuthenticationModel = (TokenAuthenticationModel)this.myBeanContext.getSingletonService(TokenAuthenticationModel.class); SUser user = this.myUserFinder.getItem(userLocator, true); try { AuthenticationToken token = tokenAuthenticationModel.createToken(user.getId(), name, new Date(PermanentTokenConstants.NO_EXPIRE.getTime())); return new Token(token, token.getValue(), new Fields(fields), this.myBeanContext); } catch (AuthenticationTokenStorage.CreationException var7) { throw new BadRequestException(var7.getMessage()); } }

Endpoint này cho phép tạo token thông qua parameter name do đó kẻ tấn công có thể tạo được authentication token cho bất kỳ user nào. TeamCity cho phép chúng ta có thể cung cấp administrator user userLocator thông qua id của user. Do đó chúng ta có thể sử dụng id user đầu tiên là id:1 và tạo được token của admin.
POC: alt text
alt text

THAM KHẢO

https://attackerkb.com/topics/1XEEEkGHzt/cve-2023-42793/rapid7-analysis?referrer=etrblog
https://github.com/H454NSec/CVE-2023-42793

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tổng hợp các bài hướng dẫn về Design Pattern - 23 mẫu cơ bản của GoF

Link bài viết gốc: https://gpcoder.com/4164-gioi-thieu-design-patterns/. Design Patterns là gì. Design Patterns không phải là ngôn ngữ cụ thể nào cả.

0 0 277

- vừa được xem lúc

Học Spring Boot bắt đầu từ đâu?

1. Giới thiệu Spring Boot. 1.1.

0 0 257

- vừa được xem lúc

Cần chuẩn bị gì để bắt đầu học Java

Cần chuẩn bị những gì để bắt đầu lập trình Java. 1.1. Cài JDK hay JRE.

0 0 37

- vừa được xem lúc

Sử dụng ModelMapper trong Spring Boot

Bài hôm nay sẽ là cách sử dụng thư viện ModelMapper để mapping qua lại giữa các object trong Spring nhé. Trang chủ của ModelMapper đây http://modelmapper.org/, đọc rất dễ hiểu dành cho các bạn muốn tìm hiểu sâu hơn. 1.

0 0 180

- vừa được xem lúc

[Java] 1 vài tip nhỏ khi sử dụng String hoặc Collection part 1

. Hello các bạn, hôm nay mình sẽ chia sẻ về mẹo check String null hay full space một cách tiện lợi. Mình sẽ sử dụng thư viện Lớp StringUtils download file jar để import vào thư viện tại (link).

0 0 55

- vừa được xem lúc

Deep Learning với Java - Tại sao không?

Muốn tìm hiểu về Machine Learning / Deep Learning nhưng với background là Java thì sẽ như thế nào và bắt đầu từ đâu? Để tìm được câu trả lời, hãy đọc bài viết này - có thể kỹ năng Java vốn có sẽ giúp bạn có những chuyến phiêu lưu thú vị. DJL là tên viết tắt của Deep Java Library - một thư viện mã ng

0 0 124