Skip to main content

6. Security Considerations (安全考虑)

大小限制问题

结构化字段定义的大多数类型的大小没有限制;因此,极大的字段可能成为攻击向量(例如,用于资源消耗攻击)。

缓解措施

大多数HTTP实现限制以下内容的大小以缓解此类攻击:

  • 单个字段的大小
  • 整个头部区段的大小
  • 整个尾部区段的大小

推荐做法

实现应该:
- 设置合理的字段大小限制
- 监控总头部大小
- 对异常大的字段值记录警报
- 考虑拒绝过大的请求/响应

字段注入攻击

具有注入新HTTP字段能力的方可以改变结构化字段的含义

问题场景

# 原始请求
Example-Dict: key1=value1

# 攻击者注入额外的字段行
Example-Dict: key1=value1
Example-Dict: key2=malicious ← 注入

# 根据HTTP规则,这些会被合并
# 结果: key1=value1, key2=malicious

风险

在某些情况下,这会导致解析失败,但无法在所有情况下可靠地失败

防御策略

  1. 严格的访问控制

    • 限制谁可以设置HTTP字段
    • 验证中间代理的行为
  2. 字段完整性验证

    • 使用签名或HMAC保护关键字段
    • 检测意外的字段修改
  3. 最小权限原则

    • 限制字段的语义影响范围
    • 不要让单个字段承载过多安全决策

解析严格性的安全意义

为什么严格解析是安全特性

场景: 恶意构造的字段值

宽容解析器:
Input: key="value\x00hidden"
可能解析为: key="value" (忽略空字节后的内容)
→ 隐藏的数据可能绕过安全检查

严格解析器:
Input: key="value\x00hidden"
结果: 解析失败,忽略整个字段
→ 没有歧义,安全边界清晰

安全优势

  1. 防止注入: 严格验证防止注入攻击
  2. 消除歧义: 所有实现行为一致
  3. 尽早失败: 在边界检查点发现问题
  4. 可预测性: 攻击者无法利用解析差异

类型混淆攻击

问题

// 字段定义: 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限制了嵌套深度
# 但实现仍需小心
Example-List: ((((((((value))))))))

防御: 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的处理

参数键在其范围内必须是唯一的。重复的键会导致解析失败。

实现建议

const params = new Map();
for (const [key, value] of parsedParams) {
if (params.has(key)) {
throw new Error('Duplicate parameter key');
}
params.set(key, value);
}

与其他安全机制的交互

1. Content Security Policy (CSP)

结构化字段可用于CSP相关的头部:

# 假设的结构化CSP指令
Content-Security-Policy-Structured:
script-src=(self "nonce-abc123"),
style-src=(self)

2. CORS

# 现有的CORS头部
Access-Control-Allow-Origin: https://example.com

# 未来可能的结构化版本
Access-Control-Allow-Origins: "https://example.com",
"https://trusted.com"

3. Cookie安全

虽然Cookie不使用结构化字段(历史原因),但新的类似机制可以受益于结构化字段的严格性。


安全清单

实现结构化字段时,确保:

  • 限制字段大小
  • 限制List/Dictionary成员数量
  • 限制字符串/Token长度
  • 限制Byte Sequence大小
  • 严格验证所有类型
  • 拒绝重复的键
  • 记录异常输入
  • 测试边界情况
  • 不尝试"修复"错误输入
  • 在失败时忽略整个字段

关键要点

  1. 大小限制: 实现必须限制字段大小以防止资源耗尽
  2. 注入风险: 字段注入可能改变语义,但无法完全防止
  3. 严格解析: 严格性是安全特性,不是缺陷
  4. 类型安全: 严格的类型检查防止混淆攻击
  5. 实现责任: 实现者需要添加合理的安全限制
  6. 防御深度: 结合多种安全机制,不要仅依赖字段验证