# 機能設計書 119-入力サニタイズ

## 概要

本ドキュメントは、QuickerSite CMSにおける「入力サニタイズ」機能の設計仕様を定義する。

### 本機能の処理概要

XSS（Cross-Site Scripting）攻撃を防止するための入力値エスケープ機能である。ユーザーからの入力やデータベースからの取得値をHTML出力する際に、特殊文字をHTMLエンティティに変換することで、悪意のあるスクリプトの実行を防止する。

**業務上の目的・背景**：CMSではユーザーがコンテンツを入力・編集できるため、XSS攻撃のリスクが高い。悪意のあるスクリプトが実行されると、セッションハイジャック、フィッシング、情報漏洩などの被害が発生する可能性がある。入力サニタイズにより、これらの攻撃を防止し、安全なコンテンツ表示を実現する。

**機能の利用シーン**：
- フォーム入力値の表示
- データベースから取得した値のHTML出力
- メタタグ（title、keywords、description）の出力
- 検索結果の表示
- ユーザー名・メールアドレス等の表示
- コメント・投稿内容の表示

**主要な処理内容**：
1. sanitize関数：quotRep関数のラッパー（標準的なXSS対策）
2. quotRep関数：HTML特殊文字のエスケープ（"、<、>）
3. quotRepJS関数：JavaScript用のシングルクォートエスケープ
4. removeCRB関数：ASPコード実行ブロックの除去

**関連システム・外部連携**：
- 全てのHTML出力処理
- フォーム処理
- データベース出力

**権限による制御**：認証・非認証に関わらず、全ての出力処理で適用。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 全画面 | 補助機能 | HTML出力時のXSS対策 |
| 196 | メタタグ設定 | 使用 | sanitize()でSEOタイトル等をエスケープ |
| 165 | 検索処理 | 使用 | 検索結果表示時のエスケープ |
| 98 | ショッピングカート管理 | 使用 | 商品名等のエスケープ |
| 59 | ゲストブック一覧 | 使用 | 投稿内容のエスケープ |

## 機能種別

セキュリティ機能 / XSS対策

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| sValue | String | Yes | エスケープ対象の文字列 | isLeegで空チェック |

### 入力データソース

- フォーム入力値（Request.Form、Request.QueryString）
- データベース取得値
- セッション変数
- その他の動的コンテンツ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| エスケープ済み文字列 | String | HTML特殊文字がエンティティに変換された文字列 |

### 出力先

- HTML出力（value属性、テキストコンテンツ等）
- JavaScript文字列

### エスケープ変換表

| 変換前 | 変換後 | 関数 |
|--------|--------|------|
| " (ダブルクォート) | &amp;quot; | quotRep |
| < (小なり) | &amp;lt; | quotRep |
| > (大なり) | &amp;gt; | quotRep |
| ' (シングルクォート) | \\' | quotRepJS |
| <% | (削除) | removeCRB |
| %> | (削除) | removeCRB |

## 処理フロー

### 処理シーケンス

```
1. sanitize関数呼び出し
   └─ quotRep関数を呼び出し
2. quotRep関数処理
   ├─ isLeeg(sValue)で空チェック
   ├─ 空の場合 → そのまま返却
   └─ 空でない場合
       ├─ " → &quot; に置換
       ├─ < → &lt; に置換
       └─ > → &gt; に置換
3. エスケープ済み文字列を返却
```

### フローチャート

```mermaid
flowchart TD
    A[sanitize&#40;sValue&#41;] --> B[quotRep&#40;sValue&#41;]
    B --> C{isLeeg?}
    C -->|Yes| D[そのまま返却]
    C -->|No| E[ダブルクォート置換<br>&quot;]
    E --> F[小なり置換<br>&lt;]
    F --> G[大なり置換<br>&gt;]
    G --> H[エスケープ済み<br>文字列返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-119-01 | HTML出力エスケープ | ユーザー入力やDB値をHTMLに出力する際はsanitize関数を使用 | 全HTML出力 |
| BR-119-02 | 空値チェック | 空値の場合はエスケープ処理をスキップ | 全エスケープ処理 |
| BR-119-03 | 3文字エスケープ | "、<、>の3文字をHTMLエンティティに変換 | quotRep使用時 |
| BR-119-04 | JS文字列エスケープ | JavaScript文字列内ではquotRepJSを使用 | JS出力時 |
| BR-119-05 | ASPコード除去 | コンテンツから<%、%>を除去してコード実行を防止 | removeCRB使用時 |

### 計算ロジック

#### quotRep関数

```vb
function quotRep(sValue)
    if isLeeg(sValue) then
        quotRep = sValue
    else
        quotRep = replace(sValue, """", "&quot;", 1, -1, 1)
        quotRep = replace(quotRep, "<", "&lt;", 1, -1, 1)
        quotRep = replace(quotRep, ">", "&gt;", 1, -1, 1)
    end if
end function
```

#### quotRepJS関数

```vb
function quotRepJS(sValue)
    quotRepJS = replace(sValue, "'", "\'", 1, -1, 1)
end function
```

#### removeCRB関数

```vb
function removeCRB(value)
    ' remove Code Render Blocks
    value = replace(value, "<" & "%", "", 1, -1, 1)
    removeCRB = replace(value, "%" & ">", "", 1, -1, 1)
end function
```

## データベース操作仕様

### 操作別データベース影響一覧

データベース操作なし（文字列変換処理のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Null値 | sValueがNullの場合 | isLeegで検出し、そのまま返却 |
| - | 空文字 | sValueが空文字の場合 | isLeegで検出し、そのまま返却 |

### リトライ仕様

特になし

## トランザクション仕様

データベース操作を伴わないため、トランザクション管理は不要。

## パフォーマンス要件

- エスケープ処理: 1ms以内（replace関数による単純な文字列置換）
- 大量データ処理でも高速（文字列操作のみ）

## セキュリティ考慮事項

1. **XSS対策**: <、>、"をエスケープすることでHTMLタグ・属性インジェクションを防止
2. **ASPコード実行防止**: removeCRBで<%、%>を除去し、サーバーサイドコード実行を防止
3. **JavaScript対策**: quotRepJSでシングルクォートをエスケープし、JS文字列への攻撃を防止
4. **一貫した適用**: sanitize関数を標準APIとして提供し、全コードで一貫した対策を実施

## 備考

- sanitize関数はquotRep関数のエイリアス（ラッパー）
- &（アンパサンド）はエスケープ対象外（一部のケースで問題となる可能性あり）
- シングルクォートはquotRepではエスケープされない（quotRepJSを使用）
- replace関数の第5引数-1は全置換、第6引数1は大文字小文字を区別しない

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

サニタイズ処理の対象となるデータ型を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | functions.asp | `asp/includes/functions.asp` 86-93行目 | isLeeg関数（空値判定） |

**読解のコツ**: isLeegはisNull、isEmpty、trim後空文字をチェック。サニタイズ関数の前提条件。

#### Step 2: コア関数を理解する

サニタイズ処理の中核となる関数を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | functions.asp | `asp/includes/functions.asp` 1065-1073行目 | quotRep関数（HTML特殊文字エスケープ） |
| 2-2 | functions.asp | `asp/includes/functions.asp` 1453-1455行目 | sanitize関数（quotRepのラッパー） |

**主要処理フロー**:
1. **1066行目**: `if isLeeg(sValue)` - 空値チェック
2. **1069行目**: `replace(sValue,"""","&quot;",...)` - ダブルクォート置換
3. **1070行目**: `replace(quotRep,"<","&lt;",...)` - 小なり置換
4. **1071行目**: `replace(quotRep,">","&gt;",...)` - 大なり置換

#### Step 3: 補助関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | functions.asp | `asp/includes/functions.asp` 1074-1076行目 | quotRepJS関数（JS用エスケープ） |
| 3-2 | functions.asp | `asp/includes/functions.asp` 35-42行目 | removeCRB関数（ASPコード除去） |

### プログラム呼び出し階層図

```
sanitize(sValue)
    │
    └─ quotRep(sValue)
           │
           ├─ isLeeg(sValue) ... 空値チェック
           │
           └─ replace() ... 文字列置換（3回）
                  ├─ " → &quot;
                  ├─ < → &lt;
                  └─ > → &gt;

quotRepJS(sValue)
    │
    └─ replace() ... 文字列置換
           └─ ' → \'

removeCRB(value)
    │
    └─ replace() ... 文字列置換（2回）
           ├─ <% → (削除)
           └─ %> → (削除)
```

### データフロー図

```
[入力]                      [処理]                           [出力]

ユーザー入力 ───────────> sanitize() ─────────────────> エスケープ済み
(例: <script>alert(1)</script>)                          (&lt;script&gt;alert(1)&lt;/script&gt;)
                               │
                               v
                         quotRep()
                               │
                               ├─ isLeeg() ─────────> 空チェック
                               │
                               ├─ replace("...")  ───> &quot;
                               │
                               ├─ replace("<")  ────> &lt;
                               │
                               └─ replace(">")  ────> &gt;

DB値 ────────────────────> quotRep() ─────────────────> HTML安全値
                               │
                               v
                         HTML出力（value属性等）

JS文字列 ────────────────> quotRepJS() ────────────────> JS安全値
                               │
                               v
                         JavaScript出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| functions.asp | `asp/includes/functions.asp` | ソース | sanitize、quotRep、quotRepJS、removeCRB関数定義 |
| page.asp | `asp/includes/page.asp` | ソース | ページオブジェクト（sanitize使用） |
| listitem.asp | `asp/includes/listitem.asp` | ソース | リストアイテム（sanitize使用） |
| process.asp | `asp/process.asp` | ソース | メイン処理（sanitize使用） |

### 利用例

```asp
' フォーム入力値の表示
<input type="text" name="title" value="<%=sanitize(Request.Form("title"))%>" />

' データベース値の表示
<td><%=sanitize(rs("sTitle"))%></td>

' JavaScript文字列への出力
<script>
var message = '<%=quotRepJS(sMessage)%>';
</script>

' メタタグの出力
<meta name="description" content="<%=sanitize(page.sDescription)%>" />

' コンテンツからASPコードを除去
sContent = removeCRB(sContent)
```

### 注意事項

1. **&のエスケープ**: quotRepは&をエスケープしないため、&amp;が必要な場合は別途処理が必要
2. **シングルクォート**: HTML属性でシングルクォートを使う場合はquotRepでは不十分
3. **URL出力**: URLエンコードが必要な場合はServer.URLEncodeを併用
4. **リッチテキスト**: WYSIWYGエディタの出力など、HTMLタグを許可する場合は別のサニタイズ戦略が必要
