6. Security Considerations (セキュリティに関する考慮事項)
サイズ制限の問題
構造化フィールドで定義されているほとんどの型のサイズには制限がありません。したがって、非常に大きなフィールドは攻撃ベクトル(例:リソース消費攻撃)になる可能性があります。
緩和策
ほとんどのHTTP実装は、このような攻撃を緩和するために以下のサイズを制限しています:
- 個々のフィールドのサイズ
- ヘッダーセクション全体のサイズ
- トレーラーセクション全体のサイズ
推奨される実践
実装は以下を行うべきです (SHOULD):
- 合理的なフィールドサイズ制限を設定する
- 総ヘッダーサイズを監視する
- 異常に大きなフィールド値に対してアラートを記録する
- 過大なリクエスト/レスポンスの拒否を検討する
フィールドインジェクション攻撃
新しいHTTPフィールドを注入する能力を持つ者は、構造化フィールドの意味を変更できます。
問題のシナリオ
# 元のリクエスト
Example-Dict: key1=value1
# 攻撃者が追加のフィールド行を注入
Example-Dict: key1=value1
Example-Dict: key2=malicious ← 注入
# HTTPルールに従って、これらはマージされます
# 結果: key1=value1, key2=malicious
リスク
場合によってはこれが解析の失敗につながりますが、すべての場合で確実に失敗するわけではありません。
防御戦略
-
厳格なアクセス制御
- HTTPフィールドを設定できる者を制限する
- 中間プロキシの動作を検証する
-
フィールド整合性検証
- 署名またはHMACを使用して重要なフィールドを保護する
- 予期しないフィールド変更を検出する
-
最小権限の原則
- フィールドのセマンティック影響範囲を制限する
- 単一のフィールドに過度のセキュリティ決定を負わせない
解析の厳格性のセキュリティ上の意味
なぜ厳格な解析がセキュリティ機能なのか
シナリオ: 悪意を持って構築されたフィールド値
寛容なパーサー:
Input: key="value\x00hidden"
解析結果: key="value" (ヌルバイト後の内容を無視)
→ 隠されたデータがセキュリティチェックをバイパスする可能性
厳格なパーサー:
Input: key="value\x00hidden"
結果: 解析失敗、フィールド全体を無視
→ 曖昧さなし、セキュリティ境界が明確
セキュリティ上の利点
- インジェクション防止: 厳格な検証がインジェクション攻撃を防ぐ
- 曖昧さの排除: すべての実装が一貫して動作する
- 早期失敗: 境界チェックポイントで問題を発見
- 予測可能性: 攻撃者が解析の違いを悪用できない
型混同攻撃
問題
// フィールド定義: Example-FieldはIntegerでなければならない
Example-Field: "123" // String型
// 誤った実装:
value = parseInt(fieldValue); // 変換成功
// しかしこれは仕様違反!
正しい方法
// 厳格な型チェック
const field = parseItem(fieldValue);
if (field.type !== 'integer') {
// フィールド全体を無視
return null;
}
リソース消費攻撃の例
攻撃1: 極端に長いList
# 100,000個のメンバーを含むList
Example-List: 1, 2, 3, ..., 100000
影響: メモリ枯渇、CPU過負荷
防御:
const MAX_LIST_SIZE = 1024; // RFCの最小要件
if (list.length > MAX_LIST_SIZE) {
throw new Error('List too large');
}
攻撃2: 深いネスト
RFC 8941の設計は既にネストを制限しています(最大2層)。
攻撃3: 極端に長い文字列
Example-String: "AAAA...AAAA" (100MB)
防御:
const MAX_STRING_LENGTH = 8192; // 例示的な制限
if (string.length > MAX_STRING_LENGTH) {
throw new Error('String too long');
}
パラメータ汚染
問題
Example-Item: value; key=1; key=2; key=3
# 同じキーが複数回出現
RFC 8941の処理
パラメータキーはそのスコープ内で一意でなければなりません (MUST)。重複するキーは解析失敗を引き起こします。
実装の推奨
const params = new Map();
for (const [key, value] of parsedParams) {
if (params.has(key)) {
throw new Error('Duplicate parameter key');
}
params.set(key, value);
}
セキュリティチェックリスト
構造化フィールドを実装する際は、以下を確認してください:
- フィールドサイズを制限する
- List/Dictionaryメンバー数を制限する
- 文字列/Tokenの長さを制限する
- Byte Sequenceのサイズを制限する
- すべての型を厳格に検証する
- 重複するキーを拒否する
- 異常な入力を記録する
- 境界ケースをテストする
- 誤った入力を「修正」しようとしない
- 失敗時にフィールド全体を無視する
重要なポイント
- サイズ制限: 実装はリソース枯渇を防ぐためにフィールドサイズを制限しなければなりません (MUST)
- インジェクションリスク: フィールドインジェクションはセマンティクスを変更する可能性がありますが、完全には防げません
- 厳格な解析: 厳格性はセキュリティ機能であり、欠陥ではありません
- 型安全性: 厳格な型チェックが混同攻撃を防ぎます
- 実装の責任: 実装者は合理的なセキュリティ制限を追加する必要があります
- 多層防御: 複数のセキュリティメカニズムを組み合わせ、フィールド検証のみに依存しない