セコム(セキュリティ対策・オブ・コムピュータ)してますか〜?

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
今の若い人はジュリー知ってるのかな?

この記事を三行にまとめると

ウェブサービスを作るときにセキュリティ対策をどれくらい行っていますか〜
四人の沢田研二?
全てを切り刻め! ディレクトリーーーーートラバーーーサァゥッ!!
あの警備サービスのSECOMではなくて、今回は「SEcurity of COMputer」を略してSECOMってことにします。ただコンピュータと言いつつも中身は、ウェブサービスを作るときにセキュリティ対策をどれくらい行っていますか〜、って話になります。

僕も仕事で自社サービスの開発や運用をやっているのですが、お客さんの中にはかなり厳しくセキュリティ対策を確認する人もいます。今までにも何度か、セキュリティチェックシートってのが送られてきて「てめーんとこがどんだけ対策してんのか教えろやゴルァ」って言われたことがあります。

もうエンジニアになって数年経ちますから、さすがに僕もノーガードってことはないですが、でも大口のお客さんから送られてくるチェックシートを見ると「何よそれ? 聞いたこともねーよ」ってのが、結構あったりする。

そんなわけで、僕が最近対峙したセキュリティチェックシートの項目を紹介しつつ、普通はみんなどれくらい対策してるもんなのかなってのを、ここで知ることができたらな〜なんて思っちょります。

項目が多いのでちょ〜っと長くなってしまいますが、「そんなの、エンジニアにとっては当たり前だろ?」って内容も多いと思うので、さら〜っと読み流してもらえたらと思います。

詳細な内容や具体的な対策の方法についても、ここではあまり説明しません。箇条書きレベルになってしまいますが、ご容赦くだせえ。めんど……いえ、俺があまりちゃんと理解してな……じゃなくって、そこまで書くとものすご〜く長くなっちゃうから。

ちなみに、僕は普段PHPのフレームワークであるCakePHPを使って開発してますので、こっから先、フレームワークって言葉が出てきたら、基本的にはCakePHPのことを指していると思ってください。



バッファオーバーフロー対策

しょっぱなから僕にとっては初耳学な内容です。

バッファオーバーフローというのは、文字通りバッファがオーバーフローしてしまうことなのですが、簡単に言うと、一度に大量のデータが送信されることでメモリがリミットブレイクしてしまった結果、サーバーの挙動がおかしくなったりすることです。あまりちゃんとは説明できないのですが、オーバーフローさせることで悪意のあるコードを実行させたりできるんだってさ。

PHPやJAVAは、このバッファオーバーフローは起こりにくいそうです。だからって無視して良いわけではないんでしょうけど、PHPの場合、post_max_sizeやmax_input_varsなどで一度に送信できるデータ量を適切に設定しとけばバッファオーバーフロー対策は大丈夫ってのが僕の認識なんですが……合ってますかね?



クロスサイトスクリプティング

XSSってやつですね。これはさすがに僕も知ってました。

これは例えば、入力フオームの中にscriptタグを埋め込んでデータを送信したりすることですね。ウェブサイトへの攻撃としてはメジャーなやつだと思います。ページが改ざんされたり大事な情報が盗まれたりしてしまうので、飛んできたデータをチェックしてscriptタグは除去するなどの対策が必要ですね。

XSSや、後で出てくるSQLインジェクションの対策に関しては、フレームワークも結構手助けしてくれますんで、全てPHPベタ書きで開発してるならともかく、フレームワークを使って開発してるなら、その辺を上手く使っていくと良いと思います。ちなみにCakePHPにはSanitizeというコアライブラリがあります。僕も利用してます。



パラメータの改ざん

URLの後ろに適当なパラメータをくっつけて、それをGETで受け取るようにしてる場合に、そこに変なパラメータをくっつけて不正な処理を行わせたりするものですね。あとはhiddenの値をこっそり書き換えたりとか。hiddenに何かしらのIDを入れてデータの取得や更新をしている場合などに、そこを書き換えられるとデータ取り放題になっちゃったり書き換え放題になっちゃったりするのは危険ですね。他のユーザーのデータとかね。

これは受け取ったデータを適切にチェックしていれば大きな問題はないでしょう。



バックドアとデバッグオプション

はい、またしても知らないのが来ましたよー。ただ、どっちも聞き慣れない単語でしたが、デバッグオプションの方は何となく想像がつきました。特定の操作によってデバッグが画面に出ちゃうことですね。

バックドアは、例えば開発者がIDやパスワードの入力なしでログインできるような方法があって、それを第三者に使われてしまう、みたいなことですかね。本番運用ではなくテスト中に、いちいちログインして動作確認するのがめんどいってことで、「http://hogehoge.jp/login.php?login=true」みたいに、URLに適当なパラメータをくっつけることで管理画面にログインできるようにしておいた場合、それが本番環境でもできちゃったりすると、それを知っていれば誰でもログインできちゃってまあ大変。そんな感じです。

この二つは、どっちもそういう操作ができないようにしとくのが一番良いでしょう。僕も以前は、ユーザーから問い合わせがあったときにそのユーザーの状態を見れるよう、パスワードが分からなくても管理者権限でログインできるようにしてたことがありましたが、今はやってないです。



強制ブラウズ

ブラウザ上で見れちゃいいけないファイルがうっかり見れちゃったりすることですね。例えばデータベースへの接続情報とか、かな。

そういうのはドキュメントルートの下に置かないようにするのが良いですね。CakePHPの場合だと、コントローラーやモデルなどのファイルはドキュメントルートの下に置かず、別の場所に置いてindex.phpを書き直すのが良いです。

以前、こんな記事を書いたこともあるので、結構古い情報ですが、もし参考になりそうであれば。
index.phpを適切に書き直す


セッションハイジャック

セッションがハイジャックされることです。これも文字通りっすな。

URLの後ろにつけたりCookieに値を持たせたりしてセッション管理をする際、そのセッションIDを盗み取ってしまうことで全く知らない第三者が任意のユーザーになりすましてサイトを利用することができるので、気をつけてくださいってことですね。

Cookieで管理する場合はsecure属性をつけるとか、セッションIDを推測されにくい文字列にするとか、定期的にセッションIDを更新するとか、その辺の対策が一般的でしょうか。



クロスサイトフォージェリー

こいつも聞き慣れない単語でした。フォージェリー? 四人の沢田研二? あれはジュリーか。

クロスサイトフォージェリー(CSRF)は、iframeで読み込んだページに不正なプログラムが入っていたりすると、本人の知らないところで勝手にデータを送信したりしてしまう、そんなようなやつです。例えばページをロードするだけでフォームのデータを送信するようなスクリプトが入ったページをiframeで読み込めば、その瞬間にデータがPOSTされてしまいますね。それで掲示板に勝手に書き込んだり、お問い合わせフォームからメールを送信したりするわけです。

対策としては、これはデータを受け取る側の話ですが、それが正規に飛んできたかデータかどうかをチェックできれば防げます。セッションIDを照合するとか、ページトークン?とかいうのを使って、変なところから飛んできてないかを確かめるとか。フレームワークによってはこの辺の対策をやってくれるのもあるので、上手く利用すれば大丈夫だと思います。CakePHPにもSecurityCompoenetってのがあります。



ディレクトリトラバーサル

知らない単語が連続で来ましたよぉ。そんな名前のテーマパークがどっかにありましたね。トラバーサルスタジオジャパンだったかしら。テーマパークよりはむしろ必殺技っぽいかな。「全てを切り刻め! ディレクトリーーーーートラバーーーサァゥッ!!」的な。

「http://hogehoge.jp/download.php?file=sample.txt」みたいに、URLにファイル名をくっつけることでそのファイルを閲覧できたりダウンロードできるような機能があったとして、そこに親ディレクトリを参照する「../」ってパラメータをくっつけたら参照できてはいけない親ディレクトリにアクセスできてしまったりする。ディレクトリトラバーサルってのはそんな攻撃方法です。

まあ……一番良いのはURLなどに直接ファイル名を入れて参照する仕組みを採用しないようにすれば良いんじゃないでしょうか。ファイル名をデータベースに登録して、IDで参照できるようにするとか? あとは「../」とかを不正な文字として処理するとかですかね。



SQLインジェクション

たぶんXSSと並んで、システム屋にとってセキュリティ対策と言えばまずこの辺が思い浮かぶって感じじゃないでしょうか。

サイトを利用するユーザーが入力した値によって意図しないSQL文が発行されてしまい、不正な操作が行われてしまう……って感じの説明で良いのかな。例えばURLに「delete」ってパラメータをつけたら、そのままDELETE文が発行できてしまうとか。これは危険ですね。あとは何でしょう……クォーテーションが入っているせいでSQLエラーになってしまったりとか、そういうのもSQLインジェクションに含まれるのかな。

不正なSQLにならないよう、文字列にエスケープ処理を入れるとか、入力フォームにSQL文が入っていたりしてもそれで直接SQLを実行にしないようにするとか、そんな感じですかね。フレームワークも基本的な対策はやってくれてますけど、自分でも気をつけておくに越したことはないですね。



OSコマンドインジェクション

もう一つのインジェクション、OSコマンドインジェクションです。

PHPでもexex()などを使ってコマンドを実行することができますが、そこにユーザーが入力した任意の値とかをそのまま突っ込んでしまうと、とんでもないことになる可能性がある。

例えば、どんなのがあるかな……rmコマンドでファイルやディレクトリを削除することができますが、それをGETで受け取った内容とかで実行できちゃったら、やばいっすね。「exec(rm -rf $_GET[‘url’])」とかでindex.phpを削除できちゃったりしたら、困るのは目に見えてますね。場合によっちゃディレクトリを丸ごと削除できちゃう。大事に大事に溜めてきたエロ画像をフォルダごと削除できちゃう。危ない。

なるべくならOSコマンドを使わないようにするのが良いんでしょうけど、どうしても使わざるを得ないときは、飛んできたデータをそのまま使ったりしないよう注意するって感じですね。



開発者用コメント

ソースに書かれているコメントのことですね。僕が先方さんからもらったチェックシートでは、ユーザーが閲覧できるHTMLソースに攻撃の糸口となるようなコメントを残していないか、というような内容でした。まあ何かテスト用に書いた「このパラメータをURLにつければこんなことができるぞ」みたいな内容をうっかり残しておかないようにってことですね。

これはコメントの内容にさえ気をつけてれば良いので、難しい手順の必要な対策ではないでしょう。



エラーメッセージ

不正な操作などによってエラーページなどに飛ばしたとき、そこで表示されるエラーメッセージに攻撃の糸口となるような情報は載せていないか、みたいならしいです。

具体例が思い浮かばないのですが、さっきのコメントと一緒で、内容にさえ気をつけていれば大丈夫でしょう。「パスワードが違います」とか「不正な画遷移です」程度の内容だったら、そこから攻撃の糸口をつかまれることはない……はず。



Webアプリケーションによる取得情報を公開ディレクトリ以外の場所に置く

これは……何でしょうね。これ以上のことがチェックシートには書かれていなかったんで、僕なりの解釈という話になりますが、例えばシステムでCSVを作成し、それを任意の場所に保管するような場合に、その保管場所を公開ディレクトリに置くなよってことなんだと思います。

ユーザーの個人情報(メールアドレスなど)の一覧をCSVで作成して、それを公開ディレクトリに置いておいたら個人情報盗み放題ですからね。そりゃオッケーなわけがない。

強制ブラウズやトラバーサルスタジオジャパンと合わせて、不正に見られることがないような場所に保管するか、そもそもそんな、見られたらやばい情報を持つファイルをサーバー上に保管しておかないか、対策としてはその辺が考えられますかね。



セッション管理で不要な情報を引き渡さない

ようは機密情報をセッションで持つなってことなんでしょうね。セッションで管理するのはセッションIDや見られても害のない情報だけにして、大事な個人情報などは適宜データベースから取ってくるようにってことだと思います。

見られても害のない情報って言うと……例えばどんなのかな。ショッピングカートに入ってる商品とかかな。後で買おうと思ってエッチなDVDをカートに入れといた場合、それを彼女に見られたらまずいとかはあるかもしれないけど、まあ、そういうのは身内で解決してください。



ログイン認証用パスワードの暗号化(ハッシュ化)

パスワードの暗号化ですね。そのままです。僕ももちろんやってます。データベースにも、暗号化した状態のデータしか持たないようにしとくと、なお良いんじゃないでしょうか。



個人情報の送受信を行う画面は暗号化経路(HTTPS)を利用する

SSLを使っていますか的なことですね。僕の場合は常時SSLを採用してるので、どのページもHTTPSで表示していることになりますね。httpではアクセスできないようにしてます。なので、この辺は強く意識することはないかな。SSLに脆弱性が見つかったときとかに必要な処置を行うくらいですかね。



Webサーバーのバージョン情報の隠蔽

Apacheのバージョンなどをユーザーが見れるようになっていると、そこから攻撃の手がかりを与えることになるから隠しとけってことらしいです。

正直、これは知りませんでした。以前、このあかつきのお宿でも、こんな環境で開発してますってことで、開発に使っているCakePHPやWordpressのバージョンを完全に載せちゃってましたが、あれも良くなかったんですね。確かに、特定のバージョンにおける脆弱性とか、ありますもんね。

Apacheのバージョンは、404エラーページなどで見れることがあります。バージョンを隠していないと「Apache/2.2.4・・・」みたいな文字が出ますが、あれを見られないようにしようってことですね。

httpd.confに以下の情報を書くことで、バージョン情報を非表示にできます。

ServerTokens Prod
ServerSignature Off

もちろん、httpd.confを書き換えたらapacheを再起動しないと、いつまで経ってもバージョン情報は出たままですんで、ご注意。






システムに関する技術的なことは、これくらいですかねー。

僕の見たセキュリティチェックシートにはもうちょっといろんな項目があったんですが「パスワードは英数字を含む8文字以上じゃないと受けつけないようにしているか」「パスワードは定期的に変更するようにアラートを出しているか」「ログインIDとパスワードに同一の文字は使用できないようになっているか」「パスワードの再発行は本人確認ができる方法を取っているか」といったパスワード関連のこととか、「サーバーのウイルス対策はどうやっているのか」「開発者のPCにウイルス対策ソフトは入っているか」「サーバーのアクセスログは一定期間以上保管しているか」「アクセスログにはどんな情報が含まれているか」「サーバーの構成は?」「ファイアウォールの設定は?」「バックアップのスケジュールは?」「本番環境への移行の手順は?」といった、えーと、こういうのは何て言うのかな……開発の体制?みたいなものに関する質問がほとんどだったので、ここでは割愛します。

いやはや、一口にセキュリティ対策っつっても、洗い出してみるとたくさんありますよね。しかも、ここに書いてあることを完璧に対策してるからって絶対安全ってわけでもないんでしょうし、ウェブなんてほんとに日進月歩の世界ですから、今は良くても半年後くらいにはもっと細かいセキュリティ対策を求められるかもしれないし、一年後には今日ここで書いたことなんてもはやセキュリティのほんの一部でしかないなんてことも、あるかもしれない。

僕は正直、クライアントさんから送られてくるセキュリティチェックシートを見て初めて「へー、こんなのもあるんだー」って感じで対策することがしばしばです。Apacheのバージョンを隠すとかはまさにそうでしたね。ディレクトリトラバーサルなんかは、初めて聞く単語ではありましたが、元から直接ファイル名を入力して参照するような機能がどこにもなかったので、とりあえず、今後そういう機能をつけることがあれば気をつけようって認識だけしておきました。

この記事を読んだみなさんは、ここに書いてあることは当たり前のように全部対策済みなんでしょうか。この記事を読んで「えー、この記事書いた人、こんな程度のことも知らないんだー? バッファオーバーフローとか知らなくて良いのは、小学生までだよねー」とか、思ってるのかな。

そこんとこ、どうなのよ?
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください