Open7

「安全なウェブサイトの作り方」を読む

よつよつ

はじめに

  • 2015年時点で日本におけるインターネット利用者は1億人を超え、なお拡大し続けている
  • 一方、ウェブサイトの脆弱性を狙った事件も増加している
    • 2020年末時点で累計11,526件が報告されている
  • なので、既存の脆弱性から学び、対策していこうね

本書の構成

以下の三部構成。

  • ウェブアプリケーションのセキュリティ実装(各種インジェクション対策など)
  • ウェブサイトの安全性向上のための取り組み(主に運用面)
  • 既存の失敗例
よつよつ

前章:脆弱性対策について

ここでは、脆弱性への対策を2つに分類してある。

  • 根本的解決
    • 脆弱性を作りこまない実装を行うこと
  • 保険的対策
    • 攻撃による影響を軽減するための対策のこと
      • 攻撃される可能性を下げる
      • 攻撃された際、脆弱性を突かれる可能性を下げる
      • 脆弱性を突かれた際、発生する被害を少なくする
      • 被害を早期に発見する
よつよつ

ウェブアプリケーションのセキュリティ実装

ここでは以下の11パターンが取り上げられている。

1) SQL インジェクション
2) OS コマンド・インジェクション
3) パス名パラメータの未チェック/ディレクトリ・トラバーサル
4) セッション管理の不備
5) クロスサイト・スクリプティング
6) CSRF(クロスサイト・リクエスト・フォージェリ)
7) HTTP ヘッダ・インジェクション
8) メールヘッダ・インジェクション
9) クリックジャッキング
10)バッファオーバーフロー
11)アクセス制御や認可制御の欠落

よつよつ

1.1 SQL インジェクション

Webサービス内部で使用されているSQLを悪用し、外部から意図しない情報を引き出したり改ざんしたりすること。
比較的発生件数が多く、全届出件数の11%を占めている(届出開始~2014/第四四半期)。

対象となるウェブサイト

データベースを使用しているウェブサイト全般。

発生しうる脅威

  • データベースに存在する非公開情報の閲覧
    • 例:他ユーザーの個人情報が漏洩する
  • データベースに存在する情報の改ざん、消去
    • 例:ページの改ざん、パスワードの変更、システム停止
  • 認証を回避することによる不正なログイン
    • 例:非ログイン状態で投稿を行う
  • ストアドプロシージャなどを介したOSコマンドの実行
    • 例:システムの乗っ取り、踏み台攻撃での利用

根本的解決

  • SQL 文の組み立てはすべてプレースホルダで実装する

    • 式の中に値をはめ込む部分を記述し、値はあとからはめ込む形式のこと
    • ほとんどの SQL が対応している(例:PostgresSQL
      • 静的プレースホルダ:SQL とパラメータを別々に送信し、データベース上で組み立てる
      • 動的   〃   :呼び出し元のライブラリなどで組み立て、データベースに送信する
        • ライブラリによって無害化されたクエリを、しばしば Prepared Statement(準備された文) という
  • SQL 文の組み立てを文字列連結により行う場合は、エスケープ処理等を行うデータベースエンジンの API を用いて、SQL 文のリテラルを正しく構成する

    • 訳:クエリ中の可変な値はちゃんと無害化してから入れてね
      • 文字列:シングルクォート(')とか危険な文字はエスケープ処理(「'」→「"」)して入れる
      • 数値:型チェックとかで数値リテラルであると確定させる
  • ウェブアプリケーションに渡されるパラメータに SQL 文を直接指定しない

    • 「論外の実装」って書いてあった(当たり前)
    • ユーザーがSQLを指定する形式には絶対しないこと
      • hidden に入れてたとしてもダメ!改変の可能性がある
      • ユーザーにSQLを意識させないように実装されるべき

保険的対策

  • エラーメッセージをそのままブラウザに表示しない

    • エラーを細かく教えてしまうと、SQLインジェクションに繋がる有益な情報となる
    • 利用者のブラウザには表示しないのが好ましい
  • データベースアカウントに適切な権限を与える

    • アプリケーションの権限を不要に上げている場合、被害が深刻化する恐れがある
    • サービスの運用に必要な最低限の権限のみを付与するべき

届出例

  • 「サイボウズ ガルーン」における SQL インジェクションの脆弱性
よつよつ

OS コマンド・インジェクション


Webアプリケーションを介して、アプリを起動しているサーバのOSコマンドを不正に実行すること。
Perl による Web アプリケーションや、組み込み製品の管理画面で用いられる CGI[1] からの報告が多い。

対象となるウェブサイト

サービスの性質を問わず、外部プログラムを呼び出すような関数を使用するアプリケーション(例:eval())。

発生しうる脅威

  • サーバ内ファイルの閲覧、改ざん、削除
  • 不正なシステム操作
  • 不正なプログラムのダウンロード、実行
  • 他システムへの攻撃の踏み台

根本的対策

  • シェルを起動できるような言語機能を使用することを避ける
    • 例:Perl の open 関数は、ファイルパスに「|」(パイプ)を使用することで
      • 後続して書かれた OS コマンドを実行できる
      • この場合、sysopen で代用すればシェルは起動しない
    • 迂回策があれば、そちらを使用するのがベスト

保険的対策

  • シェルを起動できる機能を利用する場合、引数を構成する変数すべてに対してチェックを行う
    • 本来想定している動作のみを許可し、他はすべて弾くように実装する(ホワイトリスト方式)
    • 攻撃に悪用される記号文字(「|」、「<」、「>」等)を弾く(ブラックリスト方式)
      • こちらは漏れが出るため、あまりおすすめしない

届出例

脚注
  1. WebサーバーがWebブラウザなどからの要求に応じてプログラムを実行する仕組み ↩︎

よつよつ

1.3 パス名パラメータの未チェック / ディレクトリ・トラバーサル

webアプリケーションの中には、直接ファイル名を指定しているものがある(例:http://hoge.com/hugahuga.xml などのURLを受け付ける)。これを処理する実装に問題がある場合、攻撃者に任意のファイルを指定され、意図しない挙動を許すことがある。こうした挙動の一種を 「ディレクトリ・トラバーサル」 と呼ぶ。

対象となるウェブサイト

サービスの性質を問わず、外部から指定できるパラメータにファイル名を直接指定しているアプリケーション。

発生しうる脅威

  • サーバ内ファイルの閲覧、改ざん、削除

根本的解決

  • 外部からのパラメータでファイル名を指定する実装を避ける
  • ファイルを開く際は固定のディレクトリを指定し、かつファイル名にディレクトリ名が含まれるようにする
    • パラメータに絶対パス名を指定することで、任意ディレクトリのファイルが開けてしまう場合がある
      open(filename)   // 絶対パスだと任意ファイルが開けてしまう!
      
    • これを避ける実装として、固定のディレクトリ + ファイル名 でファイル名を指定するようにする
      open(dirname + filename)   // dirname を固定して絶対パスを対策する
      
      • ただし、../ などで迂回される
    • パス名からファイル名のみを取り出す API を使用する(最善)
      • 例:PHP の basename()
      open(dirname + basename(filename))
      

保険的対策

  • webサーバ内のファイルへのアクセス権限の設定を正しく管理する
    • ファイルへのアクセス権限を正しく設定することで
    • 想定外のアクセスが発生しても、読み込まれることがない
  • ファイル名のチェックを行う
    • / ../ ..\ 等、ディレクトリを指定できる文字列を事前に弾く
      • ただし、これも完全ではない
      • URL エンコードにより、誤って通してしまう場合がある
        • 例:/ -> エンコードすることで %2F になる
        • デコード後にチェックするようにする

届出例

「Spring Framework」におけるディレクトリ・トラバーサルの脆弱性 https://jvndb.jvn.jp/jvndb/JVNDB-2014-000054