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

第46回 セキュリティ対策を考える上で欠かせないコンテクスト

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

セキュリティ対策とコンテクスト

必要なセキュリティ対策はコンテクストによって変化します。先ほど紹介したキャッシュカードの例がよい例です。システムの性能上の制限からキャッシュカードの磁気テープに暗号化されていない暗証番号を組み込こんだセキュリティ対策は,現在では有効なセキュリティ対策とは言えません。しかし,現在と環境(コンテクスト)が異なった当時は十分に妥当なセキュリティ対策でした※7⁠。

特定システムのセキュリティ対策を考える場合にはコンテクストが非常に重要です。コンテクストが変わると必要なセキュリティ対策が変化するからです。キャッシュカードの例のようにコンテクストが変わると「⁠⁠必要な)セキュリティ対策」であった対策が「⁠⁠不必要な)セキュリティ対策」に変わってしまう場合もあります。

セキュリティ対策のコンテクスト

Webアプリのセキュリティ対策のコンテクストも多種多様です。必要となるセキュリティ対策も多種多用です。いくつか例を挙げてみます。

アプリケーションの種別

プロトタイププロトタイプではセキュリティ要件はまったくないことが多い
情報公開型アプリ公開されている情報の改ざんを防げれば十分である場合が多い
情報収集型アプリ適切な権限を持ったユーザが情報を登録・編集・削除できるように制限する
金融関連アプリ 機密性,完全性,可用性を確保。すべての処理の監査ログを保存する

アプリケーションの種別によってセキュリティ要件は大きく異なります。アプリケーションが必要とするセキュリティは種別によってまったく違うことに説明は必要ないと思います。

開発の種別

新規開発プロジェクト言語,ライブラリ,フレームワークなどのシステムの仕様の自由度が高い
再構築プロジェクト既存資産を有効活用する場合,システム仕様の自由度が低くなる
既存プロジェクトメンテナンスフェーズの場合,システム仕様の自由度はほぼない

開発の種別が異なると選択できるセキュリティ対策が異なります。条件がない新規開発では自由度が高くなりますが,既存プロジェクトのメンテナンス,特にセキュリティ問題の修正のみ,のような場合は自由度はほとんどありません。

開発プロジェクトの場合,予算も大きな要素です。セキュリティ標準では開発者などのセキュリティ対策のトレーニングや専門家によるソースコード監査を要求していますが,トレーニングやソースコード監査を行っていないプロジェクトが多くあります。

開発環境

言語言語によって必要なセキュリティ対策が異なる場合がある
ライブラリ同じ目的のライブラリでもセキュリティ対策が異なったり,バージョンによって異なるセキュリティ対策が必要な場合がある
フレームワークフレームワークが異なっても共通している部分もあるが,セキュリティ対策が大きく異なる場合もある

開発環境によってもセキュリティ対策が変わってきます。C/C++でアプリケーションを作る場合とPHPやRubyなどで作る場合とでは必要なセキュリティ対策はかなり異なります。ライブラリやフレームワークが異なるとライブラリ,フレームワーフを安全に利用するために必要なセキュリティ知識は異なります。

役割

開発者主にプログラムの作成のセキュリティを担当する
運用者主にシステム環境,運用環境のセキュリティを担当する
利用者自らの利用するシステム環境(ブラウザやプラグイン,OS)と利用方法のセキュリティを担当する

役割が異なると選択肢として考慮すべきセキュリティ対策がまったく異なります。運用者はWAF(Webアプリケーションファイアーウォール)やIPS(侵入防止システム)をセキュリティ対策として検討します。しかし,ソースコードを設計,記述する開発者は通常,WAFやIPSが存在することを前提にアプリケーションは作りません。DoSなどを除けばWAFやIPSが無くても正常に動作するよう構築します※8⁠。

※7

過負荷になってシステムが使えなくなるようでは可用性の維持をしていないことになります。カードリーダーが特殊で高価な機器であった当時では,銀行であっても⁠許容されるリスク⁠でした。

※8

大量のSYNパケットを送信するなどのDoS攻撃はアプリケーションレイヤーでは対処しきれないので,通常はネットワークレイヤーであるファイアーウォールで対処します。Webアプリケーションからファイアーウォールにリクエストを送り,特定のIPアドレスを一定期間ブロックするような構成もよく利用されます。

デザインパターンとしてのセキュリティ対策

セキュリティ対策を,ベストプラクティスを実践するためのデザインパターンのように捉えている方も多いのではないでしょうか? 実際,セキュリティ対策をデザインパターンのように捉えることも可能です。この考え方は新規開発の場合には適用しやすいですが,既存のシステムに適用しづらかったり,できなかったりします。この意味では欠陥がある方法でもあります。

デザインパターンの欠点
  • デザインパターンは新規プロジェクトに向いているが,セキュリティ対策は新規プロジェクト以外にも必要

  • 想定しているデザインパターンを利用していてセキュリティ問題があった場合の修正は可能だが,想定しているパターンを利用していない場合,パターンが適用できない場合がある

  • デザインパターンの要素自体がアプリケーションやライブラリで実装されている場合,その実装が正しいか確認するための情報が提供できていない場合がある

  • 元々デザインパターンはベストプラクティスとなるパターンを定義するものであるため,セキュリティ対策の文書であってもベストプラクティスのみ解説している場合がある

  • 多くのコンテクストに対応しようとするとセキュリティ対策の解説が煩雑になってしまい,分かりづらくなる場合がある

セキュリティ対策の作業は既に構築済みまたはレガシーアプリケーションのメンテナンスである場合も多く,デザインパターンとしてセキュリティ対策を定義すると漏れが発生したり,既存コードのチェックの指針にならない場合があります。また,多様なコンテクストに対して十分なパターンを定義せず,不完全な解説になってしまう場合があります。

セキュリティ対策をデザインパターンとしてとらえて解説している例は,IPAの安全なSQLの呼び出し方です。この文書ではエスケープ処理でSQL文を組み立てた場合に発生するSQLインジェクションを例にあげて,SQLインジェクションの原理を解説しています。SQLインジェクション対策としてJDBC型のAPIを持つプリペアードクエリとプレイスホルダの例を紹介しています。このアプローチには次の問題点があります。

  • JDBC型のAPIを持たないシステムやライブラリのことが考慮されていない

  • JDBC型のAPIでは定義されていないが,必要なセキュリティ対策の解説が省略されている

  • JDBC型のAPIを持っていてコードもある場合,そのコードの実装が正しいか確認する方法の解説が省略されている

利用されることが多いSQLデータベースには,プリペアードクエリが使えるようなったのが比較的最近のものもあります。データベースではサポートしていても,アクセス用のライブラリが対応していなかったものも多くあります。まだまだプリペアードクエリを利用しないアプリケーション/コードは数多く存在します。このような場合,JDBC型のAPIを想定したパターンは役に立ちません。実際,PHPの場合でJDBC型のAPIでJDBCと同等の動作をするライブラリは少なく,PEARのMDB2くらいのようです。

JDBC型のAPIを持っていても,識別子(テーブルやフィールド名)やSQL句(LIMITやORDER)のセキュリティ対策は別途必要です。識別子やSQL句がパラメータに含まれる可能性がある場合,エスケープやバリデーションによるセキュリティ対策が必要になります。

JDBC型のAPIを持つようなライブラリをアプリケーションやサードパーティ製ライブラリで実装している場合,その実装自体が適切な実装であるか確認する必要があります。JDBC型APIの利用方法を解説するだけでは実装が適切であるか確認する方法の説明が抜けてしまいます。

特定の脆弱性に対して,必ずしも1つのセキュリティ対策で完全な対策にならなければいけないわけではありません。しかし,SQLインジェクション脆弱性は出力時の対策で完全なセキュリティ対策が実施できる脆弱性です。セキュリティ対策の解説としては完全な対策となる解説のほうが好ましいと考えられます。

著者プロフィール

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

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

URLhttp://blog.ohgaki.net/

著書