
일반적인 웹 서버를 이용해 최근 CVE-2021-44228 (Log4Shell) 취약점 악용에 대항하는 재미있는 것들.
일반적인 웹 서버를 사용하여 최근 CVE-2021-44228(Log4Shell) 취약점 악용에 맞서는 재미있는 방법입니다.
@shipilev의 게시물(https://gist.github.com/shipilev/92e709a868f3d328b6636e1bfc21cf09)을 기반으로 그의 예제를 Apache2로 포팅했습니다. 동료가 Lighttpd용으로 작업했습니다. 편의를 위해 저희 예제를 공개하기로 결정했습니다.
요청 헤더, User-Agent 또는 다른 어딘가에 "jndi:" 문자열을 넣을 이유는 거의 없습니다. 현재 제가 아는 단 하나의 이유는 CVE-2021-44228의 악용입니다. 세상이 취약한 Log4j 버전의 모든 구현을 패치하느라 바쁘기를 바라는 동안, 공격자를 최대한 느리게 만드는 것도 합리적일 수 있습니다. 공격자가 서비스를 악용하려는 동안 그들에게 수 기가바이트의 의미 없는 데이터를 제공하는 것은 어떨까요?
다음 코드 스니펫은 Log4Shell 제로데이(0-Day)로부터 여러분의 장치와 서비스를 보호하지 않습니다! 취약한 소프트웨어를 업데이트하고, log4j2.formatMsgNoLookups=true를 사용하여 jndi 조회를 비활성화하거나 패치가 제공될 때까지 오프라인 상태로 두세요! Log4j가 활성화된 서비스가 없는 서버에서만 사용하세요! CVE-2021-44228 완화 방법에 대한 자세한 정보: https://research.hisolutions.com/log4shell
또한 이는 ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://${hostName}.} 같은 난독화된 호출이나 "jndi:" 부분을 숨기려는 다른 모든 시도도 다루지 않습니다. 이에 대한 간단한 해결책이 없으므로 현재는 더 고급 탐지 기법을 다루지 않겠습니다. 그래도 대부분의 공격이 이러한 기법을 사용하지 않을 것이라고 믿기 때문에 여전히 대부분의 스크립트 키디들을 귀찮게 할 수 있습니다. :)
Linux에서 임의의 HTML 메시지가 포함된 파일을 생성하세요. 아래 예제에 있는 LOL은 사용하지 마세요. 공격자가 우리를 회피하는 범용 필터를 구현하기 쉬워지기 때문입니다. 파일 생성 진행 상황을 표시하기 위해 pv 유틸리티를 사용합니다. 선호하는 패키지 관리자로 설치해야 할 수도 있으며, 그냥 생략해도 됩니다.
$ awk 'BEGIN { for(c=0;c<10000000;c++) printf "<p>LOL</p>" }' > 100M.html
$ (for I in `seq 1 100`; do cat 100M.html; done) | pv | gzip -9 > 10G.boomgz
$ rm 100M.html
웹 서버가 www-data로 실행된다고 가정하고, www-data가 소유한 디렉터리를 생성하여 웹 서버가 제공할 가능성이 있는 모든 웹 루트에 복사본을 업로드할 필요가 없도록 합시다:
mkdir /bombs
mv 10G.boomgz /bombs
chown -R www-data:www-data /bombs
이제 재미있는 부분입니다...
https://gist.github.com/shipilev/92e709a868f3d328b6636e1bfc21cf09 참조
모든 크레딧은 @shipilev에게 있습니다.
필수 모듈을 활성화합니다
a2enmod rewrite headers ratelimit
/etc/apache2/sites-enabled로 이동합니다. 선호하는 편집기로 모든 호스트 구성 파일을 열고 **가 포함된 모든 줄 바로 위에 다음 코드 스니펫을 삽입합니다(두 개 이상일 수 있음):
RewriteEngine On
RewriteCond %{THE_REQUEST} "^.*(\${jndi|\${\${).*$" [OR]
RewriteCond %{QUERY_STRING} "^.*(\${jndi|\${\${).*$" [OR]
RewriteCond %{REQUEST_URI} "^.*(\${jndi|\${\${).*$" [OR]
RewriteCond %{HTTP_COOKIE} "^.*(\${jndi|\${\${).*$" [OR]
RewriteCond %{HTTP_HOST} "^.*(\${jndi|\${\${).*$" [OR]
RewriteCond %{REMOTE_HOST} "^.*(\${jndi|\${\${).*$" [OR]
RewriteCond %{REMOTE_USER} "^.*(\${jndi|\${\${).*$" [OR]
RewriteCond %{HTTP_USER_AGENT} "^.*(\${jndi|\${\${).*$" [OR]
RewriteCond %{HTTP_REFERER} "^.*(\${jndi|\${\${).*$"
RewriteRule . /bombs/10G_lol.boomgz [L]
<Files ~ "\.boomgz$">
Header Set Expires "Sat, 1 Jan 2000 00:00:00 GMT"
Header Set Content-Encoding "gzip"
Header Set Content-Type "text/html"
SetOutputFilter RATE_LIMIT
SetEnv rate-limit 100
</Files>
<Directory /bombs>
allow from allow
Require all granted
</Directory>
@shipilev의 초기 예제보다 변수가 훨씬 많은 이유가 궁금할 수 있습니다. 가능한 한 많은 위치를 포착하려고 결정했습니다. 이로 인해 매우 드문 경우 서비스가 중단될 수 있으므로 원래 검사 세트를 사용하려면 RewriteEngine On 문 뒤의 처음 7줄을 주석 처리하거나 삭제하고 나머지 줄에서 |\${\${ 부분을 제거하면 됩니다.
코드를 /etc/apache2/conf-available/anti-jndi.conf 같은 새 파일에 넣고 다음과 같이 포함할 수도 있습니다:
Include /etc/apache2/conf-available/anti-jndi.conf
이제 파일을 저장하고 Apache2 구성을 다시 로드합니다:
systemctl reload apache2
모든 것이 정상적으로 진행되었다면 오류 메시지가 표시되지 않습니다.
곧 공개 예정
curl을 통해 수정한 웹사이트에 연결하여 성공 여부를 확인할 수 있습니다(your-hostname을 방금 수정한 서비스 중 하나의 실제 호스트 이름으로 바꾸는 것을 잊지 마세요):
curl -s -L your-hostname -A "\${jndi:testing}" | pv > /dev/null
약 100kb/s의 다운로드 속도를 보여주는 진행률 표시줄이 표시됩니다. 취소하지 않으면 초기 HTML 파일에서 문자열로 사용한 내용에 따라 몇 분 후에 완료됩니다. 저의 경우 약 5분이 걸렸습니다. 이제 클라이언트 측에서 어떤 일이 발생하는지 확인합니다:
curl -s --compressed -L your-hostname -A "\${jndi:testing}" | pv > /dev/null
더 이상 100kb/s가 아니라는 게 보이나요? 압축이 마법을 부립니다. 클라이언트 측에서는 수 기가바이트가 됩니다. 따라서 몇 분 동안 의미 없는 데이터를 다운로드한 후, 데이터가 분석을 위해 저장된다면 공격자는 수 기가바이트를 보유하게 됩니다. 누가 알겠어요? :)