最近のCVE-2021-44228(Log4Shell)脆弱性の悪用に対抗するための、一般的なWebサーバーを使用した面白い対策です。
リクエストヘッダー、User-Agent、その他の場所に文字列 "jndi:" を入れる理由はほとんどありません。現在、それを行う理由として知っているのはただ一つ:CVE-2021-44228の悪用です。 世界中が脆弱なLog4jバージョンの実装を修正することに忙しいことを願いつつ、攻撃者の速度を可能な限り落とすことは合理的かもしれません。では、攻撃者があなたのサービスを悪用しようとしている間に、数ギガバイトの無意味なデータを送りつけてみてはどうでしょう?
以下のコードスニペットは、Log4Shell 0-Day からデバイスやサービスを保護するものではありません!脆弱なソフトウェアを更新し、log4j2.formatMsgNoLookups=true を使用して jndi-Lookups を無効にするか、パッチが利用可能になるまでオフラインにしてください!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
Web サーバーが www-data で実行されていると仮定して、www-data が所有するディレクトリを作成しましょう。そうすれば、Web サーバーが提供する可能性のあるすべての Web ルートにコピーをアップロードする必要がありません。
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ではないことがわかりますか?圧縮が魔法を発揮し、クライアント側では数ギガバイトになります。数分間無意味なデータの山をダウンロードした後、攻撃者の手元には数ギガバイトのデータが残ります(分析のために保存された場合)。誰が知っていますか? :)