エスケープファースト、この順序は変えられない

(Last Updated On: 2018年8月8日)

アプリセキュリティ対策の根本的なセキュリティ対策は教育です。セキュリティ対策を教育する場合、エスケープファースト(エスケープを一番)にすると最も高い効果を期待できます。汎用性もあり、自己解決する能力も付きます。

教育がアプリセキュリティ対策の根本的対策である、とすることに異論は無いでしょう。開発者が脆弱な設計をしたり、コードを書いたりしなければ脆弱なアプリケーションは作られません。

このエントリでは出力のセキュリティ対策(教育)をテーマに考えてみます。

効果的なセキュリティ教育の手順

では根本的対策である開発者のセキュリティ教育を効果的に行う手順はどのような手順でしょうか?

セキュリティ対策の基本は「リスク認識」です。幼児が崖や走っている車の危険性を認識できないのは「崖が危険」、「車が危険」だと認識していないからです。人は先ず危険である、とリスクを認識しなければリスク回避やリスク対策を行いません。

Webアプリの構築は危険だとリスクを認識できるようにするにはどうすれば良いでしょうか?

Webアプリはテキストインターフェースのアプリです。多くはただのテキストではなくテキスト”インターフェース”です。つまり、テキストには意味があります。入力テキストよってその意味が変わってしまうような値、つまり攻撃用テキストを含む入力を出力すると攻撃可能な脆弱性が発生します。

テキストには意味があり攻撃用の入力を出力してしまうと攻撃可能な脆弱性を作ってしまう、と理解してもらうにはどうすれば良いでしょうか?

攻撃用の文字列を含むテキスト入力を例示し、攻撃用入力が”意味”を持つテキストの構造を破壊し、どのように攻撃するのか見せると効果的です。わざと脆弱性を作ったセキュリティ教育用のWebアプリもあります。

単純な攻撃では簡単な事しかできないですが、本物の攻撃者ならどこまでやるのか説明すれば危険性は理解できます。

例えばSQLインジェクションに脆弱なら、データベース構造を丸ごと解析(ブラインドSQLインジェクション)されテーブル名・フィールド名・ユーザー名など全て盗まれ、アクセス可能な情報は全て取得・改ざんでき、他のデータベースにアクセスできる仕組みで攻撃対象となったサーバー以外の内部サーバーを攻撃(SSRF)され、条件さえ許せば任意コード・コマンド実行が可能になりサーバーを丸ごと乗っ取られます。最悪、権限昇格バグを突かれ(DBサーバーのOSは古い場合が多い)完全制御されます。任意コード・コマンド実行までほぼ全自動で行うツールも存在します。

これを聞いてSQLインジェクション?何それ放っておいて良いよ、という人はまず居ません。攻撃を防ぐには攻撃用のテキストが意味を持つテキストとしてインジェクション(挿入)されないよう、正確にテキストを管理・処理する必要があると教えます。

ではテキストのインジェクション対策としてどの対策を教えるべきでしょうか?

この流れなら攻撃に利用されたテキストをどうすれば安全になるのかを教えるれば自然です。エスケープ処理をしたテキストを見せて「これなら安全」と説明すると解りやすいでしょう。

テキストインターフェースのシステムにはエスケープ処理が定義されているのにエスケープ関数がない物もあります。例えば、MySQLはSQL識別子のエスケープ関数を実装していません。エスケープAPIが無いような場合でも、完璧に安全なSQL文を生成するために必要なエスケープ処理を教えることは可能です。

これで安全なテキスト操作が理解できるようになります。他人が作ったライブラリやフレームワークなどのエスケープ処理の実装が正しいか、概ね検証できるようになりました。

ライブラリやフレームワークのAPIはエスケープ処理の次に教えると良いでしょう。

厳密にはエスケープAPIもAPIです。この段階で教える、と考えても構いません。エスケープAPIを教えた後にヘルパーAPIとなるようなAPIを教えると解りやすいでしょう。前の段階でエスケープ処理を解説しているので順序としてはエスケープAPI、ヘルパーAPIの順序で教えると自然です。

初学者でも経験者でも「これを使えばOKだよ」という仕組みは勝手に覚えてくれる傾向が強いです。基本処理である「正確なテキスト管理」を教えた上でAPIを教えないと、最も重要なWebアプリセキュリティの基礎である「正確なテキスト管理」が蔑ろにされる可能性が高くなります。Webアプリは基本的にテキストインターフェースのアプリです。「正確なテキスト管理」は必須である、と学習者に理解してもらわないとどこで落とし穴に落ちるか分からなくなります。

「これを使えばOKだよ」と言われてもそれさえできていない人は「リスクを認識していない」事が多いです。リスク認識の段階を通り越して、必要性や制限事項を教えてもなかなか効果は出ません。順番が大切です。

エスケープでもAPIでも安全に出力できない場合もあります。このような場合は確実に安全なテキストであることをバリデーションするしかありません。最後にバリデーションを教えます。バリデーションはホワイトリスト型で行います。

まとめ

出力のセキュリティ対策(教育)は

  1. エスケープ
  2. API(エスケープが不必要なAPI)
  3. バリデーション

の順番で教えると自然で理解しやすく、この手順自体が出力のセキュリティ対策三原則です。どの出力先にでも適用できます。開発者が知らない出力先に出力しなければならなくなった場合、この三原則の順番で必要なセキュリティ対策を確認すれば、ほぼ確実に安全な出力を開発者自身で行えます。

この順番を変えて、「まずAPI」と教えたらどうなるでしょうか?APIの使い方を間違えて非常に危険な利用方法になってしまう場合があります。例えば、LDAPクエリー、XPATHクエリーにエスケープが全く無い例をよく見かけます。LDAP、XPATHにはエスケープAPIが無い場合もあるからです。主な原因は「リスク認識」を誤っているか、「APIを使えばOK」と考えていることにあります。バリデーションを最初に教えると、理解しづらくなる事は明白なので説明の必要は無いと思います。

もっと自然で解りやすい教え方・手順がある場合は是非教えて下さい。

 

楽しく、セキュアにコーディング&トレーニングしましょう!

 

追記: この種類のエントリは必ず誤解する方が居るので書いておきます。セキュリティの基本を理解した上で、実務のルールでAPIファーストにする事は当然ですが推奨です。

このエントリだけを見て、出力のセキュリティ対策三原則だけでOK!と「プリペアードクエリだけでOK!」と同類の誤認識をされると困るので付け足します。

出力セキュリティの鉄則

  1. 一文字でも意味のある文字がある場合はインジェクションが可能と想定する
  2. デフォルトで全て出力にセキュリティ対策のエスケープ/API処理する
  3.  適材適所のエスケープ/APIであるか絶対の確信を持つ(例:LDAPに二種類のエスケープ、SQLに二種類のエスケープ、他いろいろ)

必読エントリ:出力先のシステムが同じでも、出力先が異なる、を意識する

概ねこれでOKです。

参考

 

投稿者: yohgaki