CVE 2024-23897
jenkins에서 발견된 CLI command 취약점
Jenkins 2.441 하위 version에서 발생
Kali linux에 docker로 Jenkins를 설치하여 CVE test를 진행해보자
Jenkins docker 설치 시 사용 command
docker pull jenkins/jenkins:2.440-jdk17
docker image ls
docker run -p 8080:8080 jenkins/jenkins:2.440-jdk17
docker ps ls

설치 후 Jenkins 시작 시 입력하는 AdminPassword를 입력해주자

비밀번호 입력 후, 해당 경로로 jar 파일을 다운로드 받자
localhost:8080/jnlpJars/jenkins-cli.jar

해당 파일은 Jenkins command를 실행시킬 수 있는 파일로 Jenkins에서 사용하는 command를 입력하여
결과를 확인할 수 있다.
파일을 다운로드 받았으면 jar 파일을 실행시켜 사용가능한 옵션을 확인해보자

Jenkins CLI 실행
java -jar jenkins-cli.jar -s "http://localhost:8080" -http help 1 "@/etc/passwd"
java -jar jenkins-cli.jar -s "http://localhost:8080" -http help 1 "@/var/jenkins_home/secret.key"
위에서 확인한 옵션들을 바탕으로 jar 파일을 실행

/etc/passwd 파일과 secret key가 노출되는 것을 볼 수 있으나 제한적으로 확인 가능한 것을 볼 수 있다.
이제 Jenkins에서 지원해주는 command 중 connect-node를 사용하여 전체 파일을 확인해보자
java -jar jenkins-cli.jar -s "http://localhost:8080" -http connect-node "@/etc/passwd"

Error 발생 원인은 접근권한이 없는 아무 대상자들에게 읽기 권한을 허용하지 않았기 때문...! (한참 찾았다...)
만약 이를 허용하면 전체 파일 정보를 보여주게 된다.
(/etc/passwd 파일 노출)

이런 문제가 발생하는 이유를 하나씩 분석해보자
먼저 해당 링크를 통해 취약점 발생 순서를 파악하고
jenkins-cli.jar 파일을 Jadx로 확인해보자
https://www.trendmicro.com/ko_kr/research/24/c/cve-2024-23897.html
Jenkins Args4j CVE-2024-23897 Files Exposed Code at Risk
Jenkins, a popular open-source automation server, was discovered to be affected by a file read vulnerability, CVE-2024-23897.
www.trendmicro.com
https://github.com/kohsuke/args4j/blob/master/args4j/src/org/kohsuke/args4j/CmdLineParser.java#L331
args4j/args4j/src/org/kohsuke/args4j/CmdLineParser.java at master · kohsuke/args4j
args4j. Contribute to kohsuke/args4j development by creating an account on GitHub.
github.com
소스코드를 보니 해당 CVE 취약점은 HTTP, WebSocket, SSH를 통해 발생한다.

endopoint에서 Jenkins CLI를 통해 명령어 수행 시
두 개의 POST request를 시도한다. 밑의 예시를 보자
1. Upload
- 명령어를 포함시켜 전송하는 upload 요청
2. Download
- 명령어를 실행시키기 위한 download 요청

위의 그림처럼 두 번의 요청이 순서대로 진행되면 다음 메소드들을 순서대로 호출하는데
우리가 눈여겨 보아야할 메소드는
PlainCLIProtocol 과 CmdLineParser 메소드다.

PlainCLIprotocol Java class는 다양한 opcode들과 순차적인 프레임으로 구성된
특정한 binary format을 사용한다. Class 내부의 코드를 보면 다음과 같이 구성된 것을 볼 수 있다.

opcode의 true, false 값으로 어디서 전달되어지는 정보인지 파악할 수 있다.
이후, opcode의 정보를 CmdLineParser class로 전달하게 되는데
이 때, CmdLineParser class 내부에 있는 취약한 함수로 인해 parsing 과정에서 취약점이 발생하게 된다.
이 parsing 과정에 Args4J library를 사용하며 취약점 발생 분기는 바로 이 지점에서 발생한다.


expandAtFiles 함수에서 인자가 "@" 로 시작하는지 확인 후,
"@" 이후 경로에 있는 파일 내용을 읽어 인수로 추가하게 된다.
해당 분기문으로 인해 jenkins CLI 명령어로 expnadAtFiles 함수를 호출하고 인자를 제어하게 되는데
이 때, 임의의 파일을 읽을 수 있는 취약점이 발생한다.
그래서 위에서 보았듯 connect-node와 같은 jenkins CLI 명령어 옵션을 통해
내부 파일을 읽어낼 수 있었던 것이다.