昨日、セキュリティの話をしていて当たり前のことですが見過ごしていた点を教えてもらいました。セキュリティ対策の必要条件と十分条件です。
SQLインジェクション対策の必要十分条件
SQLインジェクションを例にとると
SQLインジェクション対策の必要条件
- パラメーターによるインジェクション防止
この条件は必須の条件ですが、十分条件ではありません。つまり、上記の対策だけではSQLインジェクション対策として不十分です。SQL文を構成する場合、パラメーター以外にも識別子(テーブル名やフィールド名)やSQL語句のエスケープ/バリデーションが必要になります。
SQLインジェクション対策の必要十分条件
- パラメーター文字エンコーディングのバリデーション
- パラメーターによるインジェクション防止
- 識別子によるインジェクション防止
- SQL語句によるインジェクション防止
これら全てを行わないと完全にSQLインジェクションを防止できません。
インジェクション対策の必要十分条件
インジェクション対策で明らかに必要な条件は
- 出力対策
です。インジェクション防止の出力対策ではパラメーターのエスケープ(エンコーディング)、セキュアなAPI、バリデーションを行います。
しかし、出力対策だけでは十分条件になりません。出力対策だけでは効率的なコードを書くことができない、全てのインジェクションを防止できない(単純ミス、勘違いなどを防げない)、実際に多数のインジェクション脆弱性がソフトウェアに作られている現状があるからです。
文字エンコーディングバリデーションがない場合の例:
- 非効率:バリデーションしない場合、プログラム中で何度もバリデーションを行う必要が発生する
- ミス:バリデーションしていない文字列を誤って利用する
このような状態は文字エンコーディングのバリデーションのみではありません。数値などでも同じです。
インジェクション対策の必要十分条件は
- 出力対策
- 入力対策
です。入力対策ではパラメーターをバリデーションします。入出力対策だけでは安心できないので”縦深防御”を追加することも可能です。
なぜ議論がかみ合わないのか?
話をしていて「セキュリティ対策の議論がかみ合わない根本的原因は大垣さんは必要十分条件の話をしているのに、一部の必要条件だけで十分条件になる誤解している人がいる」なので「そもそも議論にさえならない」と指摘されました。
全くその通りだと思いました。「一部の必要条件だけで十分だと」と誤解している人に「これも必要ですよ」と指摘しても誤解している限り議論になりません。
まとめ
インジェクション対策に必要な知識は外部システムの種類、APIの種類によって増えます。こういう個々の脆弱性問題”だけ”を理解するよりテキストインターフェース処理の基本などを理解し、テキスト処理系には一切そのまま変数を連結しない、を理解した方がはるかに有意義で応用が効きます。基本を理解すれば自分で必要十分条件を見つけられます。
何事でも必要十分条件を考えることが重要です。いつも当たり前に必要十分条件を考えるようにしている(しかし、これが本当に難しい。完璧にできていればバグのあるコードなど書きません)ので、他の方も同じという前提でいたことが間違いでした。
PHPカンファレンスでも、PostgreSQLセミナーでも「そもそも議論にならないことを議論している」と指摘いただきました。確かにその通り!議論の進め方には注意します!
必要条件だけで十分条件だと勘違いしないよう注意しましょう!