UUUM攻殻機動隊

UUUMのエンジニアによる技術ブログです

徳丸本から学ぶクロスサイト・スクリプティング基礎

どうも、えんじにあのやまぐちです。

今回の内容ですが、前回に引き続き「安全なWebアプリケーションの作り方」からクロスサイト・スクリプティングの基礎を題材に社内勉強会で発表したので少しだけ書こうと思います。

http://www.amazon.co.jp/exec/obidos/ASIN/4797361190/bz2jp-22/ref=nosim/www.amazon.co.jp

クロスサイト・スクリプティング (XSS)

XSSは外部からの入力に対して表示が変化する箇所がある場合に発生します。
攻撃者が用意したスクリプトがサイト利用者のブラウザ上で実行
されることにより、クッキー値が盗まれ利用者がなりすましの被害に遭う、サイト利用者の権限でWebアプリケーションの機能を悪用される、といったことが起きてしまいます。
また、WEBサイト上に偽の入力フォームを表示され、フィッシングにより利用者の個人情報を盗まれるといったこともあります。

攻撃手法

  • クッキー値の盗み出し
  • JavaScriptによる攻撃
  • 画面の書き換え

クッキー値盗み出しの流れ
罠サイトのiframe内に脆弱なサイトを表示
脆弱なサイトはXSSによりクッキー値をクエリ文字列につけて遷移
情報収集ページは受け取ったクッキー値をメールで攻撃者に送信

反射型と持続型、DOM型

反射型XSS (Reflected XSS)
送信内容のHTMLをそのまま表示してしまう典型的なXSSです。
基本的に攻撃対象サイトとは別のサイトへ誘導しスクリプトを実行させる方法です。

持続型XSS (Stored XSS)
攻撃用プログラムが攻撃対象のDBなどに保存され効果が持続する場合のものを指します。
WebメールやSNSなどが攻撃ターゲットとされる場合が多く、 メリットとしてはサイトを閲覧した全てのユーザにスクリプトが実行されるので攻撃対象を罠サイトへ誘導する手間がかからなかったり、ある程度リテラシーがある利用者でも被害に遭う可能性が高いため、反射型と比べ被害が大きくなりやすいです。

DOM型XSS (DOM Based XSS)
DOM型XSSはJavaScriptを使ってブラウザに表示しているHTMLを操作する場合に、攻撃者の用意したHTMLや文字列を挿入されてしまうことを指します。
攻撃用プログラムが必ずしもDBなどを経由する必要がなく、サーバサイド側で攻撃スクリプトを出力しない場合があるため、攻撃を検知できないないという特徴があります。
JavaScriptが多用される現代のWEBアプリケーションでは、DOM型XSSが入り込む可能性は従来よりも高まっているため対策が必要です。

XSSの原因

XSSの主な原因はHTML生成時に文法上特別な意味を持つ特殊記号を正しく扱っていないため、意図しない形でHTML・JavaScriptを注入・変形できてしまうことです。
そのため、メタ文字の持つ特別な意味を打ち消すエスケープ処理が必要となります。

対策

XSSの必要最低限の対策が以下になります。

  • 要素内容には[<]と[&]をエスケープ
  • 属性値にはダブルクウォートで囲って[<]と[“]と[&]をエスケープ

PHPでのHTMLエスケープではhtmlspecialcharsが利用できます。

string htmlspecialchars(string $string, int $quote_style, string $char)

この関数は最大4つまで引数を設定することができますが、セキュリティ上で必要なのは最初の3つになります。

  • $string: 変換対象の文字列
  • $quote_style: 引用符の変換方法
  • $charset: 文字エンコーディング

$quote_styleには次の引数を指定できますが、それぞれ変換される対象が微妙に違います。

  • ENT_COMPACT (デフォルト: ["]のみ変換)
  • ENT_QUOTES ([']と["]の両方を変換する)
  • ENT_NOQUOTES ([']と["]の両方を変換しない)

$quote_styleについては要素内容であればどの値でも構いません。
逆に属性値の場合はENT_COMPACT、またはENT_QUOTESを指定しましょう。

レスポンスの文字エンコーディング

Webアプリケーション側とブラウザ側で文字エンコーディングに差異があるとXSSの原因になり得ます。

PHPでの文字エンコーディングの指定方法

header(‘Content-Type: text/html charset=UTF-8’);

保険的対策

ここまではXSSの影響を低減するための対策でしたが、保険的に対策する方法も幾つか記載されていました。

入力値検証

入力値の妥当性を検証し、条件に一致しない場合にエラーにします。
入力値検証がXSS対策となり得るには入力値の条件が自由書式ではなく英数字限定時のみとなります。

クッキーにHttpOnly属性を付与

クッキーの属性の一つでJavaScriptからのクッキー読み出しを禁止にします。
読み出しを禁止にすることでセッションIDの盗み出しの防止となります。

PHPでの設定方法

php.ini

session.cookie_httponly = On

TRACEメソッドの無効化

クロスサイト・トレーシング(XST)というJavaScriptでHTTPのTRACEメソッドを送信することでクッキー値、Basic認証パスワードを盗みだすことのできる脆弱性があり、XSSと組み合わせることにより危険性が増します。
このためTRACEメソッドをサーバ側で受け付けない設定が必要となります。
ただ、XSTはXSS脆弱性に起因するものなのでXSSを解消していれば起きることはなく、最近のブラウザでは既に対策が取られているため特殊な場合を除き対策は不要だそうです。

Apacheでの設定

httpd.conf

TraceEnable Off

対策まとめ

必須対策 (個別の対策)

  • HTMLの要素内容はhtmlspecialchrs関数によりエスケープ
  • 属性値はhtmlspecialchrs関数によりエスケープしてダブルクォートで囲む

必須対策 (共通対策)

  • HTTPレスポンスに文字エンコードを明示

保険的対策

  • 入力値を検証
  • クッキーによるHttpOnly属性を付与
  • TRACEメソッドを無効化

UUUMではエンジニアを絶賛募集中です。

我こそはという方、是非履歴書をUUUMまでお送りください。
※毎月29日は肉が食べ放題です