Web安全之JSON注入攻击原理与防御详解
字数 2181 2025-12-09 03:09:04

Web安全之JSON注入攻击原理与防御详解

1. 什么是JSON注入攻击?

JSON注入是一种针对Web应用程序的注入型攻击,攻击者通过向应用程序提交精心构造的恶意JSON数据,意图破坏应用程序的逻辑、窃取数据或执行未授权操作。与SQL注入、XSS等传统注入不同,JSON注入主要发生在:

  • 服务器端:应用程序解析JSON数据时,未经验证或净化就将其用于动态代码执行(如eval)、数据库查询、系统命令调用或反序列化操作。
  • 客户端:JavaScript代码使用eval()JSON.parse()后未经验证直接操作DOM或执行函数。

核心风险:JSON作为一种轻量级数据交换格式,本身不是可执行代码,但当它与动态代码执行、反序列化或字符串拼接等不安全操作结合时,就会产生注入漏洞。


2. 攻击原理与常见场景

场景一:JSON动态解析为代码执行(服务器端)

某些编程语言或框架提供动态执行JSON内容的功能,例如:

// 危险示例:Node.js中使用eval解析JSON字符串(实际应使用JSON.parse)
const userInput = '{"name": "Alice", "age": "20; console.log(\'Hacked\')"}';
eval('var obj = ' + userInput); // 执行了额外的代码console.log('Hacked')

攻击方式

  • 攻击者提交JSON:{"name": "test", "age": "20; process.exit(1)"},导致服务崩溃。
  • 利用字符串拼接构造非法JSON,如插入额外键值对或破坏JSON结构。

场景二:JSONP(JSON with Padding)回调函数注入

JSONP用于跨域获取数据,通过<script>标签加载外部JSON数据,并指定回调函数名:

<script src="http://api.example.com/data?callback=handleResponse"></script>

攻击方式

  • 攻击者修改callback参数为恶意代码:?callback=alert('XSS');//
  • 服务器返回:alert('XSS');//({"data": "value"});,导致XSS攻击。

场景三:不安全的反序列化

许多语言支持将JSON反序列化为对象(如Python的pickle、Java的Jackson/Gson、PHP的json_decode+对象注入):

# Python示例:使用json.loads但后续将对象用于危险操作
import json
data = json.loads(user_input)  # 如果user_input包含恶意类或属性,可能触发副作用

攻击方式

  • 利用反序列化时的特性(如PHP的__wakeup、Java的readObject),在反序列化过程中执行任意代码。

场景四:NoSQL注入(通过JSON操作)

NoSQL数据库(如MongoDB)使用JSON格式查询,如果未经验证拼接查询:

// 危险示例:拼接用户输入到查询
const query = { username: req.body.username, password: req.body.password };
db.users.find(query);

攻击方式

  • 提交JSON:{"username": "admin", "password": {"$ne": null}},绕过密码验证。

3. 攻击步骤详解(以NoSQL注入为例)

假设登录接口接收JSON:{"username": "user", "password": "pass"},后端使用MongoDB查询:

app.post('/login', (req, res) => {
    const user = db.users.findOne({ username: req.body.username, password: req.body.password });
});

攻击过程

  1. 探测:发送正常JSON,确认接口响应。
  2. 注入尝试:将password改为操作符,提交:
    {"username": "admin", "password": {"$ne": ""}}
    
  3. 结果:查询变为db.users.findOne({username: "admin", password: {$ne: ""}}),只要password非空即返回用户数据,绕过登录。

4. 防御策略

策略一:输入验证与净化

  • 严格模式:使用JSON.parse()替代eval(),但需确保JSON格式合法。
  • 白名单验证:对JSON键值进行类型、长度、格式检查(如用户名只允许字母数字)。
  • 库函数转义:使用JSON.stringify()生成JSON字符串,避免手动拼接。

策略二:安全反序列化

  • 禁用危险特性:如PHP中json_decode()避免与__wakeup结合;Java中使用Jackson的@JsonCreator而非默认构造器。
  • 使用安全库:如Python的simplejson、Java的Gson(默认不支持任意类反序列化)。

策略三:JSONP安全

  • 验证回调函数名:只允许字母数字和下划线,拒绝特殊字符。
  • 设置Content-Type:响应头添加Content-Type: application/javascript; charset=utf-8,避免浏览器误解析。
  • 使用CORS替代JSONP:现代应用优先使用CORS实现跨域。

策略四:NoSQL查询防御

  • 参数化查询:使用ORM或驱动提供的安全方法(如Mongoose的findOne直接传对象,但避免用户控制操作符)。
  • 类型转换:将用户输入强制转换为字符串或指定类型。
  • 操作符过滤:禁止查询中出现$where$ne等危险操作符。

策略五:输出编码与安全头

  • 设置HTTP头Content-Type: application/json避免浏览器执行响应内容。
  • XSS防护:即使JSON注入成功,也要对输出到HTML的内容进行编码。

5. 最佳实践示例

// 安全示例:使用JSON.parse并验证数据
function safeParse(jsonString) {
    try {
        const data = JSON.parse(jsonString);
        // 验证必需字段和类型
        if (typeof data.username !== 'string' || data.username.length > 50) {
            throw new Error('Invalid username');
        }
        return data;
    } catch (e) {
        return null;
    }
}

// MongoDB查询防御:使用显式查询构造
app.post('/login', (req, res) => {
    const username = String(req.body.username); // 强制类型转换
    const password = String(req.body.password);
    db.users.findOne({ username: username, password: password }); // 避免操作符注入
});

6. 总结

JSON注入的本质是将不受信任的数据作为代码或查询逻辑的一部分。防御关键在于:

  • 不信任任何输入:对JSON数据做严格验证和类型检查。
  • 避免动态执行:禁用eval()Function()等危险函数。
  • 使用安全API:优先使用标准库的JSON解析和序列化方法。
  • 最小化攻击面:关闭不必要的反序列化功能或操作符支持。
    通过结合输入验证、输出编码和安全配置,可有效防护JSON注入攻击。
Web安全之JSON注入攻击原理与防御详解 1. 什么是JSON注入攻击? JSON注入是一种针对Web应用程序的注入型攻击,攻击者通过向应用程序提交精心构造的恶意JSON数据,意图破坏应用程序的逻辑、窃取数据或执行未授权操作。与SQL注入、XSS等传统注入不同,JSON注入主要发生在: 服务器端 :应用程序解析JSON数据时,未经验证或净化就将其用于动态代码执行(如 eval )、数据库查询、系统命令调用或反序列化操作。 客户端 :JavaScript代码使用 eval() 或 JSON.parse() 后未经验证直接操作DOM或执行函数。 核心风险 :JSON作为一种轻量级数据交换格式,本身不是可执行代码,但当它与动态代码执行、反序列化或字符串拼接等不安全操作结合时,就会产生注入漏洞。 2. 攻击原理与常见场景 场景一:JSON动态解析为代码执行(服务器端) 某些编程语言或框架提供动态执行JSON内容的功能,例如: 攻击方式 : 攻击者提交JSON: {"name": "test", "age": "20; process.exit(1)"} ,导致服务崩溃。 利用字符串拼接构造非法JSON,如插入额外键值对或破坏JSON结构。 场景二:JSONP(JSON with Padding)回调函数注入 JSONP用于跨域获取数据,通过 <script> 标签加载外部JSON数据,并指定回调函数名: 攻击方式 : 攻击者修改 callback 参数为恶意代码: ?callback=alert('XSS');// 。 服务器返回: alert('XSS');//({"data": "value"}); ,导致XSS攻击。 场景三:不安全的反序列化 许多语言支持将JSON反序列化为对象(如Python的 pickle 、Java的Jackson/Gson、PHP的 json_decode +对象注入): 攻击方式 : 利用反序列化时的特性(如PHP的 __wakeup 、Java的 readObject ),在反序列化过程中执行任意代码。 场景四:NoSQL注入(通过JSON操作) NoSQL数据库(如MongoDB)使用JSON格式查询,如果未经验证拼接查询: 攻击方式 : 提交JSON: {"username": "admin", "password": {"$ne": null}} ,绕过密码验证。 3. 攻击步骤详解(以NoSQL注入为例) 假设登录接口接收JSON: {"username": "user", "password": "pass"} ,后端使用MongoDB查询: 攻击过程 : 探测 :发送正常JSON,确认接口响应。 注入尝试 :将 password 改为操作符,提交: 结果 :查询变为 db.users.findOne({username: "admin", password: {$ne: ""}}) ,只要 password 非空即返回用户数据,绕过登录。 4. 防御策略 策略一:输入验证与净化 严格模式 :使用 JSON.parse() 替代 eval() ,但需确保JSON格式合法。 白名单验证 :对JSON键值进行类型、长度、格式检查(如用户名只允许字母数字)。 库函数转义 :使用 JSON.stringify() 生成JSON字符串,避免手动拼接。 策略二:安全反序列化 禁用危险特性 :如PHP中 json_decode() 避免与 __wakeup 结合;Java中使用Jackson的 @JsonCreator 而非默认构造器。 使用安全库 :如Python的 simplejson 、Java的 Gson (默认不支持任意类反序列化)。 策略三:JSONP安全 验证回调函数名 :只允许字母数字和下划线,拒绝特殊字符。 设置Content-Type :响应头添加 Content-Type: application/javascript; charset=utf-8 ,避免浏览器误解析。 使用CORS替代JSONP :现代应用优先使用CORS实现跨域。 策略四:NoSQL查询防御 参数化查询 :使用ORM或驱动提供的安全方法(如Mongoose的 findOne 直接传对象,但避免用户控制操作符)。 类型转换 :将用户输入强制转换为字符串或指定类型。 操作符过滤 :禁止查询中出现 $where 、 $ne 等危险操作符。 策略五:输出编码与安全头 设置HTTP头 : Content-Type: application/json 避免浏览器执行响应内容。 XSS防护 :即使JSON注入成功,也要对输出到HTML的内容进行编码。 5. 最佳实践示例 6. 总结 JSON注入的本质是 将不受信任的数据作为代码或查询逻辑的一部分 。防御关键在于: 不信任任何输入 :对JSON数据做严格验证和类型检查。 避免动态执行 :禁用 eval() 、 Function() 等危险函数。 使用安全API :优先使用标准库的JSON解析和序列化方法。 最小化攻击面 :关闭不必要的反序列化功能或操作符支持。 通过结合输入验证、输出编码和安全配置,可有效防护JSON注入攻击。