バリデーション、と一言で言っても一種類/一箇所だけではありません。バリデーションには3種類のバリデーションがあります。
バリデーションは重要であるにも関わらず誤解が多い機能の筆頭だと思います。日本に限らず世界中でよくある議論に
- バリデーションはモデルで集中的に行うべきだ!
- なのでコントローラー(入力)でバリデーションなんて必要ない!
- モデル集中型バリデーション以外の方法/場所でバリデーションするのは非効率で馬鹿馬鹿しい考えだ!
があります。どこかで見た事があるような議論ですが、世界的にこのような考えの開発者が多いことは、この入力バリデーション用のPHP拡張モジュールを書いた時の議論で分かりました。
実際、多くのWebアプリケーションフレームワークは入力バリデーション機能をデフォルトでは持たず、アプリケーションレベルでの入力バリデーションを必須化していません。開発者が上記のような考えになっても当然と言えるかも知れません。しかし、必要な物は必要です。何故?と思った方はぜひ読み進めてください。
流石にこの時の議論ではありませんでしたが、以下の様な議論も見かけます(ました)
- 入力データはバリデーションはできない!
- どんな入力でもWebアプリは受け付けて”適切”に処理しなければならない!
- 入力バリデーションにホワイトリスト型は無理、適用できない!
- ブラックリスト型とホワイトリスト型のバリデーションは等しいセキュリティ対策!
- 入力バリデーションはソフトウェアの仕様でセキュリティ対策ではない!
- 脆弱性発生箇所を直接または近い個所で対策するのが本物のセキュリティ対策である!
全てセキュアなソフトウェア構造を作るには問題がある考え方です。最後の「入力バリデーションはソフトウェアの仕様でセキュリティ対策ではない!」とする考え方の問題点は”セキュリティ対策の定義” を理解していないと問題点は見えないかも知れません。
- セキュリティ対策(=リスク管理)とはリスクを変化させる全ての施策で、多くの場合はリスクを廃除/軽減させる施策だが、それに限らない。
このセキュリティ対策の定義はISO 27000/ISMSの定義をまとめたモノです。
TL;DR;
何事も原理と基本が大切です。基礎的な事ですがプログラムの基本構造と動作原理を正しく理解しておく必要があります。
セキュアコーディングの構造/原理/原則
入力対策と出力対策は両方必要でバリデーションはセキュアなソフトウェア構築には欠かせません。
- 原理1: コンピュータープログラムは「妥当なデータ」以外では正しく動作できない
- 原理2: 何処かでエラーになるから、ではセキュアにならない(遅すぎるエラーはNG)
アプリケーションの入り口で入力バリデーション(入力検証)をしていないアプリはセキュアでない構造です。
入り口以外に入力検証がないアプリもセキュアではない構造です。セキュアなアプリには最低限、入り口でのデータ検証と出口でのデータ無害化(エスケープ/無害化API/バリデーション)が必須です。
- プログラムは妥当なデータでしか正しく動作できない。入力バリデーションは原理的に必須。
- 出力対策は必須の物とフェイルセーフ対策の物がある。フェイルセーフ対策の場合は下層の多層防御です。そもそも”データが妥当でない場合”(=フェイルセーフ対策)のエラーは起きてはならない。当然ですが出鱈目なデータを処理するのもNG。
多層防御 は重要なのに勘違いされているソフトウェアセキュリティ要素の1つです。
バリデーションには3つの種類があります。
- 入力バリデーション – 正しく動作する為に必須(主に形式検証)
- ロジックバリデーション – 正しく動作する為に必須(主に論理検証)
- 出力バリデーション – 大半が上の2つに失敗した場合のフェイルセーフ対策(追加の対策 – 安全な特定形式のみ許可の場合)
※ 出力時のエスケープ/エスケープが不必要なAPIの利用によるデータの無害化は、必須の対策が半分、フェイルセーフ対策が半分です。
※ “入力ミスの確認”を”バリデーション”と考えたり、言ったりすると混乱の元です。”入力ミス/論理的整合性の確認エラー”は処理の継続、”あり得ないデータによるバリデーションエラー”では処理の中止、が必要なので区別する方が良いです。
※ ソフトウェア基本構造の入力処理では”あり得ないデータによるバリデーションエラー”、ロジック処理では”入力ミス/論理的整合性の確認エラー”、になります。
※ リスク分析の経験があれば自然にセキュアな構造を思い付くことも可能だと思います。
リスク分析とリスク対応をしよう
イメージ図:
参考:データもコードも一文字でも間違い/不正があるのはNG
常識?非常識?プログラムは1文字でも間違えると正しく動作しない
もっと読む