クロスサイトスクリプティングとは、
攻撃者が送り込んだ悪意のコードをそのページを閲覧した不特定多数のユーザーに、スクリプト(簡易的なプログラム)として実行させる
可能性があることを指します。「XSS」などと省略されることもあり、このような攻撃をクロスサイトスクリプティング攻撃
と言います。攻撃者が罠を仕掛けたWebサイトから、標的となる別のWebサイトにユーザーを誘導、つまりサイトをまたいで(サイトをクロスして)攻撃
を行うことが「クロスサイト」の由来となっています。
IPA(独立行政法人情報処理推進機構)の調査によると、2021年4月から6月で届出のあったWebサイトの脆弱性の中で、クロスサイトスクリプティングの件数が最も多く、これまでの累計でも最も多い割合を占めていました。あらゆるWebサイトにおいて注意が必要な脆弱性の一つであるとともに、ソフトウェア製品についてもクロスサイトスクリプティングの脆弱性に関する多くの届出が出されており、対策が求められています。
- 悪意のコードをサイトに仕込み、閲覧したユーザーが実行させられる
- どうやってサイトに仕込むのか?
ウェブアプリケーションの中には、検索のキーワードの表示画面や個人情報登録時の確認画面、掲示板、ウェブのログ統計画面等、利用者からの入力内容やHTTPヘッダの情報を処理し、ウェブページとして出力するものがあります。ここで、
ウェブページへの出力処理に問題がある場合、そのウェブページにスクリプト等を埋め込まれてしまいます
。この問題を「クロスサイト・スクリプティングの脆弱性」と呼び、この問題を悪用した攻撃手法を、「クロスサイト・スクリプティング攻撃」と呼びます。クロスサイト・スクリプティング攻撃の影響は、ウェブサイト自体に対してではなく、そのウェブサイトのページを閲覧している利用者に及びます。
- 出力処理に問題がある場合とはどうのようなことか?
仕組み
クロスサイトスクリプティング攻撃は、ユーザーからの入力データを表示する仕組みになっている、インターネット掲示板やショッピングサイトのようなWebアプリケーションで特に発生しやすい攻撃です。
ユーザーは、攻撃者が罠を準備したWebサイトを閲覧してリンクをクリック
するか、攻撃者が送り付けたメールに含まれる不正なリンクなどによって誘導
され、標的のWebサイトにアクセスします。このとき、標的Webサイトへの入力データとして事前に不正なスクリプトが埋め込まれ
ているため、ユーザーのブラウザー上でスクリプトが実行され、攻撃者による被害を受けてしまいます。
例えば、偽のログインフォームに誘導されて入力したパスワードを盗み取られ
たり、ユーザーに関する情報が保存されたcookieが盗まれ
、ユーザーになりすましてSNSアカウントの乗っ取りやネットバンクでの不正な出金といった被害を受けてしまう危険性があります。
- リンクをつけて誘導して、行った先のサイトのスクリプトがブラウザで実行されて情報が盗られていく
- どうのような対策が必要なのか?
- フィッシングと似ているな
同じように被害件数が増加しているサイバー攻撃に、「フィッシング」があります。
フィッシングは、有名企業や関係者になりすまして
利用者から情報を盗む詐欺行為です。「クロスサイトスクリプティング」も「フィッシング」も情報を盗む犯罪ですが、フィッシングは他の誰かになりすまし、メールやSMSなどのツールを使用する攻撃。
一方でクロスサイトスクリプティングは、WEBサイトの脆弱性を利用した
攻撃です。
- どうやってWEBサイトの脆弱性をつくのか?
- 攻撃者どうやってスクリプトを埋め込むのか?
対策
ユーザーの対策
ユーザーが実施すべき対策としては、当然ながら
ブラウザーなどのアプリケーションを常に最新にアップデート
すること、そしてWebサイトやメールに含まれているリンクを安易にクリックしない
ことです。また、ブラウザーのセキュリティ設定を変更することで、信頼できるWebサイト以外ではJavaScriptなどのスクリプト機能を無効
にするといった方法もあります。ほかにも、ウイルス対策ソフトウェアを導入
し、不正なWebサイトへのアクセスや不正スクリプトの実行を阻止することも有効な対策です。
Webアプリケーション管理者の対策
Webアプリケーション管理者の対策として代表的なものをいくつかご紹介します。
まずは、ユーザーがWebページに入力する内容をそのまま表示せずに、スクリプトとして動作する文字を無効化するエスケープ処理
があります。エスケープ処理は、Webページを作成する際に特別な意味を持つ記号文字(「<」、「&」など)を、意味を持たないただの文字列として認識させる書き方(「<」、「&」など)に書き換える方法
です。これによって、もし仮に攻撃者が不正なスクリプトを埋め込もうとしても、スクリプトが動作しないよう無効化し、攻撃を回避することが可能です。
また、ユーザーが入力に使うことのできる文字の種類を制限することも有効な対策
となるでしょう。例えば、パスワードの入力欄は「半角英数字6文字以上」、郵便番号や電話番号の入力欄は「数字のみ」などといった制限をかけます。この条件に合わない値を入力された場合は再入力を求めることで、不正なスクリプトの入力を防止することができます。
さらに、Webアプリケーションへの攻撃を検知・防御するWAF(Web Application Firewall)製品の導入
も対策の一つです。WAFはユーザーの入力値までチェックすることができるため、不審なアクセスを検知し、クロスサイトスクリプティング攻撃をブロックすることが可能です。
攻撃者につけこまれる脆弱性を作り込んでしまわないよう、Webアプリケーション作成時からこうした対策を実施することはもちろん、改良時に対策の抜け漏れが発生してしまう可能性もあるため、定期的な対策状況の確認が重要
です。
- ユーザーはブラウザを常に最新のアップデートが必要
- 管理者はエスケープ処理、WAF、文字制限を実装する
- 定期的な対策状況の確認が必要
1) HTMLテキストの入力を許可しない場合の対策
2) HTMLテキストの入力を許可する場合の対策
3) 全てのウェブアプリケーションに共通の対策
...
1.5.1 HTMLテキストの入力を許可しない場合の対策
根本的解決
5-(i) ウェブページに出力する全ての要素に対して、エスケープ処理を施す。
ウェブページを構成する要素として、
ウェブページの本文やHTMLタグの属性値等に相当する全ての出力要素にエスケープ処理
を行います。エスケープ処理には、ウェブページの表示に影響する特別な記号文字(「<」、「>」、「&」等)
を、HTMLエンティティ(「<」、「>」、「&」等)
に置換する方法があります。また、HTMLタグを出力する場合は、その属性値を必ず「"」(ダブルクォート)で括るようにします。そして、「"」で括られた属性値に含まれる「"」を、HTMLエンティティ「"」にエスケープ
します。
- 全ての要素に対してエスケープ処理を施す
- 「<」、「>」、「&」等を「&lt;」、「&gt;」、「&amp;」等に置換することで特別な文字として捉えられなくする
- 「&lt;」、「&gt;」、「&amp;」を文字を半角にすると「<」、「>」、「&」と表示されている。
脆弱性防止の観点からエスケープ処理が必須となるのは、
外部からウェブアプリケーションに渡される「入力値」の文字列
や、データベースやファイルから読み込んだ文字列
、その他、何らかの文字列を演算によって生成した文字列
等です。しかし、必須であるか不必要であるかによらず、テキストとして出力するすべてに対してエスケープ処理を施す
よう、一貫したコーディングをすることで、対策漏れ(脚注3)を防止することができます。
- 全てのテキストに対してエスケープ処理を行う
なお、対象となる出力処理は
HTTPレスポンスへの出力に限りません
。JavaScriptのdocument.writeメソッドやinnerHTMLプロパティ等を使用して動的にウェブページの内容を変更する場合
も、上記と同様の処理が必要です。
- httpレスポンスだけはなくjavascriptもエスケープ処理の範囲内になる。
5-(ii) URLを出力するときは、「http://」や 「https://」で始まるURLのみを許可する。
URLには、「http://」や「https://」から始まるものだけでなく、「javascript:」の形式で始まるものもあります。ウェブページに出力するリンク先や画像のURLが、
外部からの入力に依存する形で動的に生成される場合、そのURLにスクリプトが含まれていると、クロスサイト・スクリプティング攻撃が可能
となる場合があります。たとえば、利用者から入力されたリンク先のURLを「<a href="リンク先のURL">」の形式でウェブページに出力するウェブアプリケーションは、リンク先のURLに「javascript:」等から始まる文字列を指定された場合に、スクリプトを埋め込まれてしまう可能性
があります。リンク先のURLには「http://」や「https://」から始まる文字列のみを許可する、「ホワイトリスト方式」
で実装してください。
- 外部からの入力に依存する形で動的に生成される場合、そのURLにスクリプトが含まれていると、クロスサイト・スクリプティング攻撃が可能の文の意味がわからない
- http://」や「https://」から始まる文字列のみを許可
5-(iii) 要素の内容を動的に生成しない。
ウェブページに出力する
<script>...</script>要素の内容が、外部からの入力に依存する形で動的に生成される場合、任意のスクリプトが埋め込まれてしまう可能性
があります。危険なスクリプトだけを排除する方法も考えられますが、危険なスクリプトであることを確実に判断することは難しいため、<script>...</script>要素の内容を動的に生成する仕様は、避ける
ことをお勧めします。
- 要素の内容を動的に生成する仕様は、避ける
5-(iv) スタイルシートを任意のサイトから取り込めるようにしない。
スタイルシートには、expression() 等を利用してスクリプトを記述することができます
。このため任意のサイトに置かれたスタイルシートを取り込めるような設計
をすると、生成するウェブページにスクリプトが埋め込まれてしまう可能性があります。取り込んだスタイルシートの内容をチェックし、危険なスクリプトを排除する方法も考えられますが、確実に排除することは難しいため、スタイルシートを外部から指定可能な仕様は、避けることが望まれます
。
- スタイルシートを外部から指定可能な仕様は避ける
- 要素の内容が、外部からの入力に依存する形で動的に生成される場合とは何か?
保険的対策
5-(v) 入力値の内容チェックを行う。
入力値すべてについて、ウェブアプリケーションの仕様に沿うものかどうかを確認する処理を実装し、仕様に合わない値を入力された場合は処理を先に進めず、再入力を求めるようにする対策方法です。ただし、この対策が有効となるのは限定的です。例えば、アプリケーションの要求する仕様が幅広い文字種の入力を許すものである場合には対策にならないため、この方法に頼ることはお勧めできません。対策になるとすれば、アプリケーションの要求する仕様が英数字のみの入力を許すものである場合などであり、この仕様の入力についての内容チェックはクロスサイト・スクリプティング攻撃を防止できる可能性が高いですが、この場合も、入力値の確認処理を通過した後の文字列の演算結果がスクリプト文字列を形成してしまうプログラムとなっている可能性を想定すれば、やはり完全な対策ではありません。
1.5.2 HTMLテキストの入力を許可する場合の対策
根本的解決
5-(vi) 入力されたHTMLテキストから構文解析木を作成し、スクリプトを含まない必要な要素のみを抽出する
入力されたHTMLテキストに対して構文解析を行い、「ホワイトリスト方式」で許可する要素のみを抽出します。ただし、これには
複雑なコーディングが要求され、処理に負荷がかかるといった影響
もあるため、実装には十分な検討が必要です。
- 複雑なコーディングが要求され、処理に負荷がかかるといった影響とはどのように複雑なのか?
保険的対策
5-(vii) 入力されたHTMLテキストから、スクリプトに該当する文字列を排除する。
入力されたHTMLテキストに含まれる、
スクリプトに該当する文字列を抽出し、排除してください。抽出した文字列の排除方法には、無害な文字列へ置換することをお勧め
します。たとえば、「<script>」や「javascript:」を無害な文字列へ置換する場合、「」「xjavascript:」のように、その文字列に適当な文字を付加
します。他の排除方法として、文字列の削除が挙げられますが、削除した結果が危険な文字列を形成してしまう可能性
(脚注4)があるため、お勧めできません。なお、この対策は、
危険な文字列を完全に抽出することが難しいという問題
があります。ウェブブラウザによっては、「java script:」や「java(改行コード)script:」等の文字列を「javascript:」と解釈してしまうため、単純なパターンマッチングでは危険な文字列を抽出することができません
。そのため、このような「ブラックリスト方式」による対策のみに頼ることはお勧めできません
。
- 危険な文字列を完全に抽出することが難しい
- 「ブラックリスト方式」による対策のみに頼ることはお勧めできません
- どのような対策をすればいいのか?
1.5.3 全てのウェブアプリケーションに共通の対策
根本的解決
5-(viii) HTTPレスポンスヘッダのContent-Typeフィールドに文字コード(charset)を指定する。
HTTPのレスポンスヘッダのContent-Typeフィールドには、「Content-Type: text/html; charset=UTF-8」のように、文字コード(charset)を指定できます。
この指定を省略した場合、ブラウザは、文字コードを独自の方法で推定して、推定した文字コードにしたがって画面表示を処理します
。たとえば、一部のブラウザにおいては、HTMLテキストの冒頭部分等に特定の文字列が含まれていると、必ず特定の文字コードとして処理されるという挙動が知られています。
- 文字コード(charset)を指定を省略するとブラウザは、文字コードを独自の方法で推定してしまう
- HTMLテキストの冒頭部分等に特定の文字列が含まれていると、必ず特定の文字コードとして処理されるとはどのようなことか?
Content-Typeフィールドで文字コードの指定を省略した場合、攻撃者が、この挙動を悪用して、
故意に特定の文字コードをブラウザに選択させるような文字列を埋め込んだ上、その文字コードで解釈した場合にスクリプトのタグとなるような文字列を埋め込む可能性
があります。
- 故意に特定の文字コードをブラウザに選択させるような文字列を埋め込ませ、ブラウザが推測しスクリプトのタグとなるような文字列を埋め込ませる。
たとえば、具体的な例として、HTMLテキストに、
「+ADw-script+AD4-alert(+ACI-test+ACI-)+ADsAPA-/script+AD4-」
という文字列が埋め込まれた場合が考えられます。この場合、一部のブラウザはこれを「UTF-7」の文字コードでエンコードされた文字列として識別します。これがUTF-7として画面に表示されると「<script>alert('test');</script>」
として扱われるため、スクリプトが実行されてしまいます。
- +ADw-script+AD4-alert(+ACI-test+ACI-)+ADsAPA-/script+AD4-」が「<script>alert('test');」として読み込まれてしまう
ウェブアプリケーションが、前記 5-(i) の「エスケープ処理」を施して正しくクロスサイト・スクリプティングの脆弱性への対策をしている場合であっても、本来対象とする文字がUTF-8やEUC-JP、Shift_JIS等の文字コードで扱われてしまうと、「+ADw-」等の文字列が「エスケープ処理」されることはありません。
この問題への対策案として、「エスケープ処理」の際にUTF-7での処理も施すという方法が考えられますが、UTF-7のみを想定すれば万全とは言い切れません。またこの方法では、UTF-7を前提に「エスケープ処理」した結果、正当な文字列(たとえば「+ADw-」という文字列)が別の文字列になるという、本来の機能に支障をきたすという不具合が生じます。
したがって、この問題の解決策としては、
Content-Typeの出力時にcharsetを省略することなく、必ず指定することが有効
です。ウェブアプリケーションがHTML出力時に想定している文字コードを、Content-Typeのcharsetに必ず指定してください(脚注5)。
- Content-Typeは必ず指定する
保険的対策
5-(ix) Cookie情報の漏えい対策として、発行するCookieにHttpOnly属性を加え、TRACEメソッドを無効化する。
「HttpOnly」は、Cookieに設定できる属性のひとつで、これが設定されたCookieは、HTMLテキスト内のスクリプトからのアクセスが禁止
されます。これにより、ウェブサイトにクロスサイト・スクリプティングの脆弱性が存在する場合であっても、その脆弱性によってCookieを盗まれるという事態を防止
できます。
- HTMLテキストとは?
- 「HttpOnly」でCookieを盗まれるという事態を防止できる
具体的には、Cookieを発行する際に、「Set-Cookie:(中略)HttpOnly」として設定します。 なお、この対策を採用する場合には、いくつかの注意が必要(脚注6) です。
HttpOnly属性は、
ブラウザによって対応状況に差
がある(脚注7)ため、全てのウェブサイト閲覧者に有効な対策ではありません
。
- HttpOnly属性は、`ブラウザによって対応状況に差があるため全てのウェブサイト閲覧者に有効な対策ではありません
本対策は、クロスサイト・スクリプティングの脆弱性のすべての脅威をなくすものではなく、
Cookie漏えい以外の脅威は依然として残る
ものであること、また、利用者のブラウザによっては、この対策が有効に働かない場合がある
ことを理解した上で、対策の実施を検討してください。
- cookieの対策であるため、それ以外の脅威はある
- 今まで読んだ対策が有効にならない可能性がある。
5-(x) クロスサイト・スクリプティングの潜在的な脆弱性対策として有効なブラウザの機能を>有効にするレスポンスヘッダを返す。
ブラウザには、クロスサイト・スクリプティング攻撃のブロックを試みる機能を備えたものがあります。しかし、
ユーザの設定によっては無効になってしまっている場合がある
ため、サーバ側から明示的に有効にするレスポンスヘッダを返す
ことで、ウェブアプリケーションにクロスサイト・スクリプティング脆弱性があった場合にも悪用を避けることができます。ただし、下記に示すレスポンスヘッダは、いずれもブラウザによって対応状況に差がある(脚注8)ため、全てのウェブサイト閲覧者に有効な対策ではありません。
- サーバ側から明示的に有効にするレスポンスヘッダを返すことで悪用を防ぐことができる。
【X-XSS-Protection】
「X-XSS-Protection」は、ブラウザの「XSS フィルタ」の設定を有効にするパラメータ
です。ブラウザで明示的に無効になっている場合でも、このパラメータを受信することで有効になります。 HTTP レスポンスヘッダに「X-XSS-Protection: 1; mode=block」のように設定することで、クロスサイト・スクリプティング攻撃のブロックを試みる機能が有効
になります。
- XSSに対して有効になる
【Content Security Policy】
「Content Security Policy (CSP)(脚注9)」は、ブラウザで起こりうる問題を緩和するセキュリティの追加レイヤー
です。その機能の一つに、反射型クロスサイト・スクリプティング攻撃を防止する「reflected-xss」
があります。HTTP レスポンスヘッダに「Content-Security-Policy: reflected-xss block」
のように設定することで、クロスサイト・スクリプティング攻撃のブロックを試みる機能が有効になります。
- 追加レイヤーとはTCP/IPのレイヤーと関わりがあるのだろうか?
無さそう
- 反射型クロスサイト・スクリプティングとは?
注意が必要なウェブサイトの特徴
運営主体やウェブサイトの性質を問わず、あらゆるサイトにおいて注意が必要な問題です。
Cookieを利用してログインのセッション管理を行っているサイト
や、フィッシング詐欺の攻撃ターゲットになりやすいページ(ログイン画面、個人情報の入力画面等)を持つサイト
は、特に注意が必要です。この脆弱性が生じやすいページの機能例
- 入力内容を確認させる表示画面(会員登録、アンケート等)
- 誤入力時の再入力を要求する画面で、前の入力内容を表示するとき
- 検索結果の表示
- エラー表示
- コメントの反映(ブログ、掲示板等) 等
出典
- ほとんどのサイトは気をつけないといけない
参考資料