安全なWebサイトの作り方 失敗例 要約

前の記事で書いたものは省略しています。

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

失敗例

「"」と「;」、「'」、「<」、 「>」、「|」、「 (空白)」を削除する関数を使っていた。

失敗の理由

コマンド引数に、入力された値を使用するときは、 シェルで特別な意味を持つ文字である上記の文字群に加えて 「タブ」と「バッククォート」を削除する。 シェルには、バッククォートで囲まれた部分を実行して、 その出力をコマンドラインに反映するという機能があるため。 そして、そのコマンドとコマンド引数を分けるためには、空白に加えてタブ文字も使える。 よってバッククォートと水平タブで自由にコマンドを実行できてしまう。

修正方法

  • ライブラリを使う
  • コマンドの標準入力に値を与える

メールヘッダの差出人(From:)は標準入力で与えることができる。 この場合はコマンドラインの引数に入力された値を 使わなくなるのでOSコマンドインジェクションを解決できるが、 メールヘッダインジェクションの脆弱性が生まれる可能性があるので注意。

  • シェルを経由せずにコマンドを呼び出す

Perlの場合はカンマで区切ることでこれが可能。

不適切なセッション管理

失敗例

  • セッションIDの生成にプロセスIDとUNIX時間を使用
  • セッションIDに接続元IPアドレス、ポート番号、UNIX時間を結合しハッシュ化したものを使用

    失敗の理由

    プロセスIDやUNIX時間は推測可能である。 仮に、自分の後の一分以内にアクセスしてきたユーザが居るとする。 プロセスIDは連番であり、UNIX時間は秒単位なので、 自分の次のプロセスIDと自分の時間から1分以内のUNIX時間の組み合わせは60通りとなる。 これを総当りすればセッションハイジャックが成功する可能性がある。

後者は、 接続元IPアドレスは罠サイトに誘導して取得 接続元ポート番号はだいたい2万通り 時間は10秒前後以内だと仮定して10通り この20万通りを総当りする。

修正方法

セッションIDは暗号論的擬似乱数生成器を用いて生成する。

XSS

失敗例

  • リンクのURLのパラメータのエスケープ処理漏れ

2ページ目に飛ぶリンクのURLがtwo.htmlで、 max_numberからページごとの表示件数をクエリから取得するとき、 現在のページがone.html?max_number=10ならば 次のページのリンクが<a href="two.html?max_number=10"> のように生成されるとする。

このとき、攻撃者がone.html?max_number=<script>...というURLのリンクを掲示板に書き込む。 次のページのリンクのURLの出力時にエスケープ処理が漏れていたとき、XSSが起こる。

  • 404 Not foundで表示するURLのエスケープ処理漏れ

404用のページには、「お探しの nakatta.htmlは見つかりませんでした」 のように、URLがテキストとして出力されるWebサイトがあるとする。

example.com/<scr...というURLのリンクをメールや掲示板に書き込めば、 当然<scr...というページは存在しないので、 リンクを開いた人のブラウザには「お探しの<scr...は見つかりませんでした」と出力される。 このようにXSSが成功する可能性がある。

User-AgentRefererなど、アクセス情報を出力するページは注意が必要。

誤った対策

  • ブラックリスト方式による入力チェックのみを実装

    ヌル文字などの制御文字でマッチングが回避されてしまう可能性がある。

  • 連結処理を悪用した入力チェックの回避

都道府県や市区町村単位で区切って入力し、それらを結合したものを表示する場合は、 一つ目に<scr、二つ目にipt>のように、分割して入力する方法で、 エスケープ処理を回避出来る可能性がある。

  • 危険な文字列を単に削除する方法

単にscriptという文字列を削除する処理の場合、 scriscriptptと入力された時はその結果としてscriptが出力されてしまう。 削除ではなく無害な文字列へ置換すべき。