「プログラミングはホワイトリスティングが基本」にブラックリストもホワイトリストもどちらも同じ事を言っていて違いが分からない、とコメントを頂きました。
追記:ブラックリストとホワイトリストの違いが解らない方は、恐らくホワイトリストの基本中の基本は”デフォルトで全て拒否する”であることを理解していないのだと思われます。全て拒否した上で、許可するモノ、を指定しないとホワイトリストになりません。
http://pfrb.blog114.fc2.com/blog-entry-5.html
ホワイトリストとブラックリストは単純な場合は分かりやすいコンセプトですが、ちょっと複雑になると分かりやすいようで境界が分かり辛いコンセプトです。
メールのホワイトリストとブラックリスト
メールを例にホワイトリストとブラックリストの違いと境界の分かり辛さを解説します。
メールにおける単純なホワイトリスト(許可リスト)とは受け取りたいメールアドレスを指定し、そのメールアドレス以外を拒否する機能です。私からのメールを受け取りたければ yohgaki@ohgaki.net をホワイトリストに登録します。
ブラックリスト(拒否リスト)は反対に受け取りたく無いメールアドレスを指定し、そのメールアドレス以外からのメールは受け取る機能です。私からのメールを受け取りたくなければ yohgaki@ohgaki.net を登録します。
単純な場合は、非常にシンプルで分かりやすいコンセプトです。
境界が曖昧なホワイトリストとブラックリスト
メールアドレスの指定にワイルドカード(任意の文字列を表す”*”)を利用可能にすると、ホワイトリストとブラックリストの境界は非常に曖昧になります。
私がアカウントを取得する場合、yohgakiが利用可能な場合はyohgakiをユーザ名として登録しています。私がyohgakiで始まる複数のアカウントを持っている事を知っている知人はyohgaki@ohgaki.netでも、yohgaki@gmail.comでも、yohgaki@yahoo.co.jpでも受信できるようホワイトリストに”yohgaki*”を登録するかも知れません。
反対にブラックリストのユーザは”yohgaki*”を登録して拒否するかも知れません。
“yohgaki“をホワイトリストに登録したユーザは”yohgaki“以外をブラックリストに登録したのと同じです。反対に”yohgaki“をブラックリストに登録したユーザは”yohgaki“以外をホワイトリストに登録した事になります。しかし、目的が私からのメールを許可または拒否したい為に”yohgaki*”をホワイトリスト、ブラックリストに登録したとすると、どちらのリストも目的を果たせなくなる可能性があります。
yohgakiがアカウント名として取れなかったのでyohgaki123, yohgaki456というユーザ名を取得したユーザがいたとすると、”yohgaki“をホワイトリストに登録したユーザの意図に反して、私が所有しないyohgaki123, yohgaki456のユーザ名の持つメールアドレスからのメールが許可されます。”yohgaki“をブラックリストに登録したユーザは私からのメールだけを拒否したかったのに、私が所有しないyohgaki123, yohgaki456のユーザ名を持つメールアドレスからのメールまで拒否してしまう事になります。
この様にワイルドカードを使い出すと一つのルールで複数のアドレスを許可できたり、拒否できるようにすると、拒否しなくないアドレスまで拒否してしまいます。基本的なコンセプトは変わらないのですが、どちらもその基本コンセプトを達成することができなくなり、境界が曖昧になってきます。
しかし、このような例は例外です。
プロアクティブなセキュリティ対策とリアクティブなセキュリティ対策
メールの例で示したようにホワイトリスト、ブラックリストというコンセプトだけでは境界が分かり辛くなります。
プロアクティブ(積極的)なセキュリティ対策とリアクティブ(受動的)なセキュリティ対策というコンセプトでは境界は曖昧になり辛いと考えています。こちらの方が、より分かりやすく実践しやすいと考えているので「Webアプリセキュリティ対策入門」では、セキュリティ対策のコンセプトをプロアクティブな対策とリアクティブな対策に分類し、基本的にプロアクティブなセキュリティ対策を選択するようお薦めしています。
プロアクティブなセキュリティ対策とは、予測不可能なリスクも回避できるよう安全性を保証できる対策のみを採用するセキュリティ対策です。プロアクティブなセキュリティ対策では行っても良い事を定義します。もちろん「行っても良い事」は安全である事が保証できなければなりません。安全であることを保証した「行っても良い事」だけを許可する為、予測不可能なリスクも回避できる可能性が高くなります。(JavaScriptインジェクションが良い例です)
リアクティブなセキュリティ対策とは、既知のリスクを回避できるよう、危険性を防止する対策を採用するセキュリティ対策です。リアクティブなセキュリティ対策では、行ってはならない事を定義します。「行ってはならない事」の危険性は確実です。しかし、危険と分っている「行ってはならない事」を禁止するため、予測不可能なリスクを回避する事は出来ません。(こちらもJavaScriptインジェクションが良い例です。2008年頃のブラウザには制御文字を無視したりするブラウザがあり、ブラックリスト型でJavaScriptインジェクションを防ぐ事は不可能でした。)
ホワイトリスト型のセキュリティ対策とは基本的にはプロアクティブなセキュリティ対策です。安全であると確実に分っている事だけを許可します。ただし、メールの例の様に”yohgaki*”は大垣靖男からのメールアドレスからとして処理する、と定義するのは「予測不可能なリスクも回避できるよう、安全性の保証できる対策(この場合はメールアドレス)のみ採用する」といった考え方に反する危険なルールと言えます。
プロアクティブなアプローチでは、何が安全で何が危険か常に考えながらセキュリティ対策を考えます。リアクティブなアプローチでは何が危険か考えながらセキュリティ対策を考えます。リアクティブなアプローチでは「何が安全か」という視点が無いため、危険を回避できない事が多くなります。
プロアクティブなアプローチは万能か?
プロアクティブなセキュリティ対策が万能か、というと実世界ではどう頑張ってもプロアクティブなセキュリティ対策が取れない場合もあります。例えば、データベースにデータを保存した場合、そのデータがどの様に利用されるか予め分かる事は少ないです。脆弱性があるアプリケーションによってデータベースに保存したデータが利用され、攻撃に利用されるかも知れません。
しかし、どのように利用されるか分からないからと言ってデータベースにデータを保存する場合にどんなデータを入れても良い分けではありません。テキストデータであるなら、最低限文字エンコーディングが正しい事を確認してからデータを保存すべきです。
データベースによっては、自動的に文字エンコーディングが正しいかチェックします。DBMSは文字エンコーディングが正しいかチェックするのでアプリではチェック無しでも大丈夫、とはプロアクティブな考え方のセキュリティ対策では考えません。入力が予定している形式と異なる場合は未知のリスクが発生する可能性がある、と考え正しい形式であるか、入力を受け取った時点でチェックします。データベースに保存する、しないは関係ありません。
リアクティブなアプローチの対策を先に考えてしまうと、プロアクティブなアプローチの対策の出る幕はありません。モグラ叩き、その場しのぎ、ですがリアクティブな対策の方がプロアクティブな対策より採用しやすいからです。
モグラ叩き、その場しのぎなリアクティブなアプローチでは抜け穴を許してしまう可能性が非常に高く、システム構築など、高いセキュリティが要求される場合にはリアクティブな対策ばかり採用していては安全性の高いシステム構築は期待できません。
プロアクティブな対策は万能ではありませんが、可能な限りプロアクティブな対策を先に検討し、採用する事が重要です。例えば、HTMLタグの属性をユーザが選択できるようにするなら、属性値として安全な”アルファベットのみ”の文字列なら許可する、対策を選択するよち、属性値がリストとして定義可能なら、リストに載っている属性値のみを許可する対策を選択すべきです。
ホワイトリストはプロアクティブ、ブラックリストはリアクティブ
違いが分かり辛くなってしまいがちなホワイトリスト的なセキュリティ対策とブラックリスト的なセキュリティ対策ですが、プロアクティブとリアクティブと考えると分かり辛くならないのでは無いでしょうか?
プロアクティブ(ホワイトリスト):確実に安全である物のみを許可
リアクティブ(ブラックリスト):悪いと分かっている物のみを拒否
システム構築の場合、ほとんどの要素が制御可能であるためプロアクティブな対策に大部分に採用可能です。
どちらのアプローチを採用した方が安全なシステムが出来上がるか?議論の必要は無いと思います。
バランスも大事
全ての仕様を厳密にプロアクティブなアプローチに従うと、アプリケーションの仕様、プロジェクトの進行やコストに許容しがたい影響を与える場合があります。私は何事も原理主義は良くないと考えています。状況に合わせて柔軟であることも非常に重要です。
どちらも何が言いたいのか良く分からない、という疑問に対する答えになっていれば良いのですが、どうでしょう?