なぜPHPアプリにセキュリティホールが多いのか?

第45回 入力バリデーションはセキュリティ対策

この記事を読むのに必要な時間:およそ 8 分

セキュリティ対策とバグ対策を区別する理由

ITセキュリティ対策はシステムの機密性,完全性,可用性,責任追跡性,真正性,信頼性を担保するための対策で,システムに必要なセキュリティ対策を取り入れることは当然のことです。セキュリティ対策はバグのないシステムを目指した対策ではありませんが,バグのないシステムは自動的に機密性,完全性,可用性,真正性,信頼性も担保※7できます。しかし,バグのないシステムを目指した対策を網羅しようとすると,すべての対策を網羅したセキュリティ対策の何倍もの対策と知識が必要になります。開発者への負担を軽減するために,セキュリティ上必要な対策とそうでない対策は区別するほうが分かりやすく,習得しやすくなります。

図2 セキュリティ対策とバグ対策

図2 セキュリティ対策とバグ対策

セキュリティ要件の厳しいプログラムでは「バグ対策=セキュリティ対策」となるようなものもありますが,一般的なプログラムであれば「バグ対策>セキュリティ対策」となり,バグ対策よりセキュリティ対策のほうが少なくなります。⁠バグ対策<セキュリティ対策」となることは論理上ありません。

言うまでもなく,バグのないプログラムであるほうがよいに決まっています。しかし,バグのないプログラムはほとんどありません。バグを作らないための知識は多岐に渡ります。例えば,浮動小数点型データの比較において,等価比較してはならないということを知らない開発者も多いでしょう。これは浮動小数点演算の標準であるIEEE754の仕様からの制限です。コンピュータサイエンスでは浮動小数点型の等価比較はよほど慎重に行わない限りやってはならないは常識であると思いますが,必ずしもすべてのエンジニアが知っているわけではないようです。

浮動小数点の比較による問題は多くのシステムでただのバグと分類される問題でしょう。Webアプリの開発者であっても浮動小数点演算の問題は理解しておくほうがよいですが,一般的なWebアプリの開発者がセキュリティ対策の知識として必ず身につけておくべき知識※8とまでは言えないと思います。しかし,浮動小数点演算の標準を知らない開発者が金融機関や会計システムなどのシステム設計を担当している場合,この知識の欠如はシステムの完全性を脅かすセキュリティ問題です。このようにセキュリティ要求事項によっても必要となる知識が異なることがよくあります。

必要なセキュリティ対策はアプリケーションや要求仕様によって大きく異なります。一般的なWebアプリに必要とされるセキュリティ対策と一般的な金融機関の基幹アプリに必要とされるセキュリティ対策では大きな違いがあります。セキュリティ対策の項目は沢山あり範囲も広いです。しかし,バグを作らない対策はさらに膨大かつ広範囲です。特定のアプリケーションや要求仕様別に,セキュリティのCIA※9を守るための対策を「セキュリティ対策」として区別することで,最低限必要な対策をコンパクトにすることができます。このような,セキュリティ対策とバグ対策を区別する考え方に異論を持つ方はほとんど居ないのではないでしょうか。

よい上司は部下に優先順位を明示して指示をします。これと同じでよい開発マネージャはセキュリティ対策とバグ対策を区別して指示を出します。セキュリティ対策とバグ対策では優先順位も範囲も異なるので,区分しないと適切な対応が難しくなります。

※7
責任追跡性は一般的なWebアプリの要求仕様に入っていないことが多いので省略しました。
※8
お金の計算が関わる場合,Webアプリのセキュリティ対策に加えて業務アプリのセキュリティ対策を習得すべきだと考えています。浮動小数点の等価比較を行ってはならないことをご存知でなかった方は,これを機会に覚えておくとよいと思います。
※9
セキュリティ対策で最も重要な三要素とされるのが機密性(Confidentiality⁠⁠,完全性(Integrity⁠⁠,可用性(Availability)です。頭文字をとって「セキュリティのCIA」と呼ばれることがあります。

「優れたセキュリティ対策」ではなく,「必要なセキュリティ対策」を採用する

前回Rails標準のバリデーションには欠陥があると指摘しました。この欠陥は脆弱性ではありますがセキュリティホールではありません。Railsは元々DRY(Don't Repeat Yourself)を実現し,80%のWebアプリを素早く作ることを目標にしています。Railsの開発者はこの要求事項を達成するためにいろいろ余計なものを削除しています。Railsの開発者もこのバリデーション仕様の欠陥はよく理解していることでしょう。そして,バリデーション仕様の欠陥を指摘すると恐らく「8割のWebアプリはこの仕様で安全に作れるよね」と答えるでしょう。欠陥はあっても要求事項にあっているので,仕様的なセキュリティ脆弱性があってもセキュリティ問題だとはとらえないことはよくあります。前回の記事の反応からはほとんどのRailsユーザはこの仕様の欠陥を理解しているようでした※10⁠。Railsに限らず同様の仕様になっているフレームワークの利用者はよく理解して使う必要があります。

「役立たないセキュリティ対策はない」で紹介したパスワード認証も,⁠優れたセキュリティ対策ではなく,必要なセキュリティ対策を採用する」※11よい例です。パスワード認証は非常に脆弱で欠陥だらけですが,要求事項にあっているのでセキュリティ問題だと考えられていないケースはよくあります。パスワード認証より優れた認証方式やパスワード認証を補強する対策は数多く存在しますが,安全保障に関わるシステムなどの高度なセキュリティ対策を要求されるシステムを除けば,これらの認証方式や対策を利用しないシステムを脆弱で使えないシステムだという人は居ないと思います。

入力バリデーションは未知の脆弱性を含む,非常に多くの脆弱性を緩和したり防止したりする効果があります。OWASPやSANSが非常に高く評価しているように,この意味では非常に優れたセキュリティ対策と言えます。一方,入力バリデーションはセキュリティ対策として多くの脆弱性の直接的な対策ではないとも言えます。この意味では優れた対策とは言えないかも知れません。仮に入力バリデーションを優れたセキュリティ対策としてとらえていなくても,入力バリデーションはパスワード認証と同様,その対策の優劣に関係なくセキュリティを担保するための重要なセキュリティ対策だと考えるべきでしょう。

※10
ヘルパーが安全ではない,という部分は誤解している方もいるようでした。これについてはまたの機会に解説します。
※11
必要なセキュリティ対策を選択するのは簡単なようで簡単ではありません。別の機会に解説したいと思います。

まとめ

標準規格であっても,欠点があったり,不足している部分や間違いと言える欠陥があることもよくあります。標準規格は完全な存在ではありませんから,異論があっても当然です。しかし,論理的に矛盾が起きてしまうような主張や根本を覆すような主張は,無用な混乱を避けるために慎重に行うべきだと思います。

セキュリティ対策の優劣や欠陥,適用性について議論することには意味はあります。しかし,ITセキュリティを担保するある対策がセキュリティ対策であるかどうかを議論したり,考えたりすることには意味がありません。⁠セキュリティ対策」を独自に定義しているなら別ですが,国際的な合意としてITセキュリティ(機密性,完全性,可用性,責任追跡性,真正性,信頼性)を担保する対策がセキュリティ対策と考えられています。標準規格は円滑なコミュニケーションを行う土台としての意味もあります。このために規格では用語の定義を明確に定めています。⁠Webアプリセキュリティ対策入門」にも書いていますが,すべての開発者はセキュリティ標準規格を学ぶ機会を作るべきです。ISO27000や関連ISO規格,PCI DSS※12も分量はそれほど多くありません。図書館に行ってその場ですべて読めるくらいの分量です。特にこれからセキュリティについて本格的に勉強しようと考えている方は必ず読むようおすすめします。

セキュリティ対策として議論すべきは完全性やコストなどの優劣,セキュリティ対策自体の欠陥,どのような場合に使うべきか,使えるかなどの適用性です。欠陥があるからといって,その対策は使いものにならないわけではないことには注意してください。広く使われている欠陥のある対策としては,例えば「ライセンス認証」です。難解にするだけのセキュリティ対策は通常は決して使ってはならないとされています。この考えは正しく,難解にする対策はセキュリティに欠陥がある対策です。しかし,今でもライセンス認証は広く有効な対策として利用されています。Railsのバリデーション仕様も同じです。欠陥はあっても要求仕様に合っていて合理的であれば十分使えるセキュリティ対策です。

以上からも分かるように,入力バリデーションはセキュリティ対策です。システムが意図通りに動作するように対策する入力バリデーションをセキュリティ対策ではないとするならば,システムが意図通りに動作するようエスケープしたりヘルパー関数(Viewヘルパーやプリペアードクエリ)を利用することもセキュリティ対策ではないということになってしまいます。入力バリデーションがセキュリティ対策か迷う余地はありません。

なぜこのようにおかしな議論になるのか?原因は簡単です。議論の出発点が間違っているからです。ITセキュリティを担保する対策がセキュリティ対策であり,入力バリデーションはITセキュリティを担保することができるセキュリティ対策だからです。

今回もPHPとは関係ないセキュリティの一般論になってしまいました。一部の方からは「なぜPHPアプリに」ではなく「なぜWebアプリに」とタイトルを変えたほうがよいのでは,と言われるくらいです。近いうちにPHPの話をするのでご容赦ください。

最後に,筆者が考えたセキュリティ対策の議論を有益な議論にするためのチェックリストを記載しておきます。

セキュリティ対策の議論を行う場合のチェックリスト
  • □ ITセキュリティを担保する対策であるかどうか?(真なら欠陥があってもセキュリティ対策)
  • □ どのような利点があるか?(利点は利便性・コストであることが多い)
  • □ どのような欠点があるか?(欠点はコスト・リスク要素であることが多い)
  • □ どのような場面に適用できるか?できないか?(ユースケース)
  • □ どれくらいのリスクが予想されるか?(欠点!=リスク)
  • □ 対象のアプリの要求事項に合っているか?合理的か?
  • □ 利点・欠点・リスク・ユースケースと要求事項を総合的に判断して妥当であるか?(ニーズに合うか,リスクを許容できるか)

このリストからも分かるように,セキュリティ対策はコンテクスト抜きに考えることはできません。次回はセキュリティ対策を考える上で欠かせないコンテクストについて考えてみたいと思います。

※12
PCI DSSは無償配布されています。https://www.pcisecuritystandards.org/security_standards/documents.phpからダウンロードできます。日本語版も選択できます。

著者プロフィール

大垣靖男(おおがきやすお)

University of Denver卒。同校にてコンピュータサイエンスとビジネスを学ぶ。株式会社シーエーシーを経て,エレクトロニック・サービス・イニシアチブ有限会社を設立。
オープンソース製品は比較的古くから利用し,Linuxは0.9xのころから利用している。オープンソースシステム開発への参加はエレクトロニック・サービス・イニシアチブ設立後から。PHPプロジェクトでは,PostgreSQLモジュールのメンテナンスを担当している。

URLhttp://blog.ohgaki.net/

著書