プログラミングではホワイトリスティングが基本

(Last Updated On: )

ホワイトリスト方式の優位は神話」と題するエントリに私のブログホワイトリストはどう作る? が引用されている事を教えていただきました。

ホワイトリストの基本中の基本は”デフォルトで全て拒否する”であることに注意してください。全て拒否した上で、許可するモノ、を指定しないとホワイトリストになりません。

誤解されないように書こうとすると、どうしても長文になります。暇な方だけお付き合いください。

参考: セキュリティを論理的に構築する方法 (こちらは科学的なセキュリティの基本構造の作り方の話です。ぜひどうぞ)

意地悪なブログエントリと書籍の文章

まず、ちょっと意地悪なブログエントリと書籍の文章を同列に比較されても困ります。言い訳ですが著書の”Webアプリケーションセキュリティ対策入門”では金床さんと同様の表現になっています。90年代にホワイトリスティングとブラックリスティングの議論は出尽くしているので自慢になりませんが、書籍の発行年度は私の方が早いです。

ついでのように紹介して恐縮だが、大垣さんの書かれたホワイトリストはどう作る?は、ホワイトリスト神話の悪しき例と言わざるを得ない。

スクリプトインジェクション(XSS)防止にブラックリストが機能しない事は明らかです。ホワイトリストはどう作れば良いか参考となるリンクです。どう作るか書いておいても古くなる可能性が高いので、どこを参考に作れば良いか参考URLを書いておきます。

以下のリンクの情報からスクリプトのインジェクションがどのように行えるかを参考にホワイトリストを作れば概ね間違いないと思います。

Follow up:

XSS Cheat Sheet

http://ha.ckers.org/xss.html

スクリプトインジェクション手法の中でも有名な手法を集めているサイトです。XSSロケータと呼ばれている文字列はスクリプトインジェクション脆弱性検出に重宝します。よくある脆弱性であればこの文字列で簡単に検出できます。

[ホワイトリストはどう作る?より引用]

大垣さん、これではホワイトリストではなくて、ブラックリストそのものです。

多分XSSロケータを紹介した事により、ブラックリストを紹介している、と誤解されたのかと思います。こういった文字列で悪意のある攻撃者は攻撃してくる、という基礎知識を身につけた上でホワイトリストを作らないとトンデモない物になる事を知って欲しいという意図があります。

そして、XSS Cheat Sheetを見てブラックリスティングでは対応できない事を理解して欲しい、という意図があります。

タイトルに「ホワイトリストはどう作る?」と付けて、肝心の作り方を書いていないのは読まれた方自身で理解してもらえれば、それが最も良い事である、と考えたのでホワイトリストの作り方を解説していません。

一方、興味深いことに、金床さんの書かれたウェブアプリケーションセキュリティには、同じ題材を取り扱っているが、その記述はまるで異なる。

WAFを使用しブラックリスト方式のシグネチャマッチングによってXSS対策を行う場合、攻撃を完全に防ぐことは不可能である。これはXSSを引き起こす可能性のある文字列が非常に多岐にわたるためだ。このことは非常によく知られたドキュメントであるXSS Cheat Sheetを見るとよくわかる。【中略】望ましい対策として、パラメータごとにホワイトリスト式のチェックを行う方法が考えられるが、残念ながら多くのウェブアプリケーションではホワイトリストをきちんと定義することが難しい【中略】従って、WAFを使ってXSS攻撃を完璧に防ぐことは期待できない (P92〜P94)。

[ウェブアプリケーションセキュリティより引用]

同書の書評でも述べたが、オープンソースのWAFの開発者としてホワイトリストとブラックリストの両方に真剣に向き合ってきたからこそ書ける、正確かつ誠実な記述である。

“Webアプリケーションセキュリティ対策入門”にも”くどい”と思われるかもしれない程、同じような記述があります。

確かに、このエントリだけを読んだ方には誤解してしまう可能性がある多少意地悪なエントリです。しかし、少し私のブログや書籍を読めば「プログラミングにおけるブラックリスティングはやってはならないバッドプラクティスだ」と一貫して主張しているとすぐ解ると思います。

ホワイトリストはどう作る?」は誤解され易いと思いつつ書いたエントリなので誤解が無いよう追記しました。よろしければ「ホワイトリストはどう作る?」もご覧ください。

敵を知り、己れを知れば、百戦危うからず

XSS Cheat Sheetを紹介した意図は「ブラックリストを作っても意味がほとんど無い」事を紹介する、というより実証する為に紹介しています。XSS Cheat Sheatを読み、理解して、どのようなホワイトリストを書くべきか、またホワイトリストのつもりで書いたフィルタ類がどれだけ穴だらけだったのか、などを自分で考えられるようになると思い紹介しているます。XSS Cheat Sheetの中身を見れば直ぐに解る、と思ったのですが読まないと解らないでしょうね。

XSS Cheat Sheetを読んで、それでもまだブラックリスト方式でXSSが防げる、と考える方がいるとしたら重症です。

開発者が忙しいのは解っています。しかし、重要なセキュリティ対策の基本的な知識は、なぜその対策が有効なのか、自分で読んで理解してから使って欲しいです。攻撃者がどの様に攻撃してくるか知らないと、付け焼き刃の防御法では守りきれない事が非常に多いです。

笑い話のようですが「SQLインジェクション対策として全てプリペアードクエリを使っているから安全です」と聞いていても実際にコード監査をすると、SQLインジェクション対策=プリペアードクエリ、と勘違いした開発者により

$sql = ‘SELECT * FROM ‘.$_GET[‘table_name’].’ WHERE abc = $1′;
pg_query_params($dbconn, $sql, array($_GET[‘abc’));

のようなクエリがありました。テーブル名はプリペアードクエリのパラメータとして指定できないのでユーザ入力がそのままプリペアードクエリ生成に利用されている失敗例です。SQLインジェクションの原理を正しく理解している人には当たり前の笑い話でも、”SQLインジェクション対策=プリペアードクエリ”としか覚えていない初心者には理解できません。

「敵を知り、己れを知れば、百戦危うからず」にする為には、攻撃方法や初学者の間違いを理解し、それでも安全なシステムやコードが作れるよう対策しなければなりません。

コンテンツとシステムのセキュリティ

徳丸さんのブログで”コンテンツのセキュリティ対策”におけるホワイトリスティングとブラックリスティングと、”システム開発のセキュリティ対策”におけるホワイトリスティングとブラックリスティングが同等の物であるかのような書き方をされている事が気になりました。

コンテンツはWebユーザにとって”制御できない”データの集まりです。ホワイトリスティング、ブラックリスティングにより主張されるような問題が発生する事は当然です。白黒付けるにも個人の主観が大きく関係します。様々な情報が掲載されているのでURLで単純に選別できる物でもありません。Goo Kidsの様に子供にも安全なページとして毎日新聞のURLを設定していたら問題があった事例もありました。コンテンツは日々更新されています。信頼のおけるサイトであっても広告に悪意のあるHTMLが含まれているケースもあります。コンテンツにはグレーゾーンが多くあり、ホワイトリスティングとブラックリスティング両方に存在価値があります。

システムは開発者・運営者によって”制御できる”物とデータの集まりです。Webシステムのサーバ側は開発者・運営者が自由にコントロール可能な環境です。コンテンツの様に制御がまったく不可能なデータの集まりではなく、ある程度制御されたデータを完全に指示どおりに動作するよう制御されたプログラムが扱う世界です。(たとえ、指示が間違いであっても)

システム上におけるセキュリティ問題に関してグレーゾーンはほとんど無いと言えます。攻撃できないか?攻撃できるか?攻撃できるとすればどの程度容易に攻撃できるか?で判別できます。ベストプラクティスの綺麗なコードであっても、攻撃できれば黒(脆弱性)なのです。バッドプラクティスの怪しいコードや設計であっても攻撃できなければ白です。

コンテンツのセキュリティとシステムにセキュリティを同列に並べるのは無理があります。

コンテンツにおいてブラックリスティング、ホワイトリスティングは別の目的や成果を得るために使い分けが可能で、優劣を論ずるのはあまり意味がありません。

システムのセキュリティにおいては”攻撃を防ぐ目的”にホワイトリスティング、ブラックリスティングを利用します。自ずと比較対象となります。比較の結果、ホワイトリスティング型セキュリティの方がより効果的に安全性を向上できる事は明白です。

コンシューマ向けシステムとWebシステム

コンピュータシステム上のセキュリティ問題として、コンシューマ向けのソフトウェアホワイトリスティングはあまり効果的ではないのは同じ意見です。しかし、企業内などのコントロールされた環境下で、インストールされるソフトウェアはホワイトリスト方式で管理されるべきですし、多くの会社がそうしています。運用管理システムには動作しているプロセスをホワイトリスト方式で監視できる物が多くあります。

Webシステムも規模の大小はあれ、コントロールされた環境です。コントロール可能な環境下ではホワイトリスト型のセキュリティ対策が非常に有効に機能します。Webシステムのサーバ側のシステムは、企業内システムにインストールされるソフトウェアと同様、ホワイトリスト方式で管理できるのであれば、ホワイトリスト方式で管理する方がブラックリスト方式で管理するより安全であることには明白です。

システムにおけるホワイトリスティング優位は事実

プログラムのコード中の1000万行の内、9,999,999行が完璧でも、たった1行おかしな行があるだけで有効な攻撃が可能となるのはよく在ることです。脆弱性が発生しないようにする為には、危ういコードだが攻撃はできないグレーゾーン、と呼べるようなコーディングを排除するようにしなければなりません。その為にはセキュアな設計とコード監査が書かせません。コード監査の重要性は私一人が言っている事ではなく、コード監査が重要であることはセキュリティ専門家全員が認めている事です。システムの安全性確保は安全な設計と安全なコードから始まります。

プログラミングに於いて、ホワイトリスティングの方が優位であることは”神話”ではなく”事実”です。私個人がそのように考えているのではなく様々なセキュリティ標準やセキュリティベストプラクティスでは基本的にホワイトリスティング型のセキュリティ対策を採用すべきとし、多重のセキュリティ対策としてブラックリスティング型のセキュリティ対策も採用するように奨めています。

WAFは基本的にはブラックリスティング型のセキュリティ対策です。もちろん、ホワイトリスティング型の定義で安全性を向上させる事もできます。入力値を厳格にチェックするにはアプリケーションの仕様は当然、データの使われ方まで把握しないとならない場合も少なくありません。

しかも、いくら厳格にチェックしても、データの用途が複数の場合、WAFではどうチェックしても安全性を維持できない場合は幾らでもあります。アプリケーションの内部で対応しなければ本当の安全性など達成できないのです。つまり、ホワイトリスティング型のセキュリティ対策を行う適切かつ最適は場所は、コードの中であり、システムの中なのです。付属のシステムと言えるWAFで十分な安全性は期待できません。

WAFは無用か?

WAFは有用であり、安全なシステム運用には欠かせません。しかし、間違ったWAFの使い方が少なくありません。この為、WAFの危険性を訴えるセキュリティ専門家も少なくありません。実際、間違ったWAFの使い方の例は多くあります。このブログでも国連の例を紹介しています。

WAFは有用だと最初に書きましたが、どんなWAF嫌いでも、絶対に反論できない用途があります。ゼロデイ攻撃対策です。WAFの殆ど機能はアプリケーションに実装できますが、ゼロデイ攻撃やそれに近い攻撃には、アプリケーションではまったく対応できない場合があります。

WAFの利用は最小限度に留め、必要なセキュリティ対策はアプリケーション内で行うのが最も効率的なセキュリティ対策です。

セキュリティ対策のベストプラクティスでは、多重のセキュリティが適用可能な場合は可能な限り実装する事が望ましい、とされています。その意味で、WAFを”追加”のセキュリティ対策としてホワイトリスト型の定義を利用してアプリケーションを保護する事にまったく異論はありません。

決して行ってはならないのはWAFで保護しているから大丈夫、とシステム上で対策できる問題を放置する事です。Webセキュリティ対策はあくまでもWebシステムが”主”でありWAFは”従”です。

関連:

 

投稿者: yohgaki