攻撃から学ぶXSS対策

#はじめに
WEBエンジニアとして成長するために、セキュリティ対策は避けては通れない道ですよね。

僕も含め**「なんとなく知ってる」**という方は多いのではないでしょうか。

大切なWEBサイトを守るためにも、WEBエンジニアとしての基礎を固める為にも、しっかりと学んで一緒にレベルアップしていきましょう。

また、本記事の内容は様々な文献をもとに自身で調べ、試したものをまとめています。
至らぬ点や、間違いがありましたら、コメントにてご指摘をお願いします。

#XSSってなに？
XSS（Cross-site scripting）とは、他人のブラウザーで悪意のあるJavaScriptを実行するコードインジェクション攻撃です。

ターゲットに標的を定めて攻撃するのではなく、ターゲットがアクセスするWEBサイトの脆弱性を悪用して、悪意のあるJavaScriptを実行します。

このように攻撃者が直接攻撃していることは被害者には分からないので

**自分のサイトが気がついたら犯罪に加担していた**

という最悪の事態も考えられます。

#JavaScriptでどんな攻撃ができるか
上記のように悪意のあるコードを実行することで、以下のような攻撃が可能です。

* Cookieなどの機密情報の一部へのアクセス
* XMLHttpRequestなどを利用して任意の情報をHTTPリクエストを任意の宛先に送信
* DOM操作メソッドを使用して、WEBページのHTMLに変更を加える

単体ではあまり効果を発揮しませんが、これらを組み合わせることで強烈な攻撃を行うことが出来ます。

###Cookieの盗難
攻撃者は、Webサイトに関連付けられた被害者のCookieにアクセスして、自分のサーバーに送信することで、セッションIDなどの機密情報を取得することが可能です。

###キーロギング
キーロギングとはユーザーがキーボードでPCに入力する内容を密かに記録する行為です。
これにより、パスワードやクレジットカード番号などの機密情報を記録して任意の宛先に送信することが可能です。

###フィッシング
DOM操作を使用して偽のログインフォームをページに挿入し、formのaction属性を任意のサーバーに設定することで機密情報を送信させることが可能です。

これらはあくまで一例で、組み合わせ次第では更に手の込んだ攻撃が出来ます。

#XSSのタイプ
XSSには3つのタイプが存在します。

###Persistent XSS
1. 攻撃者はWebサイトのフォームを使用して、データベースに悪意のあるスクリプトを挿入します。
2. 被害者はWebサイトにページをリクエストします。
3. Webサイトの応答には、データベースからの悪意のあるコードが含まれ、被害者に送信されます。
4. 被害者のブラウザ内で、悪意のあるスクリプトを実行され、被害者の情報が攻撃者のサーバーに送信されます。

###Reflected XSS
1. 攻撃者は悪意のあるスクリプトを含むURLを作成して被害者に送信します。
2. 被害者は、悪意のあるスクリプトを含むURLのページをリクエストします。
3. レスポンスにはURLに含まれる悪意のあるスクリプトが含まれています。
4. 被害者のブラウザ内で、悪意のあるスクリプトを実行され、被害者の情報が攻撃者のサーバーに送信されます。

###DOM-based XSS
1. 攻撃者は悪意のあるスクリプトを含むURLを作成して被害者に送信します。
2. 被害者は、悪意のあるスクリプトを含むURLのページをリクエストします。
3. レスポンスにはURLに含まれる悪意のあるスクリプトが含まれていません。
4. 応答された正当なDOMをレンダリングした後に、悪意のあるスクリプトがページに挿入されます。
5. 被害者のブラウザ内で、挿入された悪意のあるスクリプトを実行され、被害者の情報が攻撃者のサーバーに送信されます。

###Reflected XSS と DOM-based XSSの違い
この2つのタイプはとても似ています。

Reflected XSSは、悪意のあるスクリプトをページに挿入した状態で応答します。
被害者のブラウザが応答を受信すると、悪意のあるスクリプトがページの正当なコンテンツの一部であると想定し、他のスクリプトと同様に**ページのロード中**にそれを自動的に実行します

DOM-based XSSは、悪意のあるスクリプトを含まない正当な状態で応答します。
ページの読み込み中に自動的に実行されるスクリプトはあくまで正当なものです。
**ページが読みこまれた後に既存のJavaScriptの脆弱性が原因**で悪意のあるスクリプトが含まれたURLが実行されてしまいます。

Reflected XSS や Persistent XSS の例では、URLに悪意のあるスクリプトを仕込むことで、攻撃していた為、JavaScriptは必要ありませんでした。

つまりサーバー側のコードに脆弱性がない場合、WebサイトはXSSの対策が出来ていると言えます。

ですが、近年のWebアプリケーションの発達に伴い、サーバーではなくクライアント側のJavaScriptによって生成されるHTMLの量が増えています。

つまり、XSSの脆弱性は、サーバー側のコードだけでなく、クライアント側のJavaScriptコードにも存在する可能性があると言えます。


##XSSへの対策について
XSS攻撃は悪意のあるスクリプトを、ユーザーの入力値として解釈されることが原因で起こる、コードインジェクション攻撃です。

**このタイプの攻撃を防ぐには、安全な入力処理が必要になります。**

僕たちWEB開発者ができる対策を挙げてみましょう。
対策の細かい設定は別に調べてもらった方がいいと思うので簡略的に説明します。

###エスケープ処理の追加
入力された値をエスケープし、スクリプトではなく文字列としてのみ解釈するようにする。 
###厳密なバリデーション処理
想定する値以外を入力できないように、可能な限り厳密に入力をフィルタリングする。
###適切なレスポンスヘッダーの使用
HTMLまたはJavaScriptを含めることを意図していないHTTP応答でのXSSを防ぐために、`Content-Type`および`X-Content-Type-Options`ヘッダーを使用して、ブラウザーが意図したとおりに応答を解釈できるようにする。
###エンコード処理の追加
ユーザーが入力したデータがHTTP応答で出力される場合は、出力をエンコードしてアクティブコンテンツとして認識されないようにする。
###CSPルールのセット
コンテンツセキュリティポリシー（CSP）ルールの適切なセットを適用すると、ブラウザーがインラインJavaScript、eval（）、setTimeout（）、または信頼できないURLからのJavaScript などを実行しないようにする。

#まとめ
実際に文字にしてみると、分からない事や、不明確なまま理解している事が多かったです。
`セキュリティ`という大きな検索で調べるのではなく、`XSS`などの具体的な攻撃方法で検索した方が、たくさんの情報がヒットするので、興味のある方は更に調べてみてください。

海外エンジニアの記事などはサンプルコードなども掲載しており、とても参考になりました。

次はXSRFについてまとめていきたいと思います。

### 参考文献
[A comprehensive tutorial on cross-site scripting](https://excess-xss.com/)
[JavaScript Security Issues and Best Practices](https://blog.bitsrc.io/javascript-security-issues-and-best-practices-37e78df4dce4)