フロントエンドエンジニアのセキュリティ対策について考える

## 導入
Webサイトやアプリのセキュリティ対策というと、バックエンドやインフラの領域だと考える人は多いでしょう。
（実際、私自身も以前はそう思っていました。。。）

ですが、後述するXSSやCSRFなどによる被害に遭わないためにも、フロントエンドのエンジニアがセキュリティの知識を身につけ、脆弱性対策を実装できるようになることは重要です。

そこでこの記事では、フロントエンドへの代表的なサイバー攻撃手法と、それらに対する具体的なセキュリティ対策について、紹介して行きたいと思います。

## セキュリティの基礎知識

ますは、どんなWebサイトやアプリを開発する時でも意識するべき、セキュリティの基礎知識について紹介します！

### HTTPSで安全な通信を行う
#### HTTPとは
![HTTP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621464/a530ba96-f485-3b6f-765a-eae9134f44ba.png)

まず、HTTPSについて説明する前に、前提となるHTTPについて確認しましょう。

HTTPとは、「Hyper Text Transfer Protocol（ハイパーテキスト・トランスファー・プロトコル）」の略で、Webページを環境に依らず問題なく表示するための通信規格（プロトコル）のことです。

HTTPのおかげで、WindowsやMacといったOSの差異、GoogleChromeやSafariなどのブラウザの差異を機にすることなく、同じようにWebページを表示することができます。

ただし、HTTPはあくまでHTML文書の通信のためのプロトコルなので、セキュリティについては考慮されておらず、通信の安全性という点では不十分です。

その欠点をカバーするために生まれたのが、HTTPSというわけです。

#### HTTPSとは
![HTTPS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621464/5b22c682-6416-2185-ad64-c8ad648e88c2.png)

HTTPSとは、TLSという通信プロトコルを用いてセキュリティを高めたHTTPのことです。

TLSを用いることで、「通信データの暗号化」「通信相手の検証」「通信データの改ざんチェック」などが実現され、通信の安全性を高めることができます。

Webサイトの発展と共に盗聴などの手口も増えた現在では、HTTPS化はほぼ必須であると言えるでしょう。

Googleなどの検索エンジンでもSSLを推奨しており、現在ではほとんどのWebページのURLがHTTPSとなっています。

#### HTTPSの導入によるメリット
WebアプリケーションにHTTPSを導入することにより、下記のようなメリットが得られます。

- 通信が暗号化され、ユーザーの個人情報やCookieなどの盗聴を防ぐことができる
- HTTPSのホームページはGoogle・Yahoo!の検索順位が優遇される（SEO効果がある）
- 企業のサービスやホームページに対する信頼性の向上につながる。(HTTPS化されていないホームページは、Google Chromeなどのブラウザで警告が表示される)

### CORSを理解する
#### CORSとは
![CORS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621464/6271444b-e762-d5bd-3c59-af15a6cdbb2c.png)

CORS(Cross-Origin-Resource-Sharing、オリジン間リソース共有)とは、ウェブブラウザが異なるオリジン（ドメイン、スキーム、ポート）のサーバーからのリソースを安全に読み込むことを可能にするセキュリティ機能です。

セキュリティの関係上、ウェブブラウザはデフォルトの状態で、異なるオリジン(クロスオリジン)のリソースへのアクセスを制限します。これを**同一オリジンポリシー**と言います。

これはセキュリティ上とても重要なものですが、全てのクロスオリジンへのアクセスが厳しく制限された状態だと、実現したい機能の開発の妨げになってしまうこともあります。

そこで、CORSによって同一オリジンポリシーを一部緩和し、異なるオリジン間のリソース共有を許可することで、複数のWebアプリケーション同士で連携を行うような機能の実装が可能となるのです。

#### CORSの仕組み
上記の通り、デフォルトの状態では同一オリジンポリシーが働くため、クロスオリジンへのリクエストを行っても、レスポンスのリソースへのアクセスはブロックされてしまいます。

クロスオリジンノリソースへアクセスするためには、レスポンスに特定のHTTPヘッダを付与する必要があります。

##### 単純リクエストの場合

GETやPOSTなどの単純リクエスト[^1]をクロスオリジンに対して行う場合は、**Access-Control-Allow-Origin**ヘッダに、アクセスを許可するオリジンを記載する必要があります。

Expressを使用してサーバーを作成する場合、下記のようなコードになります。

```javascript:api.js

const express = require("express");
const router = express.Router();


router.use((req, res, next) => {
    //レスポンスのHTTPヘッダにアクセスを許可するオリジンを追加する 
    res.header("Access-Control-Allow-Origin", "https://hogehoge.com");
    
    next();
});

module.exports = router;

```

[^1]: WHATWGの「Fetch-Standard」にて、「CORS-Safelisted」と定義されているHTTPメソッドやHTTPヘッダのみが送信されるリクエスト

##### 単純リクエスト以外の場合

PUTやDELETEなどのHTTPメソッドが使われているリクエストは、サーバー内のリソースを変更・削除することができてしまうため、単純リクエストよりも厳重な扱いが必要です。

また、ユーザーが任意のヘッダを付与したリクエストについても、安全性の観点で懸念があります。

そのため、そのようなリクエストに対しては、事前にそのリクエストを送信しても問題ないかどうかを確認する**プリフライトリクエスト**が行われます。

上記のようなリクエストを許可するためには、**Access-Control-Allow-Methods**ヘッダや**Access-Control-Allow-Headers**ヘッダを使用します。

```javascript:api.js

router.use((req, res, next) => {
    //レスポンスのHTTPヘッダにアクセスを許可するHTTPメソッドを追加する 
    res.header("Access-Control-Allow-Methods", "PUT, DELETE");
    
    //レスポンスのHTTPヘッダにアクセスを許可する任意のヘッダ名を追加する
    res.header("Access-Control-Allow-Headers", "X-Token");
    
    next();
});

```

CORSの仕組みを理解して、適切なアクセスリストを定義することで、不必要な外部のリソースから隔離された安全性の高いWebアプリケーションを開発できるようにしましょう。

### 依存関係をきちんと管理する
現代のフロントエンド開発では、さまざまなフレームワークやライブラリが組み合わされて使用されることが多いです。

それらは相互に関連しあい、複雑な依存関係を構築しています。

これらの依存関係を効率的に管理して、アップデートやセキュリティパッチに対応し続けることは、フロントエンドの開発において重要な課題です。

#### 依存関係の管理に役立つツール
- **パッケージマネージャー**
    npmやYarnは、依存関係の追加、更新、削除を自動化し、管理プロセスを合理化します。これにより、開発者は依存関係リストを簡単に定義、保存、維持できます。
     
- **モジュールバンドラー**
    WebpackやRollupは、アプリケーションの資産と依存関係をバンドルして最適化し、読み込み時間を軽減します。
    
- **CI/CDパイプライン**
    継続的インテグレーションとデリバリーは、更新ごとの自動テストとデプロイを可能にし、依存関係の安定性を確保します。

## 代表的なサイバー攻撃とそのセキュリティ対策

次に、フロントエンドの脆弱性が問題となって生じることがある代表的なサイバー攻撃手法について、その対策とともに紹介します！

### XSS(クロスサイト・スクリプティング)
![XSS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621464/0c3d4441-d859-f14d-4547-fd17188ce3e4.png)

#### XSSとは
XSS(クロスサイトス・クリプティング)とは、攻撃者がWebページに悪意のあるコードを埋め込み、そのページを閲覧した不特定多数のユーザーに対して、スクリプト(簡易的なプログラム)を実行させることにより情報の盗取などを行うサイバー攻撃です。

IPAによる脆弱性に関する届出状況の報告書によれば、2023年第一四半期に届出された脆弱性の中で、XSSは最も高い割合(50.9%)を占めています[^2]。

[^2]:  『ソフトウェア等の脆弱性関連情報に関する届出状況[2023年第1四半期（1月～3月）]』 IPA   https://www.ipa.go.jp/security/reports/vuln/software/ps6vr70000011unv-att/vuln_software_report_2023q1.pdf

#### XSSによる被害の例
 - ユーザーの個人情報などの機密情報が攻撃者に奪取される
 - Webアプリケーションが改ざんされ、偽の情報が表示される
 - ユーザーのセッション情報を盗んでなりすまし、意図しない商品の購入などが行われる

#### XSSが発生する例
それでは、実際にどのようにXSSが発生してしまうのか、見ていきましょう。

XSSにはいくつかの種類があり、サーバー側でセキュリティを設けるべきものと、フロントエンドでセキュリティを儲けるべきものがあります。

今回は、フロントエンドのコードの不備によって発生する「DOM-based XSS」について実例を紹介します。

例えば、下記のようなコードでURL内の#以降の文字列を画面上に表示するUIがあったとします。


```javascript: xss.js

const message = decodeURIComponent(location.hash.slice(1));
document.getElementById("message").innerHTML = message;

```

通常の文字列がURLに含まれている場合、下記のようにテキストが画面に表示されるだけで特に問題は起こりません。

通常のURL: [ https://xss.com/#ねこは可愛い ]　

```html: xss.html
<div id="message">ねこは可愛い</div>

```

しかし、下記のようなURLではどうでしょうか。

XSSが発生するURL: [ https://xss.com/#＜img src onerror="location.href='https://virus.com'" /＞ ]

この場合、画面に表示されるHTMLは下記のようになります。

```html: xss.html
<div id="message">
    <img src onerror="location.href='https://virus.com'" />
</div>

```
上記のコードでは、img要素のsrc属性が正しく設定されていないため、onerror属性に指定されたlocation.hrefが実行されます。

その結果、攻撃者が用意した悪意のあるサイトに遷移してしまう、という訳です。

#### XSSへの対策方法
実際のアプリケーション開発においては、XSS対策を自動で行ってくれるライブラリやフレームワークを使用する場合がほとんどでしょう。

【XSS対策として有効なライブラリやAPI】
* [DOMPurify](https://www.npmjs.com/package/dompurify)
* [Sanitizer API](https://developer.mozilla.org/ja/docs/Web/API/HTML_Sanitizer_API)

しかし、それらのライブラリやフレームワークが行っているXSS対策の仕組みをきちんと理解しておくことは、フロントエンドのエンジニアとして大切なことだと思います。

下記に、基本的なXSSの対策方法について紹介します。

* プログラム上特別な意味を持つ文字や記号は、&lt; &gt; &amp;などのHTMLエンティティに置換する(**エスケープ処理**)。
* valueなどの属性値を文字列として扱う場合は、直接値を代入せずクォーテーションで囲む。
* 動的にhref属性を設定するような実装の際は、「javascript:」から始まるスクリプトを防ぐため、「http://」や「https://」で始まるURLのみを許可する**ホワイトリスト方式**で実装する。
* 外部からの入力内容を画面に表示するUIの場合、innerHTMLではなくcreateElementやappendChildなどDOM操作用の関数やプロパティを使用する。
* CSP(Content-Security-Policy)を使用する

### CSRF(クロスサイト・リクエストフォージェリ)
![CSRF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621464/163c8342-3ad4-9d04-8a7e-eff38723429f.png)

#### CSRFとは
CSRFとは、攻撃用のWebページにアクセスしてきたユーザーのセッション情報などを利用することによって、ユーザーが使用しているWebアプリケーションに対して、ユーザーの意図しない不正なリクエストを送信する、サイバー攻撃の一種です。

#### CSRFの被害例

* ログイン後の利用者のみが利用可能なサービスの悪用
不正な送金、利用者が意図しない商品購入、利用者が意図しない退会処理 等

* ログイン後の利用者のみが編集可能な情報の改ざん、新規登録
各種設定の不正な変更（管理者画面、パスワード等）、掲示板への不適切な書き込み 等

#### CSRFの対策方法

- CAPTCHA(画像認証)やワンタイムトークンによるリクエストの照合強化
- **Originヘッダ**を検証することで、指定したサイト以外からのリクエストは処理を行わないようにする
- **SameSite Cookie**機能を利用して、同一サイト以外へCookieを送信しないようにする

### クリックジャッキング
![クリックジャッキング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621464/47f5442e-1184-ed45-f030-fa62fece9d39.png)

#### クリックジャッキングとは

クリックジャッキングとは、Webサイト上に隠蔽・偽装したリンクやボタンを設置し、サイト訪問者を視覚的に騙して悪意のあるリンクをクリックさせ、意図しない操作をするよう誘導させる攻撃手法です。

#### クリックジャッキングの被害例

* 意図しない商品を購入させられる
* SNSで特定のアカウントをフォローさせられる、投稿させられる
* Adobe Flashを使ってWebカメラやマイクを作動させられる
* ウイルスを感染させられる

#### クリックジャッキングへの対策方法
* HTTPレスポンスヘッダに**X-FRAME-OPTIONS**を追加し、外部サイトからのiframeによる埋め込みを制限する。
* CSPの**frame-ancestors**を指定し、外部サイトからのiframeによる埋め込みを制限する

### オープンリダイレクト
![オープンリダイレクト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621464/ee61f812-d1f2-f970-649e-28df521f612f.png)

#### オープンリダイレクトとは
オープンリダイレクトとは、Webアプリケーション内の他ページや外部サイトに遷移するためのリダイレクト機能を悪用し、被害者を攻撃者が用意したページに誘導する攻撃手法です。

#### オープンリダイレクトの被害例

* 誘導先のコンテンツとしてクレジットカード情報やログインID、パスワードなどの入力を促す内容を表示することで、被害者の機密情報を窃取する

#### オープンリダイレクトの対策方法

* リダイレクトの遷移先のURLを静的にする
* 遷移先のURLに識別コードを割り当てて、リダイレクト先を自由に指定できないようにする
* リダイレクト先として渡されたURLをサーバ側で検証したり、WAF等を用いてアクセス制御したりすることで、意図したドメインの場合のみ遷移を行う
* MAC(Message Authentication Code)などを利用し、リダイレクト先URLが攻撃者によって改ざんされていないことをサーバ側で確認した上で、Webアプリケーションによる遷移を行う


## まとめ
いかがでしたでしょうか？
これらはあくまで基本的な内容ではありますが、意外とフロントエンドでも考慮すべき点がたくさんありますよね。

今後、フロントエンドの実装に取り組む際に、この記事の内容が参考になれば幸いです！


## 参考文献
- 『フロントエンド開発のためのセキュリティ入門 -知らなかったでは済まされない脆弱性対策の必須知識-』 平野晶士 著、はせがわようすけ、後藤つぐみ 監修
- [MDN オリジン間リソース共有 (CORS)](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)
- [AWS CORSとは](https://aws.amazon.com/jp/what-is/cross-origin-resource-sharing/)
- [WHATWG Fetch Standard](https://fetch.spec.whatwg.org/)
- [ソフトウェア等の脆弱性関連情報に関する届出状況[2023年第1四半期（1月～3月）]』 IPA](  https://www.ipa.go.jp/security/reports/vuln/software/ps6vr70000011unv-att/vuln_software_report_2023q1.pdf)