2013年9月2日月曜日

ロリポップのサイト改ざん事件に学ぶシンボリックリンク攻撃の脅威と対策

既に報道されているように、ロリポップ!レンタルサーバーに対する改ざん攻撃により、被害を受けたユーザー数は8428件にのぼるということです。ここまで影響が大きくなった原因は、報道によると、(1)「WordPressのプラグインやテーマの脆弱性を利用」し、不正なファイルがアップロードされた、(2)パーミッション設定の不備を悪用されて被害が拡大した、ということのようです。
29日夜の時点では、攻撃者の改ざん手法について「WordPressのプラグインやテーマの脆弱性を利用」し、不正なファイルがアップロードされて「wp-config.phpの」の設定情報が抜き出されたと説明していたが、30日午後7時過ぎの説明で、この脆弱性が侵入経路となって同社のパーミッション設定の不備を悪用されたことが原因だったことを明らかにした。
「ロリポップ」のWordPressサイト改ざん被害、原因はパーミッション設定不備より引用
これ以上の詳細は本校執筆時点で公表されていないので憶測は控えますが、ロリポップからのリリースに以下の内容があることが気になるところです。
サーバーの設定を変更しFollowSymLinksを無効にしました。
当社サービス「ロリポップ!レンタルサーバー」ユーザーサイトへの第三者による大規模攻撃についてより引用
これは、httpd.confにて元々FollowSymLinksが有効になっていたか、レンタルサーバーの利用者が.htaccessによりFollowSymLinksを有効にできる状態であったという意味でしょう。この状況では、レンタルサーバーの悪意の利用者(サーバーへの侵入者を含む)が、同じサーバーを共有する別の利用者の秘密情報をシンボリックリンク攻撃により盗み読みすることができます。以下、シンボリックリンク攻撃の原理と脅威、対策について説明します。

デモ環境の説明

以下は、ロリポップに似せた設定の架空のレンタルサーバーのホームディレクトリ設定です。ユーザはsuzukiとtanakaで、それぞれsuzuki.example.jpとtanaka.example.jpがホスト名です。以下は、suzuki.example.jpの表示です。


ホームディレクトリの設定は下記となります。
$ ls -l
drwx-----x  3 suzuki      LolipopUser 4096 Aug 31 17:26 suzuki/
drwx-----x  3 tanaka      LolipopUser 4096 Aug 31 17:39 tanaka/
$
各利用者のホームディレクトリのパーミッションが701となっていて、同じグループ(LolipopUser)に属していますが、これはレンタルサーバー特有の設定です。これは、レンタルサーバーの利用者同士は同じグループに属するため、他のユーザのファイルにアクセスできず、apache等のサービスは、LolipopUserグループに属さないユーザの権限で動くため、各ユーザのファイルにアクセスできるという設定になっています。

レンタルサーバーの利用者間では、ファイルは閲覧できない

ここで、tanakaさんが、suzukiさんのファイルを閲覧できないことを示します。
$ su - tanaka
Password:  ←パスワードを入力
tanaka$ pwd
/home/tanaka
tanaka$ ls -l
total 8
-rw-r--r-- 1 tanaka LolipopUser  465 Sep  1 23:45 log.txt
drwxr-xr-x 2 tanaka LolipopUser 4096 Sep  1 23:39 www
tanaka$ ls -l ../suzuki/
ls: cannot open directory ../suzuki/: Permission denied  ← 別ユーザのディレクトリは参照できない
tanaka$ cat ../suzuki/www/index.html
cat: ../suzuki/www/index.html: Permission denied  ← 別ユーザのコンテンツも同様
tanaka$

閲覧権限がないファイルにシンボリックリンクを設定できる

ところが、tanakaさんは、suzukiさんのファイルに対してシンボリックリンクを設定することは可能です。
tanaka$ cd www
tanaka$ ln -s ../../suzuki/www/index.html suzuki.html
tanaka$ cat suzuki.html
cat: suzuki.html: Permission denied  ← シンボリックリンクは作れるが参照はできない
tanaka$
上記のように、シンボリックリンクは、権限のないファイルに対して設定することができます(存在しないファイルにも可)。上記のように、このシンボリックリンクを指定してもファイルを閲覧することはできませんが、apacheによる表示は可能です。apacheは、シンボリックリンク自体とリンク先の両方にアクセス権があるからです。


ただ、これだと、元々公開している情報を別のホストで表示しているだけなので、攻撃としての価値はあまりありません。問題は、この方法で以下が可能になる場合があることです。
  • CGIプログラムやPHPスクリプトのソースが閲覧できる
  • 非公開ディレクトリのファイルが閲覧できる場合がある

閲覧できない情報をシンボリックリンク攻撃により表示する

以下、これを試してみましょう。suzukiさんのホームページ上にメールフォームがあり、そのファイル名が inquiry.php であることが分かっているとします。以下のように、これに対して inquiry.txt というシンボリックリンクを設定します。
tanaka$ ln -s ../../suzuki/www/inquiry.php inquiry.txt
これを閲覧すると、下記となります。


拡張子を.txt に変更したことで、PHPスクリプトのソースが見えてしまっています。
実は、拡張子が.php のままだと、レンタルサーバー環境の場合、PHPスクリプトは実行できないと考えられます。レンタルサーバーの場合は、CGIプログラムやPHPスクリプトは、suEXECにより、各ユーザの権限で動作します。上記のシンボリックリンクの場合、tanakaの権限により、suzukiのスクリプトを実行しようとしますが、今まで見たように、tanakaの権限ではスクリプトファイルの読み込みができないからです。しかし、apacheの実行ユーザだと読み込み権限があるため、ソースの閲覧は可能です。
さて、上図のソースから、ログファイルが ../log.txt だと分かります。このファイルにもシンボリックリンクを設定して、閲覧できるか調べてみましょう。
tanaka$ ln -s ../../suzuki/log.txt log.txt
閲覧画面は下記となります。


上記のように、通常は閲覧できないディレクトリ上の、攻撃者に読み込み権限のないデータファイルも、シンボリックリンクを設定することで、外部から閲覧できることが分かりました。この際のlog.txtのパーミッションは下記となっています。
tanaka$ su - suzuki
Password:
suzuki$ ls -l log.txt
-rw-r--r-- 1 suzuki LolipopUser 465 Sep  1 23:45 log.txt
suzuki$
すべてのユーザーに対して読み込み権限が与えられています。これは、PHPスクリプトのfopenで作成したファイルに与えられるパーミッションですが、仮にアプリケーションの実行に最低限の権限(600)が設定されていたら、apacheから読み込むことができず、このファイルに対するシンボリックリンク攻撃は成立しません。

シンボリックリンク攻撃が成立する条件

冒頭に書いたように、シンボリックリンク攻撃が成立する条件は下記の両方が成立する場合です。
  • FollowSymLinksが有効になっているか、攻撃者が.htaccessによりFollowSymLinksを有効にできる
  • 攻撃者が、公開ディレクトリにシンボリックリンクを設定できる
通常のWebサーバーでFollowSymLinksが問題にならないのは、後者の条件が成立しないからです。一方、レンタルサーバーの場合は、以下のいずれかにより、攻撃者が公開ディレクトリにシンボリックリンクを設定可能です。
  • 攻撃者がレンタルサーバーのユーザとなる(お試し等でも可)
  • 攻撃者がレンタルサーバーのユーザtanakaを攻撃して、tanakaの書き込み権限を得る
通常のWebサーバーでも、攻撃者が書き込み権限を得ることはあり得ますが、他のユーザの権限を得る動機があまりないところが、レンタルサーバー環境との違いです。

シンボリックリンクを作成する時点で、相手側のディレクトリ一覧は参照できない場合が多いのですが、以下の手順でファイル名が推定可能です。
  • 外部公開のURLからファイル名を推定する
  • スクリプトのソースファイルからファイル名を得る
  • WordPress等の標準的なファイル構成からファイル名を得る

シンボリックリンク攻撃の脅威

一般的には、シンボリックリンク攻撃が成立すると、攻撃者の有する権限よりも高い権限を獲得することができます。上記の例では、攻撃者が持っているtanakaの権限に加えて、apacheの権限により、権限を持たないファイルも閲覧可能になります。
おおざっぱに言って、シンボリックリンク攻撃の影響は、ディレクトリトラバーサル攻撃の影響と似ています。

対策

一般に、シンボリックリンク攻撃が問題になる場合は、ファイルのオープン時にシンボリックリンクかどうかを確認して、シンボリックリンクの場合はエラーにします(参考)。apacheの場合は、FollowSymLinksを無効にすることで、これが実現できます。
しかし、これだけではだめです。攻撃者が.htaccessの設定で、FollowSymLinksを設定する可能性があるからです。このため、AllowOverride ディレクティブにて、Noneを指定するか、Options=にて、許可したいオプション(FollowSymLinks以外)を明示的に列挙する方法があります。
利用者側でシンボリックリンクを安全に設定したい場合は、SymLinksIfOwnerMatchを利用できます。これは、「シンボリック先のファイルまたはディレクトリが、 シンボリックリンクの所有ユーザ ID と同じ場合にのみシンボリックリンクを たどれるようにします。」というものです(参照)。
レンタルサーバーの利用者が上記を確認する方法についてはここでは説明しませんので、レンタルサーバー事業者に個別に確認いただくのがよいと考えます。レンタルサーバー事業者は、今回の事件を受けて、自社の設定状況と安全性を説明いただく(あるいは急いで設定を修正する)とよいでしょう。

まとめ

シンボリックリンク攻撃の脅威と対策について説明しました。これは、シンボリックリンクを悪用して、上位権限のプロセスにファイルをアクセスさせる手法です。前述のように、レンタルサーバー環境で、apacheのFollowSymLinksが有効な場合、シンボリックリンク攻撃が成立してしまいますが、これはレンタルサーバー利用者の中に悪意のユーザが存在する可能性があるからです。
似たような状況として、Androidアプリケーションがあります。Androidアプリケーションは、アプリケーション毎にLinuxのアカウントが割り当てられるので、悪意のアプリケーション(マルウェア)が端末に導入された場合、root権限で動作するプロセスに対してシンボリック攻撃を仕掛け、マルウェアがroot権限を奪取するような攻撃に使われます。

追記(2013/09/03 10:00)

さとうふみやすさんから、apacheの-FollowSymLinksでは、レースコンディションによりシンボリックリンク攻撃の防御が回避されてしまうという指摘をいただきました(参照: Apache HTTPD: `Options -FollowSymLinks` は不完全)。さとうさん、ありがとうございます。
これは、TOCTOU 競合状態という問題で、参考文献として紹介したJPCERT/CCのドキュメントでも言及されています。また、TOCTOU競合を避ける方法についても、同じJPCERT/CCの解説に、「POS35-C. シンボリックリンクの有無のチェック時の競合状態を避ける」として紹介されています。ただ、これはapache(などのhttpd)を開発する側でとれる対策で、apacheの利用者としては、apache側で対策してくれるのを待つしかありません。
さとうさんは、『この攻撃の根本的な対策方法は「シンボリックリンクを作らせない」 しかない』としていますが、これもなかなか難しいと思います。現在のレンタルサーバーの多くは、シンボリックリンク攻撃のTOCTOU競合については受容している(あきらめている)のだと理解しています。
利用者側でとれる対策としては、CGIやPHPのスクリプトや、これらからアクセスするファイルのパーミッションを600や400として、apacheから読み取らせないようにすることです。ただし、.htaccessや.htpasswdはapacheから読めないとまずいので、この方法では保護できません。
ということで、この問題が受容できない利用者は、さとうさんの言及されている「ユーザーごとに別権限の Web サーバーを立ち上げる」サービスを提供しているレンタルサーバーやVPSなどに移行するしかないと考えます。
(追記終わり)

参考文献

1 件のコメント:

  1. 僕のサイトにも、一日以上サービス停止してしまった

    返信削除

フォロワー