- 개요
Apache Web Server와 연동하기 위해 사용되는 Tomcat AJP(Apache Jserv Protocol) 프로토콜에서
입력 값 검증 미흡으로 인해 임의의 파일 읽기, 잠재적인 원격 명령어 실행 취약점이 발생합니다..
- 취약한 버전
Tomcat 6.x (EOS), 7.0.0 ~ 7.0.99, 8.5.0 ~ 8.5.50, 9.0.0 ~ 9.0.30
- 취약점 설명 및 분석
먼저 입력 값 검증에 대한 패치 노트는 아래와 같습니다. AbstractAjpProtocol.java 파일이며
Attributes에 대한 검증을 추가한 것으로 보입니다.
tomcat에서 AJP 메시지를 처리할 때 AjpProcessor.java의 prepareRequest()가 호출되고
request 객체를 Attribute로 설정합니다.
request 메시지 헤더에서 파일 확장자를 확인하여 *.jsp 는 jspServlet.java에서 처리하며
다른 파일은 DefaultServlet.java에서 처리합니다.
AJP 메시지를 처리하는 프로세스는 간단하게 다음과 같습니다.
prepareRequest() (Set Attributes) -> getAdapter() -> URL parsing, if *.jsp ->
JspServlet.java -> service() -> serviceJspFile()
위 프로세스에서 사용되는 SC_A_* attribute는 아래와 같습니다. 사전에 정의되지 않은
attribute를 사용하는 경우 SC_A_REQ_ATTRIBUTE로 설정되게 됩니다.
Request Attribute가 SC_A_REQ_ATTRIBUTE라면 attribute_name과 attribute_value를
n, v 값으로 설정하고 Request 메시지를 캡슐화 하여 getAdapter() 함수를 통해
Servlet 과정으로 전송합니다. 이 과정에서 n, v값에 대한 검증이 없기 때문에 취약점이 발생합니다.
일반 파일의 경우 위와 같은 request가 DefaultServlet.java에서 처리합니다.
해당 파일의 service() 함수에서 doGet() 함수가 호출됩니다.
doGet() 에서는 serveResource() 함수를 호출합니다.
serveResource() 함수에서 getResource() 함수를 호출하며 해당 함수는 경로에 맞는 파일의 실행 결과를 가져옵니다.
JSP 파일은 JspSevlet.java에서 request를 처리하며 request에 정의되어 있는
servlet_path attribute를 jspUri에 넣고, serviceJspFile함수에서 해당 경로에 있는
파일의 리소스를 가져와 컴파일러에 전송되어 실행 결과가 server에 보내집니다.
따라서 attribute_name, value 값을 임의로 지정한 후 request uri 를 *.jsp로 지정했을 때
potential remote code execution이 가능하며 *.jsp가 아닐경우 arbitrary file read 가 가능합니다.
arbitrary file read 같은 경우 webapps/ROOT/ (Home Directory) 하위의 모든 파일을 읽을 수 있습니다.
- WEB-INF/web.xml
Potential RCE 같은 경우 file upload가 가능할 때 발생합니다.
file upload는 되지만 webshell 파일의 확장자 검증이 존재할 때 아래와 같은 jsp 구문을
text 파일로 업로드한 후 실행시켜 Reverse shell을 획득할 수 있습니다.
- Get Reverse shell
- 위협요소
인증되지 않은 사용자가 웹 설정 파일, 소스코드 파일을 전부 탈취할 수 있으며 잠재적으로 Remote Code Execution이 가능해 Server의 shell 권한을 탈취당할 수 있습니다.
- 대응방안
1) Tomcat Version Update
6.x 는 기술 지원이 끝났기 때문에 major version을 올려야 합니다.
7.0.100
8.5.51
9.0.31
2) AJP Protocol 비활성화
3) AJP Protocol을 사용해야 할 경우 requiedSecret 설정