xss-sqlinjection-csrf

表示処理、SQL呼び出しおよび「重要な処理」に伴う脆弱性

前回までに、Webアプリケーションの脆弱性の機能と脆弱性の関係、「入力」と脆弱性の関係をまとめた。ここでは、表示処理(XSS)、SQL呼び出しおよび「重要な処理」(CSRF)に伴う脆弱性についてまとめる。

1 表示処理に伴う問題

クロスサイト・スクリプティング(基本編)

概要

Webアプリケーションには外部からの入力などに応じて表示が変化する箇所があり、この部分のHTML生成の実装に問題があると、クロスサイト・スクリプティング(Cross-Site-Scripting:XSS)という脆弱性が生じる。例えば、サイト使用者のブラウザ上で、攻撃者の用意したスクリプトの実行によりクッキー値を盗まれ、利用者がなりすましの被害に遭うといったものがある。

 

XSS脆弱性のまとめ

  • 発生箇所:Webアプリケーション上でHTML、JavaScriptを生成している箇所
  • 影響箇所:Webアプリケーション全体
  • 影響の種類:Webサイト利用者のブラウザ上でのJavaScriptの実行、偽情報の表示
  • 影響の度合い:中〜大
  • 利用者関与の度合い:必要。罠サイトの閲覧、メール記載のURLの起動、攻撃を受けたサイトの閲覧など
  • 対策の概要:属性値はダブルクォート「”」で囲む、HTMLで特別な意味を持つ記号文字をエスケープする

 

攻撃手法と影響

  • クッキー値の盗み出し:1)罠サイトのiframe内で、脆弱なサイトが表示される。2)脆弱なサイトはXSS攻撃により、クッキー値をクエリー文字列につけて情報収集ページに遷移する。3)情報収集ページは受け取ったクッキー値をメールで攻撃者に送信する
  • JavaScriptによる攻撃:例えばXSSを悪用したワーム(JS/Spacehero(samy)、JS.Twettirなど)
  • 画面の書き換え:1)</form>により元のサイトにあるform要素が終了する。2)新しいform要素を開始しstyle指定で改変。3)actionのurlには罠のサイトを指定する
  • 反射型XSSと持続型XSS:攻撃用JavaScriptが攻撃対象サイトとは別のサイトにある場合を反射型XSS(入力値の確認用のページなど)、同じサイトにある場合を持続型XSS(WebメールやSNSなど)と呼ぶ

 

脆弱性が生まれる原因

XSS脆弱性が生じる原因は、HTML生成の際に、HTMLの文法上特別な意味を持つ特殊記号(メタ文字)を正しく扱っていないことである。メタ文字の持つ特別な意味を打ち消し、文字そのものとして扱うためにエスケープという処理を行う。

HTMLエスケープとは、1)要素内容の場合「<」と「&」を文字参照にする、2)属性値の場合属性値を「”」で囲み、「<」と「”」と「&」を文字参照にするといった処理を最低限行うことである。

 

対策

以下の3つの対策が挙げられる。

  • XSS対策の基本:エスケープ対策。PHPではhtmlspecialchars関数が利用できる。セキュリティ上は最初の3つの引数が重要
  • レスポンスの文字エンコーディング指定:header関数を用いる
  • XSSに対する保険的対策:入力値検証。クッキーにHttpOnly属性を付与する。TRACEメソッドの無効化

 

クロスサイト・スクリプティング(発展編)

href属性やsrc属性のXSS

a要素のhref属性、img要素やframe要素、iframe要素のsrc属性などは、URLを属性値としてとる。このURLを外部から変更できる場合、URLとして「javascript:JavaScript式」という形式(javascriptスキーム)で、JavaScriptを起動できる。

  • URLを生成する場合の対策:http: または https: で始まる絶対URLか、スラッシュ「/」で始まる相対URL(絶対パス参照)のみを許容するようにする
  • リンク先ドメインのチェック:リンク先URLを検証してURLが外部ドメインである場合はエラーにするか、外部ドメインへのリンクであることを利用者に注意喚起するためのクッションページを表示する

 

JavaScriptの動的生成

  • イベントハンドラのXSS:1)データをJavaScript文字列リテラルとしてエスケープする。2)この結果をHTMLエスケープする
  • script要素のXSS:script要素内の終端はJavaScriptとしての文脈を一切考慮しないため、最初に「</script>」が出現した時点でscript要素は終わることを悪用する
  • JavaScriptの文字列リテラルの動的生成の対策:1)JavaScriptの文法から、引用符と「\」や改行をエスケープする。2-1)イベントハンドラ中の場合は、1)の結果を文字参照によりHTMLエスケープして「”」で囲む。2-2)script要素内の場合は、1)の結果に「</」という文字列が出現しないようにする。またUnicodeエスケープによる対策や、script要素の外部でパラメータを定義してJavaScriptから参照する方法がある

 

DOM based XSS

DOM based XSSとは、JavaScriptによりクライアント側で表示処理する箇所があり、そこに脆弱性がある場合のXSSのこと。JavaScriptの標準関数にはHTMLエスケープの機能が用意されていないため、jQueryを使って文字列を表示するといった対策が必要である。

 

HTMLタグやCSSの入力を許す場合の対策

HTMLタグやCSSの入力を許可するサイトを開発する場合は、HTMLテキストを構文解析して必要な要素のみを抽出するライブラリを使用することが望ましい。例えば、HTML Purifierなど。

 

エラーメッセージからの情報漏洩

  • エラーメッセージに攻撃者にとって有益なアプリケーションの内部情報が含まれる
  • 意図的な攻撃としてエラーメッセージに秘密情報を表示させられる

情報漏洩を防ぐために、アプリケーションでエラーが発生した場合、画面に表示するのは「アクセスが集中しているのでしばらく待ってからお試しください」など利用者向けのメッセージにとどめ、 エラーの詳細内容はエラーログに出力するように設定するべきである(詳細は後述)。

 

2 SQL呼び出しに伴う脆弱性

SQLインジェクション

概要

SQLインジェクションとは、SQLの呼び出し方に不備がある場合に発生する脆弱性である。例えば、データベース内のすべての情報が外部から盗まれる、データベースの内容が書き換えられるといった影響を受ける可能性がある。攻撃者が能動的に(利用者の関与なしで)サーバーを攻撃できるため、この脆弱性が絶対に混入しないようなプログラミングが求められる。

 

SQLインジェクション脆弱性のまとめ

  • 発生箇所:SQL呼び出しをしている箇所
  • 影響箇所:すべてのページ
  • 影響の種類:情報漏洩、データ改ざん、認証の回避、プログラムの実行、ファイルの参照・更新
  • 影響の度合い:大
  • 利用者関与の度合い:不要
  • 対策の概要:静的プレースホルダを利用してSQLを呼び出す

 

攻撃手法と影響

  • エラーメッセージ経由の情報漏洩
  • UNION SELECTを用いた情報漏洩:2つのSQL分の結果の和集合を求める演算
  • SQLインジェクションによる認証回避:「’ or ‘a’=’a」
  • SQLインジェクション攻撃によるデータ改ざん:iframe要素やscript要素の埋込
  • その他の攻撃:OSコマンドの実行、ファイルの読み出し、ファイルの書き出し、HTTPリクエストにより他のサーバーを攻撃。すべてのデータベースエンジンで発生する共通の影響は、データベース内のデータの読み出し

 

脆弱性が生まれる原因

パラメータとして指定した文字列の一部がリテラル(’Shakespeare’や-5などSQL文中で決まった値を示すもの)をはみ出すことにより、SQL文が変更されること。

  • 文字列リテラルの問題:シングルクォートで囲む。文字列リテラル中にシングルクォートを含めたい場合は、シングルクォートを重ねる(SQL標準規格)
  • 数値項目に対するSQLインジェクション:シングルクォートで囲まない。数値でない文字が現れた時点で数値リテラルは終了する

 

対策

SQL文を組み立てる際にSQL文の変更を防ぐこと。その方法には、1)プレースホルダによりSQL分を組み立てる、2)アプリケーション側でSQL文を組み立てる際に、リテラルを正しく構成するなどSQL文が変更されないようにするというものがある。2)は完全な対応が難しいため、1)が推奨される。

  • プレースホルダによるSQL文組み立て:プレースホルダ(place holder:場所取り)とは、変数や式など可変のパラメータの場所に埋め込んでおくもの(SQL文中の「?」など)。
  • プレースホルダ方式が安全な理由:静的プレースホルダと動的プレースホルダがある。静的プレースホルダの方が以下の理由からより安全(プレースホルダ状態でSQL文がコンパイルされるため、後からSQL文が変更される可能性が原理的にない)
  • プレースホルダを用いた様々な処理:検索条件が動的に変わる(条件設定が可能)場合、様々な列でのソートするなど
  • SQLインジェクションの保険的対策:1)詳細なエラーメッセージの抑止。2)入力値の妥当性検証。3)データベースの権限設定

 

3 「重要な処理」の際に混入する脆弱性

ここで述べる重要な処理とは、ログインした利用者のアカウントにより実行できる、取り消しできない処理のことである。例えば、利用者のクレジットカードでの決済、利用者の口座からの送金、メール送信、パスワードやメールアドレスの変更などである。

 

クロスサイト・リクエストフォージェリ(CSRF)

概要

CSRF(Cross-Site Request Forgeries)とは、「重要な処理」における脆弱性のことである。「重要な処理」の受付に際しては、利用者の意図したリクエストであることを確認する必要がある。しかし、この確認処理が抜けていると、罠のサイトなどを閲覧しただけで利用者のブラウザから勝手に「重要な処理」を実行させられる場合がある。例えば、利用者のアカウントによる物品の購入、利用者のパスワードやメールアドレスの変更などがある。

 

CSRF脆弱性のまとめ

  • 発生箇所:1)クッキーのみでセッション管理が行われているサイト。2)HTTP認証、SSLクライアント証明書、携帯電話の携帯IDのみで利用者の識別が行われているサイト
  • 影響箇所:CSRF脆弱性のあるページのみ
  • 影響の種類:被害者の権限で「重要な処理」が実行させられる。物品購入、掲示板への書き込み、パスワード変更など
  • 影響の度合い:中〜大
  • 利用者関与の度合い:必要。リンクのクリック、攻撃者の罠サイトの閲覧など
  • 対策の概要:「重要な処理」の前に、正規利用者からのリクエストであることを確認する

 

攻撃手法と影響

  • 入力−実行パターンのCSRF攻撃:利用者がログインしており、被害者が罠を閲覧し、罠のJavaScriptにより被害者のブラウザ上で攻撃対象サイトに対して新しいパスワードがPOSTメソッドにより送信されることで、パスワードが変更される
  • CSRF攻撃とXSS攻撃の比較:CSRFは攻撃用リクエストに対するサーバー側の処理を悪用するもので、XSSは攻撃用リクエストがブラウザ上で実行されることで起こる
  • 確認画面がある場合のCSRF攻撃:hiddenパラメータ(type属性がhiddenのinput要素)の使用、セッション変数を使う方法

 

脆弱性が生まれる原因

以下の2つのWebの性質が背景にある。

  1. form要素のaction属性にはどのドメインのURLでも指定できる
  2. クッキーに保管されたセッションIDは、対象サイトに自動的に送信される

1.は罠などのサイトからでも、攻撃サイトにリクエストを送信できるということ。2.は罠経由のリクエストに対しても、セッションIDのクッキー値が送信されるので、認証された状態で攻撃リクエストが送信されるということ。

 

対策

CSRF対策は、以下の2点を実施し、さらに保険的対策を講じるのがよい。

  • CSRF対策の必要なページを区別する:1)要件定義工程で機能一覧を作成・マーク。2)基本設計工程で画面遷移図を作成・マーク。3)開発工程でCSRF対策を作る
  • 正規利用者の意図したリクエストを区別できるよう実装する:1)秘密情報(トークン)の埋め込み。2)パスワード再入力。3)Refererのチェック
  • CSRF攻撃への保険的対策:重要な処理の実行後に、対象利用者の登録済みメールアドレスに対して、処理内容の通知メールを送信することを推奨する

 

最後に

表示処理においては、正しいHTMLを生成することがXSS解消の第一歩となる。SQL呼び出しにおいては、静的プレースホルダを利用してSQLを呼び出すことが重要である。「重要な処理」に伴う脆弱性においては、CSRF対策の必要なページを区別し、利用者の意図したリクエストであることを確認することが必要である。いずれの脆弱性対策でも「事前準備」が何よりであることがよくわかる。

著書では「概要−攻撃手法と影響−脆弱性の生まれる原因−対策」という流れで、各脆弱性への対応がまとめられている。phpファイル例での反応と合わせて学習することで、より理解が深まるだろう。また、さらなる情報源としてはせがわようすけ氏による連載や、Justin Clarke「SQL Injection Attacks and Defense, Second Edition」などが参考として挙げられている。興味がある方は見てみることをおすすめする。

次回は、セッション管理の不備、リダイレクト処理、クッキー出力にまつわる脆弱性についてまとめる。

体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>