こんにちは。SIOS OSSエバンジェリスト/セキュリティ担当の面 和毅です。
12/10/2021にApache Log4jの任意のコード実行の脆弱性(Log4Shell: CVE-2021-44228)が公開され、引き続いてCVE-2021-45046や、log4jv1の脆弱性CVE-2021-4104, CVE-2021-42550 も出ており、攻撃も既に観測されています。さらに先程CVE-2021-45105(DoS)も出てます。セキュリティ界隈の方々や開発者、運用者含めてITエンジニアの方々は、先週から本件でかなり振り回されていると思います。
ここでは、本件の脆弱性のPoCをSELinuxで保護できるか、またiptablesで保護できるかどうかを確認し、その結果を考察したいと思います。
【2021/12/26 13:00追記】SIOS Security ChannelでのPoC動画を追記しました。
PoC
Log4Shell (CVE-2021-44228) PoC
早速、PoCを実行したいと思います。PoCのコード自体は本記事では詳しく説明しません(GitHubなどで見ることが出来ます)。本PoCも、公開されているコードを流用しています。
環境
仮想環境でPoCを実施しました。
- 脆弱性があるサーバ(centos8.localdomain: 172.16.148.149)
- OS: CentOS 8(Stream)、最新版
- Java: jdk-8u20-linux-x64.tar.gz
- Tomcat: tomcat-9
- log4j: apache-log4j-2.14.1-bin.tar.gz
- 環境:tomcatからlog4jをキックして、logs以下のcatalina.outを外部のrsyslogサーバに転送している)。
- 攻撃元(client: 172.16.148.133)
- OS: Debian 11
- PoCコード(LDAPサーバとJava: jdk-8u20-linux-x64.tar.gzで作成したシェル起動プログラムで構成されている)
- 環境:Python用のpwncatで別ターミナルで待ち受けている
PoC
- CentOS 8(centos8.localdomain)上でSELinuxを有効にした状態でPoCを実施します。Tomcatでログインを行う際にユーザアカウントとして攻撃コード(${xxx:xxx://172.16.148.133/XXX})を指定してログインを行います。
- catalina.outに攻撃コードがERRORログとして上がってきます。
- 攻撃が成功し、リモートの攻撃者(Debian11: client)のpwncatの方でcentos8.localdomainのコンソールを開くことが出来ます。コンソール上でのコマンドですが、idコマンドでは
と、SELinuxは有効(Enforcing)になっているにも関わらず攻撃は成功しており、攻撃用のjavaプログラムを経由して開いたシェルはtomcatユーザ・unconfined_service_tドメインで動作していることがわかります。
PoCの考察(SELinux及び一般のrwxについて)
ここで前項の結果の考察ですが
- SELinuxを有効にしていたとしても、この攻撃を防ぐことは出来ません。
- しかし、攻撃結果から、「log4jをキックしている親プロセスの権限(uid, gid, SELinux context)を継承している」ことがわかります。
- そこでもし仮に、「log4jを適切なUIDで動くようにしていれば(つまり、親プロセスのJavaプログラムをrootなどではなく専用のユーザで動作させるようにさせていれば)被害を局所化出来る」事がわかります。
- また仮に「(デフォルトのSELinuxポリシではダメですが)log4jをキックするプログラムのSELinuxドメインを適切に遷移させて、例えばtomcat_log4j_tドメインみたいな形に遷移するようなポリシを書いて実装させていれば」被害を局所化出来ていたであろうことが考えられます。
つまり、ひとえに「Linuxでプログラムを動作させるときには、「LinuxのUID/GIDを(そして、出来ればSELinuxを有効にしてドメイン分離も)きちんと考えて実装させる」事を心がければ、今回のようなケースでも、被害は完全には防げませんが被害範囲を局所化出来るのでしっかり考えましょう」という事になります。
追記:PoC: iptablesでなんとか出来ないか
今回の攻撃は、被害者になるサーバ上で、OUTBOUNDのLDAPを制限すれば攻撃を防げるかと思いまして実験してみました。
環境は上記の環境を用います。
- まず、被害者のマシン(centos8.localdomain)上でiptablesのOUTBOUND(LDAPSと仮定して1389)を制限します(書き方は粗っぽいです)。
- 攻撃側(client)から攻撃を加えると、Port 1389への通信をDropしているので、攻撃は成功しませんでした。
- 攻撃側(client)で、Port 4444への通信をPort 1389へフォワードするようにiptablesを書いてあげます(設定は悪用を防ぐため、念の為に載せません)。
- 攻撃側(client)で、今回の攻撃をPort 4444で受けるようにして攻撃が成功しました。
この様に、単に被害者のサーバ上でLDAP/LDAPSのOUTBOUNDをiptablesで塞ぐ場合には、攻撃者が容易に迂回してしまうことがわかります。被害者側でiptablesで防ぐ場合には、こちらのVMWare社のワークアラウンドにあるように不達のIPは全て防ぐなど、もう一捻り必要になりそうです。
日々のメモを更新しています。
セキュリティ関係ニュースを更新しています。個別で情報出せるようになる前の簡単な情報・リンクなんかも載せていきます。
セミナー情報1
2021/10/22日に大阪商工会議所様が開催致しました「BCP・サイバーセキュリティセミナー「やってはイケナイ」をやってみる!」ですが、Youtube動画が公開されています。筆者も登壇しましたので、ご興味がありましたらぜひ見て下さい。