
Coisas divertidas contra o abuso da recente vulnerabilidade CVE-2021-44228 (Log4Shell) usando servidores web comuns.
Coisas divertidas contra o abuso da recente vulnerabilidade CVE-2021-44228 (Log4Shell) usando servidores web comuns.
Baseado no post de @shipilev (https://gist.github.com/shipilev/92e709a868f3d328b6636e1bfc21cf09) portei o exemplo dele para o Apache2. Um colega de trabalho fez o mesmo para o Lighttpd. Decidi tornar nossos exemplos públicos por conveniência.
Existem poucos motivos para colocar a string "jndi:" em cabeçalhos de requisição, User Agents ou em qualquer outro lugar. Atualmente, só conheço um único motivo para fazer isso: a exploração do CVE-2021-44228. Enquanto o mundo está, esperançosamente, ocupado corrigindo todas as implementações de versões vulneráveis do Log4j, pode ser razoável desacelerar os atacantes o máximo possível. Que tal, então, servir a eles alguns gigabytes de nonsense enquanto tentam explorar seus serviços?
Os trechos de código a seguir não protegem seus dispositivos e serviços contra o 0-Day Log4Shell! Atualize o software vulnerável, use log4j2.formatMsgNoLookups=true para desabilitar os jndi-Lookups ou coloque-o offline até que haja um patch disponível! Use isso apenas em servidores sem serviços habilitados para Log4j! Mais informações sobre como mitigar o CVE-2021-44228: https://research.hisolutions.com/log4shell
Isso também não cobre chamadas ofuscadas como ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://${hostName}.} ou qualquer outra coisa que tente esconder a parte "jndi:". Como não há uma solução simples para isso, não abordarei técnicas de detecção mais avançadas no momento. Ainda acredito que a maioria dos ataques não usará essas técnicas, então ainda podemos irritar a maioria dos script kiddies. :)
No Linux, crie um arquivo com alguma mensagem HTML aleatória. Por favor, não use o LOL do exemplo abaixo, pois isso facilita para o atacante implementar um filtro genérico para nos evitar. Estamos usando o utilitário pv para exibir o progresso da criação do arquivo; talvez você precise instalá-lo via seu gerenciador de pacotes favorito ou simplesmente omiti-lo.
$ 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
Supondo que seu servidor web execute como www-data, vamos criar um diretório pertencente a www-data para não precisarmos enviar uma cópia para cada webroot que o servidor web possa estar servindo:
mkdir /bombs
mv 10G.boomgz /bombs
chown -R www-data:www-data /bombs
Agora vem a parte divertida...
Veja https://gist.github.com/shipilev/92e709a868f3d328b6636e1bfc21cf09
Todos os créditos vão para @shipilev
Ative os módulos necessários
a2enmod rewrite headers ratelimit
Navegue até /etc/apache2/sites-enabled. Abra cada arquivo de configuração de host com seu editor favorito e insira o seguinte trecho de código logo acima de cada linha contendo (pode haver mais de uma):
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>
Você pode estar se perguntando por que há muito mais variáveis do que no exemplo inicial de @shipilev. Decidi tentar capturar o maior número possível de locais. Isso pode interromper serviços em alguns casos raros, então, se quiser usar o conjunto original de verificações, basta comentar ou excluir as primeiras 7 linhas após a instrução RewriteEngine On e remover as partes |\${\${ das linhas restantes.
Você também pode colocar o código em um novo arquivo, por exemplo /etc/apache2/conf-available/anti-jndi.conf, e incluí-lo assim:
Include /etc/apache2/conf-available/anti-jndi.conf
Agora salve o(s) arquivo(s) e recarregue a configuração do Apache2:
systemctl reload apache2
Se tudo correu bem, você não deve receber uma mensagem de erro.
Em breve
Você pode verificar se obteve sucesso conectando-se ao seu site modificado via curl (lembre-se de substituir your-hostname pelo hostname real de um dos serviços que você acabou de editar):
curl -s -L your-hostname -A "\${jndi:testing}" | pv > /dev/null
Você deve ver uma barra de progresso, mostrando cerca de 100kb/s de velocidade de download. Se você não cancelar, deve terminar após alguns minutos, dependendo do que você usou como string no arquivo HTML inicial. Para mim, levou cerca de 5 minutos. Agora verifique o que está acontecendo no lado do cliente:
curl -s --compressed -L your-hostname -A "\${jndi:testing}" | pv > /dev/null
Viu como não são mais 100kb/s? A compactação faz sua mágica, são alguns gigabytes no lado do cliente. Então, depois de baixar uma pilha de nonsense por alguns minutos, o atacante fica com alguns gigabytes sobrando, caso os dados sejam armazenados para análise. Quem sabe? :)