Published on

安全なWebアプリケーションの作り方メモ

Authors

Webアプリケーションの脆弱性とは

  • 脆弱性があるとダメな理由

    • 経済的損失
    • 法的な要求
      • 個人情報の保護に関する法律
      • 個人情報保護委員会が定める各種ガイドライン
    • 利用者が回復不可能なダメージを受ける場合が多い
    • Webサイト利用者に嘘をつくことになる
    • 攻撃インフラ(ボットネットワークなど)構築に加担してしまう
  • 脆弱性が生まれる理由

    • バグによるもの
    • チェック機能の不足によるもの

Webセキュリティの基礎〜HTTP、セッション管理、同一オリジンポリシー、CORS

  • GETとPOSTの使い分け

    • GETメソッドは参照(リソースの取得)のみに用いる
    • GETメソッドは副作用がないことが期待される
    • 秘密情報の送信にはPOSTメソッドを用いる
      • GETでない理由
        • URL上に指定されたパラメータがReferer経由で外部に漏洩するため
        • URL上に指定されたパラメータがアクセスログに残る
        • URL上のパラメータがブラウザのアドレスバーに表示され他人にのぞかれる
        • パラメータつきのURLを利用者がソーシャルネットワークなどで共有してしまう
  • クッキーによるセッション管理

    • クッキーが保持できる値の個数や文字列長には制限がある
    • クッキーの値は利用者本人から参照・変更できるので、秘密情報の格納には向かない
  • セッションIDに求められる要件

    • 第三者がセッションIDを推測できないこと
    • 第三からセッションIDを強制されないこと
    • 第三者にセッションIDが漏洩しないこと
  • セッションID漏洩の原因 − クッキー発行の際の属性に不備がある

    • ネットワーク的にセッションIDが盗聴される
    • XSSなどアプリケーションの脆弱性により漏洩する
    • PHPやブラウザなどプラットフォームの脆弱性により漏洩する
    • セッションIDをURLに保持している場合は、Refererヘッダから漏洩する
  • クッキー発行の際の属性に不備がある

    • Domain
    • Path
    • Expires
    • Secure
    • HttpOnly
  • 能動的攻撃

    • 攻撃者がWebサーバーに直接攻撃すること
  • 受動的攻撃

    • 攻撃者がサーバーを直接攻撃するのではなく、Webサイトの利用者に罠を仕掛けることにより、罠を閲覧したユーザを通してアプリケーションを攻撃する手法
    • 単純な受動的攻撃
      • 罠サイトに利用者を誘導する
  • 正規サイトを悪用する受動的攻撃

    • 正規のサイトに罠が仕込まれる
      • 罠サイトに誘導する手間が要らない
      • 正規サイトは利用者が多いので被害が拡大する可能性が高い
      • 正規サイトの機能を不正利用することにより攻撃者にメリットが得られる
      • 利用者の個人情報を盗むことにより攻撃者にメリットが得られる
      • 手法
        • FTPなどのパスワードを不正入手してコンテンツを書き換える
        • Webサーバーの脆弱性をついた攻撃によりコンテンツを書き換える
        • SQLインジェクション攻撃によりコンテンツを書き換える
        • SNSなど利用者が投稿できるサイト機能のXSS脆弱性を悪用する
  • サイトをまたがった受動的攻撃

    • 罠サイトと正規サイトをまたがった攻撃
      • 手順
        1. 利用者が罠サイトを閲覧する
        2. 罠サイトから、仕掛けを含むHTMLをダウンロードする
        3. HTMLの仕掛けが発動して正規サイトに攻撃のリクエストを送信する
        4. 正規サイトからJavaScriptなどの仕掛けを含むレスポンスが変える
  • ブラウザはどのように受動的攻撃を防ぐか

    • サンドボックス
      • 利用者に配布元を確認させた上で、利用者が許可した場合のみ実行する
      • プログラムの「できること」を制限するサンドボックスという環境を用意する
    • JavaScriptのサンドボックス
      • ローカルファイルへのアクセス禁止
      • プリンタなどの資源の利用禁止(画面表示は可能)
      • ネットワークアクセスの制限(同一オリジンポリシー)
  • 同一オリジンポリシー

    • JavaScriptなどのクライアントスクリプトからサイトをまたがったアクセスを禁止するセキュリティ上の制限
  • 同一オリジンである条件

    • URLのホストが一致している
    • スキーム(プロトコル)が一致している
    • ポート番号が一致している
  • JavaScript以外のクロスドメインアクセス

    • frame要素とiframe要素
      • JavaScriptによってクロスドメインのドキュメントにアクセスすることは禁止されている
    • img要素
      • src属性はクロスドメインの指定が可能
    • script要素
      • src属性を指定すると他のサイトからJavaScriptおを読み込むことができる
    • CSS
      • クロスドメインでの読み込みが可能
    • form要素のaction属性
      • クロスドメインの指定が可能
      • form要素の仕様を悪用した攻撃手法がCSRF攻撃
  • Access-Control-Allow-Origin

    • クロスオリジンからの読み出しを許可するための仕掛け
    • HTTPレスポンスヘッダとして出力
  • 特定の条件を満たす「シンプルなリクエスト」の場合、XMLHttpRequestを用いて異なるオジリンにHTTPリクエストを送ることが相手側の許可なしに可能

    • シンプルなリクエストの要件
      • メソッドは下記のうちのいずれか
        • GET
        • HEAD
        • POST
      • XMLHttpRequestオブジェクトのsetRequestHeaderメソッドで設定するリクエストヘッダは以下に限る
        • Accept
        • Accept-Language
        • Content-Language
        • Content-Type
      • Content-Typeヘッダは以下のいずれかであること
        • application/x-www-form-urlencoded
        • multipart/form-data
        • text/plan
  • プリフライトリクエスト

    • 「シンプルなリクエスト」の条件を満たさない場合、ブラウザは、プリフライトリクエストというHTTPリクエストを送信
  • 認証情報を含むリクエスト

    • XMLHttpRequestオブジェクトのwithCredentialsプロパティをtrueにする
    • レスポンスヘッダとしてAccess-Control-Allow-Credentials: trueを返す

Webアプリケーションの機能別に見るセキュリティバグ

  • 脆弱性はどこで発生するのか

      • HTMLの出力
      • HTTPヘッダの出力
      • SQL分の呼び出し
      • シェルコマンドの呼び出し
      • メールヘッダおよび本文の出力
    • 脆弱性には処理に起因するものと出力に起因するものがある
    • 入力に起因する脆弱性はない
    • 出力に起因する脆弱性には「インジェクション」という単語がつくものが多い
  • Webアプリケーションの「入力」では何をするか

    • 文字エンコーディングの妥当性検証
    • 文字エンコーディングの変換(必要な場合のみ)
    • 入力値(パラメータの文字列)の妥当性検証
  • 入力値検証のないアプリケーションでは、以下のような現象が起こりえる

    • 数値のみを受け付ける項目に英字や記号を入力して、DBのエラーになる
    • 更新処理が途中でエラーになり、DBの不整合が発生する
    • 利用者が多数の項目を入力して実行ボタンをクリックしたら内部エラーとなり、入力を最初からやり直すはめになる
    • メールアドレスの入力を忘れているのにアプリケーションがメール送信処理を実行する
  • 入力値検証の目的

    • 入力値の間違いを早期に発見して再入力を促すことにより、ユーザビリティ(使いやすさ)を向上する
    • 間違った処理を継続することによるデータの不整合などを防ぎ、システムの信頼性を向上させる
  • 入力値検証がセキュリティの役に立つケース

    • SQLインジェクション対策が漏れていたパラメータがあるが、英数字のみ許可していたので実害にならない
    • PHPのバイナリセーフでない関数を使っているが、入力段階で制御文字をチェックしているので実害には至らない
    • 表示処理の関数に文字エンコーディングを指定を怠っているが、入力段階で不正な文字エンコーディングをチェックしているので実害には至らない
  • 入力値検証の基準はアプリケーション要件

    • 制御文字のチェック
    • 文字数のチェック
    • 数値の最小値・最大値のチェック
      • 数値文字列としての文字種・文字数チェック
      • 文字列型から数値型への型変換
      • 最小値・最大値の範囲にあることの確認
    • その他の注意点
      • 入力項目が指定されていない(項目自体がない)ケース
      • 配列形式で入力されているケース
  • XSS脆弱性による影響

    • サイト利用者のブラウザ上で、攻撃者の用意したスクリプトの実行によりクッキー値を盗まれ、利用者が成りすましの被害にあう

    • 同じくブラウザ上でスクリプトを実行させられ、サイト利用者の権限でWebアプリケーションの機能を悪用される

    • Webサイト上に偽の入力フォームが表示され、フィッシングにより利用者が個人情報を盗まれる

    • XSSの悪用方法

      • クッキー値の盗み出し
      • その他のJavaScriptによる攻撃
      • 画面の書き換え
  • 反射型XSS

    • 多くの場合入力値をそのまま表示するページで発生
  • 持続型XSS

    • WebメールやSNSなどが典型的な攻撃ターゲット
    • 罠サイトに利用者を誘導する手間がかからない
  • XXSに対する保険的対策

    • X-XSS-Protectionレスポンスヘッダの使用
      • 反射型XSSをブラウザが検知
    • 入力値検証
    • クッキーにHttpOnly属性を付与する