LAMPセキュリティを強化する4つの方法
http://enterprisezine.jp/article/detail/311
書いてある情報は有用な事も記載されていますが、偏狭な視点からの記述により誤解を招く記事になっていると考えられます。著者はセキュリティの専門家ではないようなので仕方ないかも知れませんが、間違った認識は有害です。
# 原本は読んでいません。もしかすると日本語訳にも問題があるのかも知れません。
実行できる最も重要な対策は、PHPを使わないことです。腐った果物を導入する前に、以下に目を通してください。
後にPerl/Ruby/Pythonの方がかなり安全である旨の記述があります。メモリ管理が必要ない同じスクリプティング言語のレベルで「Perl/Ruby/Pythonを使えばセキュアなアプリケーションができる」と考えるのはナンセンスです。PHPを利用したシステムには、既知の脆弱性があるバージョンであったり、十分な安全性を保証できない構成である「腐った果実」が多いのも事実ですが、歴史が長いからそうなった側面もあります。同じような状況は他の言語でもあります。
古いTomcatアプリケーション等は好例でしょう。古いTomcatを運用されている方は、この著者がいう「腐った果実」状態にならないよう苦労されている事だと思います。後述しますが、あまり古く無いRailsでも同じです。
古くなると「腐った果実」になるのです。これはPHPに限りませんが、この記述だと「PHP=腐った果実」と誤解を与えると思われます。
著者はWebシステムを安易に利用するものでは無いことが言いたいのかも知れません。そういう事であれば同意できます。Webシステムは全般的に非常にセキュリティ問題に脆弱です。「良く使われているから」と安易にWebサーバを設置して、Webアプリケーションを運用すべきではありません。
著者はMonth of PHP Bugs(MoPB)等を参照して「PHPは他の言語より危険だ」と感じたのかもしれません。しかし、実際には、Perl/Ruby/PythonをPHPと同じようにWebサーバのモジュールとして利用し、共有するとPerl/Ruby/PythonはPHP以下の安全性しか提供できません。今の所、フェイルセーフ機能がPHPにはある分ましと言えると思います。
#「まし」とはいうだけで「安全」ではないので
# どんぐりの背比べですが。
PHPには入力のチェックに役立つツールがこれといってないため、独自の検証ルーチンを書く必要があります。
後ほど、MySQLのセットアップでchroot環境を利用してもセキュリティ上の意味が無いような記述がります。このため「taintモードがあるので検証ルーチンを書く必要がない」と主張しているとは思えません。とにかく、taintモードは検証ルーチンにはなり得ません。
# 後述しますが、MySQLセットアップでchrootを利用するのはセキュリ
# ティ上非常に有用です。これはchrootがセキュリティ対策として用い
# ても意味がない場合があることとは関係ありません。著者はこの事を
# 理解していない可能性があるように思えます。
PHPには無いですが、普通に取得できるフレームワークにはバリデーションコード(検証ルーチン)付いています。PEARのHTML_QuickFormには結構便利なバリデーション機能があります。AJAXには使いづらいですが、AJAX対応フレームワークにはバリデーションを用意している物がほとんどです。(無い物は知らないです)当たり前ですがPerl/Ruby/PythonにもWeb用のバリデーションコードが言語自体に付属していません。ライブラリは検証コードありますが「CGI.pmには検証ルーチンが付属しているので優れている」とするのはナンセンスです。どいう意味で「独自の検証ルーチンを書く必要があります」と書いてあるのか解らないのでコメントはこの程度にします。
Apacheのmod_phpを使ってPHPをApacheモジュールとして実行すると、Apacheプロセスのすべての資格情報がPHPに引き継がれます。つまり、Apacheが読み書きできるものは、PHPでも読み書きできます。これが意味するのは、PHPの乗っ取りに成功すれば、Apacheに直接乗り込んでいって、Apacheが接触するものならどこへでも入り込める、ということです。mod_phpを1人のユーザーしかいない単純なサイトで使うなら許せますが、多数のユーザーが共有するシステムの場合、すべてのスクリプトは同じApacheユーザーの下で実行されるため、これは大惨事を招きます。代わりに、PHPをsuEXECまたはCGIWrapの下で実行すべきです。これらのしくみは、Perl、Python、Rubyのような穏健なスクリプト言語でも利用できます。
これは多くのホスティングサービスがPHPをApacheモジュールとして提供しているので危険だ、と言いたいのでしょう。しかし、「安全なWebサービスを提供しよう」とするなら共有型のWebホスティングサービスを使う時点で間違っています。suEXEC, CGIWrapなどを使うのではなく、仮想プライベートサーバを利用するのが最低限のスタートラインです。
Perl/Ruby/Pythonはより安全な状態でのみ利用できるように読めてしまえるかも知れません。しかし、Perl/Ruby/PythonもApacheもモジュールとして動作させるオプションもあります。モジュールとして動作させた場合、PHPと何ら変わりありません。つまり、mod_phpで出きるようにmod_perl, mod_ruby, mod_pythonを使えばWebサーバのログを書き換えたり、メモリ参照が可能な関数を利用してSSLサーバ秘密鍵を盗むことはPHPだけの十八番ではありません。同じように使えば、同じ事なのです。
この記述を予備知識なしに読んだ方は「PHPの方が危険なんだ」と誤解すると思われます。
人知れずPHP3やPHP4を使い続けているサイトはたくさんあり、バグフィックスやセキュリティパッチをまったく適用していないサイトもそれ以上にたくさんあります。PHP5がリリースされたのは2004年で、PHP3のリリースともなると1998年までさかのぼります。
同じような状況はRubyやPerlに無いとでも思っているのでしょうか? PerlはWebスクリプティング言語として歴史が長く、人知れず古いPerl(+脆弱性満載のCGI)で動作しているサイトも沢山あります。もちろんシェアの関係で古いPHPを利用しているサイト数が圧倒的に多いとは思います。
もしかすると、歴史が長い事は悪いことだ、と言いたいのかも知れません。
全てのプログラムに言える事ですが、脆弱性がある古いプログラムを利用するのは良くない事です。これはPHPとそのスクリプトに限った事ではありません。例えば、比較的新しいと言えるRuby on Railsでも1.2.4以下にはセッション管理に問題があり、スピアフィッシングを行えば非常に簡単に他人のセッションを盗めてしまいます。先日、Webrickにディレクトリ遷移を利用した情報漏洩の脆弱性もレポートされています。放置すれば/etc/passwd等、重要な情報が簡単に取得できてしまいます。Javaなら大丈夫か、というとそうでもありません。JSPWikiと呼ばれるJavaベースのWikiには先日、任意JSPを挿入され実行されてしまう脆弱性が発見されました。Tomcatの脆弱性情報もつい先日公開されたばかりです。
言語を替えても、インフラを替えても、見つかった脆弱性は放置すれば同じです。「WindowsよりOSXの方が安全」と考えるのはナンセンスです。基本的な要素が同じなら、いかに管理し、対処しているかによりどちらの方が安全か評価できます。同じように「PHPよりPerl/Ruby/Pythonの方が安全」ではありません。これらは偏見に満ちた間違った考え方です。この様な考え方でWebシステムを構築・管理していては、いつまで経ってもWebシステムは安全になりません。
実に困った物騒な代物なのですが、たいていの場合、新しいPHPリリースにアップデートするには相当な量のコードを書き直す必要があります。
著者は本当にPHPのコードを書いているのか疑いたくなります。
少なくとも自分のコードはPHP4からPHP5へ移行する際、修正はほとんど必要ありませんでした。私が利用しているOSSのコードのほとんど書き直しは必要ありませんでした。
# OSSの場合、バージョンアップのコストはほどんとかかりません。
# 「ユーザに試してもらい、動かなかったら対処する」で構いません。
# しかし、信頼性が重要な商用サービスでは言語のバージョンアップ
# を行う場合のコストは無視できないくらい大きなコストが必要です。
# しかし、これはPerl/Ruby/Pythonなら不必要となる、とか激減する
# というコストではありません。
「たいていの場合、新しいPHPリリースにアップデートするには相当な量のコードを書き直す必要があります」と書いていますが、よほど汚いコードを書いていない限り「相当な量のコードを書き直す必要」は無いはずです。マイナーバージョンアップで困る事(バグで機能が壊れたなど)もありますが、それ以外でコードを書き換える事はほとんどありません。
ちなみに、私の書いたPHP3のコードはほとんど書き換え無しにPHP4で動作していました。多分PHP5でも問題なく動作したでしょう。おそらく、PHP3の頃のスクリプトはいわゆるバッチ型のスクリプトが多く、PHP4/PHP5でほとんど修正なしに動作します。確かに、PHP3は純粋インタプリタだったのでPHP4への移行が難しいスパゲッティコードで、それが原因で移行できなかったのかも知れません。仮にそのようなコードを使っているサイトがPerl/Ruby/Pythonに乗り換えたからといって安全な運用を行うとは到底思えません。
言語は安全な運用を強要する物ではありません。「Perl/Ruby/Pythonならより安全に運用できる」ものではありません。
「Python 3000, Ruby 1.9, Perl 6.0ならコードの調整も無し、互換性チェックも無しにバージョンアップできる」はずがありません。実際にリリースされているRuby 1.9の状況を見ても同じです。1.8へのバージョンアップでも似たような状況だったと思います。言語機能だけみると他の言語のバージョンアップとPHPのバージョンアップとそう変わらないと思います。
大きな違いは、PHPは多くのモジュールをバンドルしているのでPHPのバージョンアップをするとモジュールもバージョンアップされてしまう事です。これには良い面と悪い面がありますが、セキュリティ面だけ考慮すればモジュールごとバージョンアップされるのは良い事です。そうでないとPHP本体のバージョンだけアップグレードし、脆弱性があるモジュールを使い続ける事になり安くなります。
PHPはWeb開発フレームワークと言うには機能は貧弱ですが、言語の基本機能に内蔵されたWebプログラミングサポート機能などフレームワーク的な要素が強く、多くのモジュールも一緒にバージョンアップ・リリースされ、バージョンアップされます。このため、他の言語とに例えると「言語」のバージョンと「フレームワーク」のバージョンアップを同時にするような状態になり、バージョンアップが難しくなる側面もあります。特にホスティングサービスの場合、アプリケーションが利用している機能を特定できないので、この記事の著者の言うように「腐った果実」をそのまま使っているサービスが氾濫しています。
PHP3のような化石ともいえそうなPHPバージョンにも言及されているので、古いPerlライブラリの脆弱性を例に上げます。古いPerlのシステムではCGI.pmの脆弱性が放置されたままであるサーバもあるでしょう。例えば、
http://www.securityfocus.com/bid/8231
など。ざっと検索して最初に見つけた物だけです。これ以外にもあるかも知れません。
# 問題はPHPのバージョンアップに伴い必要となる、互換性の検証に
# コストが必要であり、多くのサイトがそのコストをかけてない
# ことが問題なのです。これは歴史が同じくらい長いPerlサイトでも
# 同じです。
#
# 昨年もあるサイトのリニューアルで多数の古いPerlスクリプトを新
# しいサイトに移行するプロジェクトに関わりました。当然ですが、
# セキュリティ的に合格点が出るようなスクリプトはほとんどありま
# せんでした。
#
# 既知の脆弱性が無い、新しいバージョンのプログラムを利用する方
# が良いには代わりありませんが、古いバージョンでもかなり安全に
# 利用することも可能です。放置するだけでリスクアセスメントと対
# 策を全く行ってい事が一番の問題なのです。
私見を述べさせてもらうと、Perl、Python、Rubyのどれかを使う方が良いでしょう。
本当にそうでしょうか? 言語を変えるとプログラマがセキュリティを気にせず使っても安全なWebアプリが作れるのでしょうか?
個人的には全ての言語の標準的なライブラリのセキュリティ状態が非常に気になります。ほとんどのセキュリティ研究者はライブラリのセキュリティ状態までチェックしていません。
最も良くチェックされているライブラリはPHPが標準でバンドルしているモジュールだと思います。
# とは言っても先日、結構致命的な脆弱性をPHPモジュールに発見してし
# まいました。
# 自分の書いたスクリプトなら問題ないのですが、多くのスクリプト
# 影響を受けると思います。パッチはこれから書きます。PHPユーザの方
# バージョンアップの準備をした方が良いです。
PHPはWebサーバモジュールとして利用する事が多く、MOPBのおかげで最近はメモリ管理エラーはきちんとセキュリティ上の問題として取り扱われています。PHP以外の言語ならモジュール関数を仕様外の使い方でクラッシュさせても「自分で自分の足を打つな」と言われるのがおちでしょう。
長い目で見ると手間や心配事は激減します。
これは間違っています。現在のPHPの様に、長い間不適切な管理を続けるとPerl/Ruby/Pythonを使ってもいても同じ様に心配ごとが激増します。長い目でみると言語を替えてもセキュリティ対策の根本的な解決とならず、放置すれば心配事が激増するのは明かです。
記事の著者が古くてバージョンアップしていないPHPホスティングサービスは「ゴミ同然」(「腐った果実」と表現しているので)と記述していますが、長い目で見てPerl/Ruby/Pythonに変える事によりこの状況が変わる、とは思えません。言語を替えるとフレームワーク毎新しくしなければならないので、替えた直後は最新のフレームワークと言語になり安全な状態になりますが、時間と共に安全性は劣化していきます。同じような管理では問題をリセットして先送りするだけになります。
たいていのホスティングサービスは危なっかしい骨董品のLAMPスタックを後生大事に使っているので、まともなWebホスティングサービスを探したい場合はWebHosting Talkをチェックするとよいでしょう。
このアドバイスは適切です。しかし、求める物はもう少し具体的に書いた方が良いでしょう。ホスティングサービスにセキュリティを求める場合、仮想プライベートサーバ以上にして、自分でインフラとして利用するWebサーバ、言語、ライブラリ、フレームワーク、アプリケーションを管理しなければなりません。
自分でインフラとして利用するWebサーバ、言語、ライブラリ、フレームワーク、アプリケーションを管理するのは面倒なように思えますが、Perl/Ruby/Pythonを使っても同じです。Perl/CPANを利用したサイトでPerl/CPANのアップデートを行っていないサイトは数えきれないほど見ています。
『MySQL Reference Manual』のセキュリティに関する章も役に立ちます。また、chrootはセキュリティデバイスではありませんが、Security Focusは使用を推奨しています。
これも非常にミスリーディングで悪い記述だと思います。Security Focus記事の著者は、chroot制約が乗り越える事ができることくらいは知っていると思われます。(少なくともそう願いたい)他のデータベースサーバも同じですが、MySQLにはシステム上のファイルをロードする機能があります。この機能を利用して/etc/passwd等を読み取られないよう、chroot環境にMySQLをインストールするのはセキュリティ上非常に重要な意味があります。
この記述では「Security Focusはセキュリティ上意味が無いchrootを使う設定を推奨している」と読めてしまいます。
Fedora Linuxには、Apacheポリシーを含む良質のSELinuxポリシーと、グラフィカルな管理ユーティリティsystem-config- selinuxが標準で用意されています。簡単とは言いませんが、ゼロから始めるよりは簡単です。AppArmorも調べてみる価値があります。 SELinuxより簡単に扱えるとされており、どちらが優れているかを巡る議論は楽しく、有益な情報が得られます。
これは良いアドバイスです。
MySQL等もchrootよりはSELinuxで強制アクセス制御を使った方がより安全であることは言うまでもありません。
PHPにはフェイルセーフ機能としてsafe_modeやopen_basedirがありますが、これらはセキュリティを保証する機能ではありません。不要なファイルアクセスを厳密に制限するにはSELinux等を利用すべきです。
しかし、フェイルセーフ機能が無用か、というとそれは違います。chrootの様に適切に利用するとシステムの安全性を向上させる事ができます。
まとめ
前提条件などが無い記事なので真意は計りかねますが、これだけは間違えてはなりません。
言語を替える事はセキュリティ問題の解決策にはなりません。
この記事からは「LAMPセキュリティを強化する4つの方法」の最も重要な要素は「PをPHPからPerlかPython(もしくはRubyでLAMR)に変える事」である「Pを変える事により大きくセキュリティが強化される」と読めます。これは大きな勘違いです。「Javaにすれば自動的にセキュアでスケールアウトが可能なWebアプリができる」と勘違いしているのと同じです。
言語を替えれば、短期的にセキュリティ問題が改善するのは当たり前です。新しく構築するシステムにだれもわざわざ脆弱性があるバージョンを選んだりしません。根本的な問題は全く別です。
この記事は短いので言葉たらず、もしくは著者の見識不足、または私の読解力・知識不足なのかもしれませんが、この記事は非常に悪い誤解を与える記事だと思います。
EnterpriseZineの「LAMPセキュリティを強化する4つの方法」はお粗末なので、忙しくていつ書けるか解りませんが、次のエントリは「LAMPセキュリティを強化する4つの方法」(方法はもっと増えるかも)テーマに書くことにします。
参考