본문 바로가기
INCOGNITO 2023

[WebSocket] Jenkins 보안 취약점 ( CVE-2024-23897 / CVE-2024-23898)

by hezin* 2024. 3. 7.

 

최근 Jenkins에서 공격에 취약한 서버의 데이터에 액세스하고 특정 조건에서 임의의 CLI 명령을 실행할 수 있는 두가지 취약점이 발견됐다.

Jenkins는 소프트웨어 개발, 특히 지속적 통합 (CI) 및 지속적 배포(CD)에 널리 사용되는 오픈소스 자동화 서버로, 애플리케이션 구축, 테스트, 배포 등 소프트웨어 개발 프로세스의 다양한 부분을 자동화하는데 중요한 역할을 한다.

 

 


 

첫번째 취약점인 CVE-2024-23897은 인증되지 않은 공격자가 제한된 양의 임의 파일 데이터를 읽을 수 있으며, 공격자가 Jenkins 서버에서 전체 임의 파일에 대해 "읽기 전용" 권한을 부여받을 수 있는 취약점이다. 그리고 공격자는 "읽기" 권한을 부여받는 취약성을 활용하여, 관리자에게 권한을 에스컬레이션하고 결국 서버에서 임의의 코드를 실행할 수 있게 된다.

읽기 전용 권한이 없는 공격자도 파일의 처음 몇 줄은 읽을 수 있으며, 그 수는 사용 가능한 CLI 명령어에 따라 달라진다.

 

두번째 취약점인 CVE-2024-23898은  CSWSH 취약점을 통해 피해자가 링크를 클릭하도록 조작하여 임의의 CLI 명령을 실행하도록 한다. 

 

 

배경

 

Jenkins는 "anyone can do anything" , "legacy" , "logged-in users can do anything" 과 같은 여러가지 권한 부여 방법을 제공한다. "logged-in users can do anything" 와 "legacy" 옵션은 익명 읽기 옵션을 허락하고, 모든 사람들에게 읽기 권한을 부여한다. 

이러한 읽기 전용 액세스를 통해 사용자는

- 기본 Jenkins API  및 액세스 권한이 있는 모든 개체의 API에 액세스

- 사용자 디렉토리에 액세스하여 표시되는 프로젝트에 관련된 모든 사람의 사용자 계정 및 ID를 나열

하는 식의 작업이 가능하게 된다.

그리고 관리자는 Jenkins 인스턴스에서 거의 모든 작업을 수행할 수 있는데, 공격자의 관점에서보면 관리자는 Jenkins 서버에서 임의의 코드를 수행하는 작업까지 가능하다.

 

 

 

 

Jenkins-CLI 기능

Jenkins-CLI 는 Jenkins Git 리포지토리의 hudson/cli 디렉토리에 구현된 사용자 지정 명령을 실행할 수 있는 기본 제공 명령줄 인터페이스를 사용자에게 제공한다.

Jenkins-CLI을 호출할 때는 일반적인 방법 외에도, WebSocket을 사용하는 jenkins-cli.jar나 SSH를 사용할 수 있다.

 

 

Stapler(method와 endpoint의 상관관계를 지정하는 Jenkins의 구성요소) 가 /cli 경로의 관련 메소드를 가져올 때, endpoint는 PlaincliEndpointResponse() 예외를 발생시키며, generateResponse 함수로 끝난다.

public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException {
    try {
        UUID uuid = UUID.fromString(req.getHeader("Session"));
        //...
        if (req.getHeader("Side").equals("download")) {
            FullDuplexHttpService service = createService(req, uuid);
            //...
            try {
                service.download(req, rsp);
            }
            //...
        } else {
            FullDuplexHttpService service = services.get(uuid);
            //...
            try {
                service.upload(req, rsp);
            }
            //...
}
}

 

이 CLI 기능을 사용하려면, 다운로더와 업로더가 필요하다.

다운로더는 명령의 응답을 반환하고, 업로더는 요청 본문에서 지정된 명령을 호출한다. Jenkins는 Session header의 UUID를 사용하여 다운로더와 업로더를 연결한다.

 


Data Leak Vulnerability (CVE-2024-23897)

 

: 인수와 함께 CLI 명령을 호출할 때, Jenkins가 expandAtFiles를 호출하는 args4j의 parseArgument를 사용한다.

 

private String[] expandAtFiles(String args[]) throws CmdLineException {
    List<String> result = new ArrayList<String>();
    for (String arg : args) {
        if (arg.startsWith("@")) {
            File file = new File(arg.substring(1));
            if (!file.exists())
                throw new CmdLineException(this,Messages.NO_SUCH_FILE,file.getPath());
            try {
                result.addAll(readAllLines(file));
            } catch (IOException ex) {
                throw new CmdLineException(this, "Failed to parse "+file,ex);
            }
        } else {
            result.add(arg);
        }
    }
    return result.toArray(new String[result.size()]);
}

 

이 함수는 인수가 @로 시작하는지 확인하고, @로 시작한다면 @ 뒤 경로에서 파일을 읽고, 각 줄에 대해 새로운 인수를 확장한다.

 

 

즉, 공격자가 인수를 제어할 수 있는 경우 Jenkins 인스턴스의 임의의 파일에서 임의의 수로 확장할 수 있게 되는데, 이 때 공격자가 임의의 수의 인수를 가져와서 사용자에게 다시 표시하는 명령을 찾는 것이다.

인수는 파일 내용에서 채워지기 때문에 공격자는 이러한 방식으로 파일 내용을 유출할 수 있다.

 

-> 인수가 '@' 문자로 시작할 때, 파일 내용을 명령 인수로 자동 확장하여 Jenkins 컨트롤러 파일 시스템에서 임의의 파일을 무단으로 읽을 수 있게 하는 Jenkins의 args4j 명령 파서의 기본 동작에서 비롯되는 취약점이다.

이러한 특정 취약점을 악용하면 관리자 권한 및 임의의 원격 코드 실행으로 이어질 수 있다.

 

 

Patch

Jenkins 보안팀은 "expandAtFiles" 기능을 비활성화하는 보안 구성을 추가하여 CVE-2024-23897을 패치했다.

+  public static boolean ALLOW_AT_SYNTAX = SystemProperties.getBoolean(CLICommand.class.getName() + ".allowAtSyntax");
//...
-    return new CmdLineParser(this);
+    ParserProperties properties = ParserProperties.defaults().withAtSyntax(ALLOW_AT_SYNTAX);
+    return new CmdLineParser(this, properties);

 


 

 

CSWSH Vulnerability (CVE-2024-23898)

 

Jenkins-CLI 명령을 호출하는 방법에는 WebSocket을 사용하는 방법이 있다

.

브라우저는 WebSocket에 SOP 및 CORS 정책을 적용하지 않는 것으로 알려져 있다.

WebSocket은 WS (WebSocket) 또는 WSS (WebSocketSecure) 프로토콜을 통해 작동하는 동안 HTTP 응답에 제한이 적용되기 때문에 SOP 및 CORS 정책에 의해 부과 된 교차 출처 제한은 WebSocket에 적용되지 않는다.

 

따라서 WebSocket 요청에는 CSRF토큰 또는 Origin 헤더 검사가 없으므로, 웹 사이트에서 WebSocket을 사용하여 CSRF 취약점과 유사한 방식으로 피해자의 ID를 통해 Jenkins-CLI 명령을 호출할 수 있다,.

 

 

Patch

WebSocket endpoint에 Origin 확인을 추가했다. 이 매개변수는 toggle 역할을 하여 관리자에게 기본 동작을 재정의할 수 있는 기능을 부여한다. Origin에 관계없이 WS CLI에 대한 액세스를 일관되게 허용하거나 거부하는 옵션을 제공한다.

 

 

public HttpResponse doWs(StaplerRequest req) {
    if (!WebSockets.isSupported()) {
        return HttpResponses.notFound();
    }
+    if (ALLOW == null) {
+        final String actualOrigin = req.getHeader("Origin");
+        final String expectedOrigin = StringUtils.removeEnd(StringUtils.removeEnd(+Jenkins.get().getRootUrlFromRequest(), "/"), req.getContextPath());
+
+        if (actualOrigin == null || !actualOrigin.equals(expectedOrigin)) {
+            LOGGER.log(Level.FINE, () -> "Rejecting origin: " + actualOrigin + "; expected was from request: " + +expectedOrigin);
+            return HttpResponses.forbidden();
+        }
+    } else if (!ALLOW) {
+        return HttpResponses.forbidden();
+    }
    Authentication authentication = Jenkins.getAuthentication2();

 

 

WebSocket은 Origin 헤더의 문제와 관련한 CSWSH 취약점이 다수 발생한다.

그 이유로는 WebSocket 이 일반 HTTP 요청과는 다르게 SOP에 의해 제한되지 않는 프로토콜이기 때문이라고도 볼 수 있다. 따라서, WebSocket을 사용하는 경우에는 서버 측에서 출처 검사 및 인증을 통해 취약점을 방지해야 한다.만약 출처 검사를 거치지 않고 WebSocket 연결을 하게 되면, 공격자가 다른 출처에서 WebSocket 연결을 통해 공격할 수 있다.

 

 

 

[참고 자료]

과도한 확장: Jenkins의 중요한 보안 취약점 발견 | 수중 음파 탐지기 (sonarsource.com)

 

Excessive Expansion: Uncovering Critical Security Vulnerabilities in Jenkins

This blog uncovers two vulnerabilities, a Critical and High severity, recently discovered by our research team. Exploiting these vulnerabilities, attackers have the potential to gain Remote Code Execution on a Jenkins instance.

www.sonarsource.com

중요한 Jenkins RCE 결함에 대한 익스플로잇 릴리스, 지금 패치 (bleepingcomputer.com)

 

Exploits released for critical Jenkins RCE flaw, patch now

Multiple proof-of-concept (PoC) exploits for a critical Jenkins vulnerability allowing unauthenticated attackers to read arbitrary files have been made publicly available, with some researchers reporting attackers actively exploiting the flaws in attacks.

www.bleepingcomputer.com