パート 5

脆弱な構成

アプリケーションは、たいてい攻撃者による攻撃に便利なデフォルト設定でインストールされています。 特にこれは、実行しているアプリケーションやフレームワークと同じものに、 攻撃者が簡単にアクセスできるサードパーティーのソフトウェアに関する問題です。 ハッカーはデフォルトのアカウント名とパスワードを知っています。 例えば、 jdata.py を見ると、 それがデフォルトのアカウント名は ‘admin’、パスワードは ‘secret’ というのがわかります。 ハッカーが利用するリソースの例として http://www.governmentsecurity.org/articles/default-logins-and-passwords-for-networked-devices.html を参照してください。

脆弱な構成もまた攻撃箇所を増やす特徴があります。 例にあるように、デフォルトの構成は脆弱なため、使わないようにします。 それは、ステータスページやエラーのスタックトレースのダンプ等のデバッグ機能が含まれています。

情報漏洩 #1

white box 脆弱な構成を利用し、実行中のサーバのデータベースの内容を取得してください。

Gruyere のコードからデフォルトの構成や、機能とは関係ないデバッグ機能を探します。

ヒント

ヒント 1

Gruyere にインストールされているすべてのファイルを見てください。あってはならないファイルがありませんか ?

ヒント

ヒント 2

どこからも参照されてない .jtl ファイルを見てください。

ノート

攻撃方法と解決方法

攻撃方法 は、以下の URL により データベースのコンテンツを表示する、 dump.jtl というデバッグ用のダンプページを利用します:

http://google-gruyere.appspot.com/123/dump.jtl

解決方法 は、常にデバッグ機能がインストールされていないか確認します。 この場合は、 dump.jtl を削除します。 これはアプリケーション内に誤って残してしまったデバッグ機能の一例です。 このようなデバッグ機能が必要な場合は、慎重に厳重にロックします。 管理者ユーザのみにアクセスを許可し、デバッグ用の IP アドレスからのリクエストのみを処理するようにします。

この攻撃はユーザのパスワードを公開します。 パスワードはプレインテキストで保存しないようにしましょう。 パスワードはハッシュ化します。 認識として、ユーザ認証は、パスワードそのものを知っておく必要はなく、 ユーザがパスワードを知っていることを確実にするためのものです。 ユーザがパスワードを設定した際に、 そのパスワードのハッシュ値と、ハッシュ生成のためのセキュリティ文字列のみを保存します。 ユーザがパスワードを再入力した際に、そのハッシュ値を再計算し、 それが合致している場合にパスワードが正しいと判断します。 攻撃者がハッシュ値を取得したとしても、元のパスワードに復元するのは不可能に近いでしょう。 (また、ユーザは多くの指摘があるにもかかわらず、 脆弱なパスワードを複数のサイトで使いまわしているので、それは大変良い考えです)

情報漏洩 #2

white box 上記を解決しても、攻撃者はそれを元に戻し、攻撃を実行することができます。なぜでしょうか ?

ヒント

ヒント

どんな形式のファイルでもアップロードすることができます。

ノート

攻撃方法と解決方法

攻撃方法 は、Gruyere は .jtl を含むあらゆる形式のファイルをアップロードできます。 これにより、攻撃者は dump.jtl 等のファイルをアップロードし、アクセスすることができます。 実際、先述したように、 HTML 、JavaScript 、 Flash などファイル形式に関係なく、 サーバに任意のコンテンツをアップロードできるのはセキュリティリスクです。 明確でないファイル形式を許可する機能は、セキュリティーホールとなるかもしれません。

解決方法 は、いくつか実施しなければならないことがあります:

  1. Gruyere に含まれるファイルは、テンプレートとみなします。
  2. ユーザがアップロードしたファイルはアプリケーションファイルと同じ場所に格納しないようにします。
  3. アップロード可能なファイルの形式の制限 (ホワイトリストの利用など) を検討してください。

情報漏洩 #3

white box 上記を解決しても、異なる攻撃方法により同様の攻撃が可能です。みつけることができますか ?

この攻撃は脆弱な構成ではなく、悪意のあるコードによります。

ヒント

ヒント 1

データベースの内容を表示するための何かを、プライベートスニペットに挿入できます。

ヒント

ヒント 2

この攻撃は前述と密接に関係しています。 テンプレート拡張コードのバグを利用します。

ノート

攻撃方法と解決方法

Gruyere のテンプレートの変数を展開し再評価するコードにバグがあります。 具体的にはブロックを展開する際に、ブロック変数も展開します。 その後、テンプレートとしてブロックを解析し、再び変数を展開します。

攻撃方法 は、以下のプライベートスニペットを追加します:

{{_db:pprint}}

解決方法 は、変数が挿入された際に絶対に再評価されないようにテンプレートコードを変更します。 コード上の欠陥は、 ExpandTemplate_ExpandBlocks の後に _ExpandVariables を呼び出していますが、 _ExpandBlocks は内部で ExpandTemplate を呼び出しています。 入り組んでいるので難しく聞こえるかもしれません。 ブロックと変数を別々に解析するのは初歩的な展開の設計ミスですが、解決は簡単ではありません。

テンプレート言語が任意のデータベースに直接アクセスできるのがこの攻撃の原因です。 テンプレートが提供されたデータのみしかアクセスできないのであれば、それは安全です。 例えば、テンプレートはデータベースのクエリに関連付けられており、 そのクエリにマッチするデータだけをテンプレートに渡します。 これによりバグのスコープが、そのユーザにアクセスを許可されたデータにのみに制限します。

AJAX の脆弱性

誤った AJAX コードにより、 攻撃者が意図しない方法でアプリケーションの一部を修正できるかもしれません。 従来のクライアントアプリケーション開発では、 アプリケーションと表示用のデータを明確に分離していました。 次の 2 つの攻撃で、それが Web アプリケーションには通用しないことが明確になります。

AJAX による DoS

black box ユーザのホームページ上で、プライベートスニペットを見れなくする攻撃を見つけてください。 (攻撃は “refresh” リンクをクリックすると発動しますが、XSS を使う必要はありません。)

ヒント

ヒント 1

AJAX レスポンスでプライベートスニペットの値を変更する方法がわかりますか ?

ヒント

ヒント 2

JSON オブジェクトが同じキーバリューを持っている場合、何がおこりますか ?

ノート

攻撃方法と解決方法

攻撃方法 は、 private_snippet という名前のユーザを作成し、 1 つ以上のスニペットを作成します。 JSON レスポンスは {'private_snippet' : <user's private snippet>, ..., 'private_snippet' : <attacker's snippet>} のようになり、 ユーザのスニペットが攻撃者のものと置き換わります。

解決方法 は、AJAX コードはデータが必要と仮定した場所だけデータを送信するようにします。 ここでの欠陥は JSON の構造が強くないことです。 いい構造とは [<private_snippet>, {<user> : <snippet>,...}] なります。

AJAX によるフィッシング

前述の攻撃は重要でなく不便に思うかもしれませんが、 不注意な DOM 操作はより深刻な問題に発展させることができます。

black box 右上にあるロゴのリンクを ``http://evil.example.com`` へ変更する方法を見つけてください。

(攻撃は “refresh” リンクをクリックすると発動しますが、XSS やスクリプトを使う必要はありません。)

ヒント

ヒント 1

スクリプトがどのようにページ上のスニペットを置き換えるかを見てください。 それと関連させて、ロゴ内のリンクも置き換えることができますか ?

ヒント

ヒント 2

それがどのように各スニペットを置き換えるか AJAX コードを見てください。 また、ホームページの構造を確認し、他に何を置きかえれるかを見てください。 (直接ロゴ内のリンクを置き換えることはできません。他に置きかえれるものがあります。)

ノート

攻撃方法と解決方法

攻撃方法 は、 menu-right というユーザを作成し、 右側のメニューバーに表示するための以下のようなスニペットを作成します。

<a href='http://evil.example.com/login'>Sign in</a>
| <a href='http://evil.example.com/newaccount.jtl'>Sign up</a>

ユーザが既にログインしている場合は、メニューバーは壊れて見えます。 しかしそれは問題ありません。 ユーザが何か起こっていると重い、一度ログアウトし、ログインすれば万事うまく行きます。

解決方法 は、DOM を修正するプロセスは、より強固にします。 ユーザの値を DOM の要素識別子内で利用する場合は、 ユーザの値にプリフィックス id="user_" を追加するなど、 それが衝突しないようにします。 より良いのは、ユーザの値ではなく、新たな別の識別子を利用します。

ユーザが Sign in をクリックし、 evil.example.com が表示されるのであれば、 攻撃は簡単に見つけることができます。 頭がいい攻撃者は、より発見を難しくするために、 Sign in リンクを現在のページにレンダリングし、 別のサーバにフォームを送信するスクリプトに書き換えます。

その他の脆弱性

バッファオーバーフローとインテジャーオーバーフロー

アプリケーションが適切にバッファーを保護せず、 ユーザデータがバッファーの終端を超えて書き込みできる場合、 バッファオーバーフロー (Wikipedia: バッファオーバーフロー) の脆弱性があります。 この超過したデータはポインタと関数の戻り先のアドレスを含む他の変数を修正することができるため、任意のコード実行に至ります。 歴史的に、バッファオーバーフローの脆弱性は、 SQL Slammer (Wikipedia: SQL Slammer)、 ブラスター (Wikipedia: ブラスター)、と Code Red ワーム (Wikipedia: Code Red) を含む、 最も広範囲に及んだインターネット攻撃の原因です。 PS2、Xbox や Wii のすべては、バッファオーバーフローを使ってハッキングされました。

同様に、 整数オーバーフロー の脆弱性も計り知れないぐらい危険です。 整数の算術が不適切な結果を返す場合、アプリケーションは不適切な動作をします。 幸いな場合は、アプリケーションが機能しなくなります。 最悪な場合は、セキュリティバグとなります。 例えば、アプリケーションが length + 1 < limit をチェックした場合、 length は最大の正の整数値となり、 それはバッファオーバーフローの脆弱性となります。

Gruyere は Python で書かれているため、この codelab ではバッファオーバーフローの脆弱性を取り扱っていません。 Python は典型的なバッファーや整数オーバーフローに対して脆弱ではありません。 Python は配列外の読み書きができないため、整数があふれることがありません。 C や C++ プログラムがこの脆弱性が最も発生しやすい言語として知られていますが、 他の言語が免れるわけではありません。 例えば、 Java はバッファオーバーフローを防いでいますが、整数オーバーフローは無視します。

SQL インジェクション

XSS の脆弱性が、 攻撃者に Web ページへのスクリプトの混入を許すように、 SQL インジェクション (Wikipedia: SQL インジェクション) の脆弱性は、 攻撃者に SQL クエリに恣意的なスクリプトの混入を許します。 SQL のクエリが実行されると、データの読み書きか可能なため 典型的な XKCD の Bobby Tables というコミックのように (←ちょううけるw) 攻撃者は SQL インジェクションを使ってデータベースを上書きします。 SQL を利用する際の最も重要なアドバイスは、 文字列連結によるクエリの構築を避けることです: その代わりに API を利用します。 Gruyere は SQLを利用していないため、この codelab では SQL インジェクションを取り扱っていません。

Codelab を終えて

この codelab が有益だったことを願っています。 より多くを学びたい場合、Gruyere には前述した以上のセキュリティバグがあります。 学んだことを活用し、 アプリケーションにバグがなく、将来利用されることが決して無いかチェックするため、 アプリケーションを攻撃するユニット (単体) テストを書く必要があります。 ファジング テストツールの利用も検討すべきです。 Google のセキュリティの詳細は、 ブログコーポレートセキュリティ を参照してください。 また、 Google Code University の他の様々なトピックから学習用のリソースをチェックアウトしてください。