Log4J 취약점에 대해서
이번에 어떤 의미에서 시스템 보안 역사상 최악의 취약점이라 불리는 상황이 벌어졌다. 뭐 말이 너무 거창하기는 하지만 시스템을 개발하고 운영하는 입장에서 봤을 때 최악의 상황까지 갈 수 있는 문제점이 발견되어서 각 언론에서 난리다. 여러 업체들이 대응전담반까지 만들어서 조직적으로 취약점 대응을 하고 있는 상황이기도 하고 말이다.
Log4J, 혹은 Log4Shell 취약점이라고 불리는데 일반적으로 설명하기는 좀 어려운 내용임은 분명하다. 개발 관련 내용이고 프로그램을 만드는데 있어서 코딩 관련 영역이기 때문이다. 그리고 자바(Java) 언어 관련 부분인지라 내가 그동안 사용해온 언어도 아니어서 말이지.
하지만 내용은 얼추 알고 있으며 얼마나 위험한 문제점인지도 알고 있어서 기록 차원에서 한번 정리를 해볼까 한다. 참고로 이 취약점은 CVE-2021-44228로 취약점 보고가 되었기 때문에 자세한 내용은 해당 링크에 들어가서 확인해보는 것도 좋을 듯 싶다. 기술적인 내용이라서 보기가 어려울 수 있겠지만서도.
Log4J는 무엇?
일단 Log4J가 무엇인지 좀 살펴보자. 자바를 위한 로그 라이브러리인데 로그는 말 그대로 기록을 위한 것으로 개발자든 운영자든 보기 편한 형식으로 내용을 기록하는 것을 의미한다. 뒤에 4J는 for Java의 약자로 보면 된다.
Log4J 라이브러리는 아파치 재단에서 제공하는 오픈소스 라이브러리이기 때문에 수많은 자바 솔루션에서 사용된다. 우리나라의 전자정부프레임워크(eGovFramework)에서도 Log4J 라이브러리를 로그 기능용으로 제공하고 있을 정도다.
자바에서 제공하는 System.out.Println과 같은 기본 명령어를 사용할 수도 있지만 좀 더 편하게 기록을 남기기 위해서 log.info와 같은 Log4J 라이브러리에서 제공하는 명령어를 많이 쓴다. 해당 명령어를 이용하면 Log4J에서 지정한 파일로 내용을 손쉽게 남길 수 있기 때문이다.
참고로 자바의 기본 명령어들을 이용해서도 파일에 내용을 남길 수 있지만 해야 할 작업들이 좀 많고 귀찮다. Log4J 라이브러리에서 제공하는 명령어들은 이런 귀찮은 작업들을 대부분 라이브러리에서 처리해주기 때문에 편하게 사용할 수 있다. 그래서 많이 사용되는 것이다.
그렇다면 Log4J 라이브러리에 대해서 얼추 알았으니 어떤 취약점이 발견되었는지 살펴보자.
그렇다면 어떤 문제가?
이번에 발견된 Log4J 취약점은 Log4J 명령어를 이용할 때 단순히 Log4J 명령어 뒤의 내용을 그대로 파일이나 지정된 매체에 기록하면 되는데 그렇게 하지 않고 먼저 Log4J 명령어 뒤의 내용을 분석해서 실행할 수 있는 내용이라면 실행을 한다는 것을 악용하는 것이다.
예를 들어, (이건 말 그대로 예일 뿐이며 이대로 되는 것은 아니지만) log.info("Debug: {}", str)이라고 코딩이 되어 있는 상태에서 str의 내용에 실행가능한 파일 이름이 있을 경우(a.exe와 같은) 'Debug {a.exe}'라고 파일에 쓰기 전에 a.exe를 먼저 실행할 수 있다는 얘기다.
내용을 분석해서 해당 내용에 대해서 수행할 수 있는 구문이면 수행을 먼저 진행한다는 얘기다. 예시로 실행파일 이름을 넣었는데 그게 아니라 만약 외부 웹서버에서 프로그램을 다운로드 받는 구문을 넣는다면 어떻게 될까?
해커가 해킹 프로그램을 HTTP를 통해서 다운로드 받겠끔 해뒀을 때 웹서버에서 어떤 주소를 호출하고 그 뒤에 해킹 프로그램의 위치를 넣은 다음에 웹서버의 프로그램 중에서 Log4J 라이브러리를 통해서 주소 뒤의 내용을 로그로 남기도록 코딩을 했다면?
그 다음에 다운로드 다 한 후 마찬가지의 방법으로 해킹 프로그램을 실행하도록 주소 호출 뒤에 해킹 프로그램 실행 명령을 넣는다면?
위의 방식으로가 가능할지 모르지만 일단 알려진 Log4J 취약점의 내용이라면 위의 2가지 행위로 해커는 자바로 만들어진 웹서비스에서 자신이 원하는 해킹 프로그램을 해당 웹서비스의 웹서버에 다운로드시켜 실행시킬 수 있다는 얘기다.
로그 관련 명령은 프로그램 중간중간에 수많이 적용된다. 지속적으로 단계별로 내용을 확인해야 하기 때문에 로그 관련 명령을 많이 사용한다는 얘기다. 한두군데 쓰이는 것이 아니라는 얘기다. 즉, 자바로 만들어진, 그리고 Log4J 라이브러리를 통해서 로그를 남기는 시스템은 죄다 문제가 된다는 얘기다.
그리고 프로그램 안에서 외부로부터의 어떤 입력에 대해서 나름 방어를 한다고 하더라도 입력 등의 행위에 대한 로그를 남기는 부분에서 문제가 생겨버리기 때문에 보안 작업이 무용지물이 되어버리는 경우도 생길 수 있다는 것이 가장 큰 문제라고 할 수 있다.
이런 문제가 일어나는 이유는 Log4J 라이브러리에서 제공하는 Loopups(룩업) 기능 때문이다. 특히 JNDI 룩업 기능을 통해 위에서 언급한 공격이 가능하다.
룩업 기능은 앞서 언급한 것처럼 내용을 분석해서 실행 가능한 구문인지 판별하고 실행하는 기능이며 JNDI는 Java Naming and Directory Interface의 약자로 분산시스템에서 다른 시스템의 자원을 가져오는데 사용하는 방식이다.
즉, JNDI 룩업 기능은 다른 시스템으로부터의 자원(프로그램이 되었던 프로세서가 되었건간에)을 가져와서 이용하는 방식이기 때문에 위의 실행파일을 실행하거나 다른 웹서버에 있는 파일을 접속하거나 가져올 수 있다는 것이다.
엄밀히 따지면 실행하는 것은 아니고 자바의 경우 클래스를 이용해서 자원을 관리하는데(정확하지는 않지만) 외부 클래스를 가져와서 사용할 수 있는데 해당 외부 클래스 안에 명령어들 중에서 외부 파일을 가져오거나 실행하는 명령(함수)이 있을 수 있다는 얘기다.
더 깊게 얘기하자면 너무 어려워질 것 같아서 이정도로만 정리하는데 어찌되었던 지금의 시스템이 아닌 다른 외부의 시스템(인터넷을 포함한 네트워크로 연결된)의 자원을 갖다쓸 수 있는데 이게 로그 라이브러리를 통해서 실행될 수 있으며 악용되면 앞서 언급한 것처럼 엄청난 문제가 될 수 있다는 것이다.
앞서 언급했듯 대부분의 자바를 이용한 시스템에서 Log4J를 사용하고 있으며 전자정부프레임워크에서도 제공하기 때문에 국내의 경우 상당수의 웹서비스에서 문제가 될 수 있는 상황이다. 그렇기 때문에 어떤 의미에서 최악의 취약점 발견이라고 하는 것일지도 모르겠다.
해결 방법은?
일단 해결 방법으로 제시되는 것은 JNDI 문제점이 해결된 Log4J 라이브러리로 업데이트 한 후 다시 재컴파일 및 재기동을 하는 방법, Log4J의 룩업 기능을 중단하는 방법 등이다.
솔직히 로그 기록 라이브러리의 기능에 지정된 파일이나 매체에 내용을 기록만 하면 되지 룩업 기능을 왜 제공하는지는 모르겠다. 아마도 만들 때 필요가 있었기 때문에 넣었을테지만 용도를 벗어난 기능이고 결국 이 기능이 악용되어서 이런 사태를 만들었다고 보기 때문이다.
일반 사람들에게는 그닥 와닫지 않는 내용일 수 있지만 개발자나 운영자 입장에서는 상당히 심각한 문제로 다가올 수 있는 내용인지라 어렵더라도 기록 차원으로 정리를 해봤다.