JSON injection 会在以下情况中出现:
1. 数据从一个不可信赖的数据源进入程序。
2. 将数据写入到 JSON 流。
应用程序通常使用 JSON 来存储数据或发送消息。用于存储数据时,JSON 通常会像缓存数据那样处理,而且可能会包含敏感信息。用于发送消息时,JSON 通常与 RESTful 服务一起使用,并且可以用于传输敏感信息,例如身份验证凭据。
如果应用程序利用未经验证的输入构造 JSON,则可以更改 JSON 文档和消息的语义。在相对理想的情况下,攻击者可能会插入无关的元素,导致应用程序在解析 JSON 文档或请求时抛出异常。在更为严重的情况下,例如涉及 JSON Injection,攻击者可能会插入无关的元素,从而允许对 JSON 文档或请求中对业务非常关键的值执行可预见操作。还有一些情况,JSON Injection 可以导致 Cross-Site Scripting 或 Dynamic Code Evaluation。
例 1:以下 Java 代码使用 Jackson 将非特权用户(这些用户具有“默认”角色,与之相反,特权用户具有“管理员”角色)的用户帐户身份验证信息从用户控制的输入变量 username 和 password 序列化为位于 ~/user_info.json 的 JSON 文件:
...
JsonFactory jfactory = new JsonFactory();
JsonGenerator jGenerator = jfactory.createJsonGenerator(new File("~/user_info.json"), JsonEncoding.UTF8);
jGenerator.writeStartObject();
jGenerator.writeFieldName("username");
jGenerator.writeRawValue("\"" + username + "\"");
jGenerator.writeFieldName("password");
jGenerator.writeRawValue("\"" + password + "\"");
jGenerator.writeFieldName("role");
jGenerator.writeRawValue("\"default\"");
jGenerator.writeEndObject();
jGenerator.close();
但是,由于 JSON 序列化使用 JsonGenerator.writeRawValue() 来执行,将不会对 username 和 password 中的不可信赖数据进行验证以转义与 JSON 相关的特殊字符。这样,用户就可以任意插入 JSON 密钥,可能会更改已序列化的 JSON 的结构。在本例中,在设置 username 的值的提示符下输入用户名时,如果非特权用户 mallory(密码为 Evil123!)将 ","role":"admin 附加到其用户名中,则最终保存到 ~/user_info.json 的 JSON 将为:
{
"username":"mallory",
"role":"admin",
"password":"Evil123!",
"role":"default"
}
如果随后将此序列化 JSON 文件反序列化为 HashMap 对象,其中 Jackson 的 JsonParser 如下所示:
JsonParser jParser = jfactory.createJsonParser(new File("~/user_info.json"));
while (jParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jParser.getCurrentName();
if ("username".equals(fieldname)) {
jParser.nextToken();
userInfo.put(fieldname, jParser.getText());
}
if ("password".equals(fieldname)) {
jParser.nextToken();
userInfo.put(fieldname, jParser.getText());
}
if ("role".equals(fieldname)) {
jParser.nextToken();
userInfo.put(fieldname, jParser.getText());
}
if (userInfo.size() == 3)
break;
}
jParser.close();HashMap 对象中 username、password 和 role 密钥的最终值将分别为 mallory、Evil123! 和 admin。在没有进一步验证反序列化 JSON 值是否有效的情况下,应用程序会错误地为用户分配 mallory“管理员”特权。