JSON Injection 解决:
加 JsonSanitizer.sanitize() 进行校验(这个校验貌似可以解决很多Json相关的Fortify Issue);
com.mikesamuel
json-sanitizer
1.0
-----------------------------------------------------------------------------Issue 描述--------------------------------------------------------------------------------------------------
摘要
该方法将未经验证的输入写入JSON。此调用可能允许攻击者将任意元素或属性注入JSON实体。
说明
JSON注入发生在以下情况下:
1.数据从不受信任的源进入程序。
2.数据被写入JSON流。应用程序通常使用JSON来存储数据或发送消息。当用于存储数据时,JSON通常被视为缓存的数据,
并且可能包含敏感信息。当用于发送消息时,JSON通常与RESTful服务结合使用,并且可以用于传输敏感信息,例如身份验
证凭据。如果应用程序从未经验证的输入构造JSON,则可以更改JSON文档和消息的语义。在相对温和的情况下,攻击者可能
够插入无关的元素,这些元素导致应用程序在解析JSON文档或请求时引发异常。在更严重的情况下,例如涉及JSON注入的情
况,攻击者可能能够插入无关的元素,以允许对JSON文档或请求中的业务关键值进行可预测的操纵。在某些情况下,JSON注入
可能导致跨站点脚本编写或动态代码评估。
示例1:
以下Java代码使用Jackson来从用户控制的输入变量username和$中序列化非特权用户(具有“默认”角色的用户
,而不是具有“ admin”角色的特权用户)的用户帐户身份验证信息。 JSON文件的密码位于 ~/user_info.json:
...
JsonFactory jfactory= newJsonFactory();
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()执行的,因此不会验证用户名和密码中不受信任的数
据来转义与JSON相关的特殊字符。这允许用户任意插入JSON密钥,可能会更改序列化JSON的结构。在此示例中,如果非特权用户
使用密码Evil123!在设置用户名变量值的提示符下输入用户名时,在用户名后附加“,” role“:” admin,保存到
〜/ user_info.json的结果JSON将为:
{"username":"mallory","role":"admin","password":"Evil123!","role":"default"}
如果此序列化的JSON文件随后使用Jackson的JsonParser反序列化为HashMap对象,则:
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对象中的用户名,密码和角色密钥的结果值分别为Mallory,Evil123!和admin。如果不进一步验证反序列化的JSON值是否有效,
该应用程序将错误地分配用户Mallory的“ admin”特权。
建议:
将用户提供的数据写入JSON时,应遵循一些准则:
1.不要创建其名称来自用户输入的JSON属性。
2.确保使用安全的序列化功能执行对JSON的所有序列化,该函数在单引号或双引号内定界不受信任的数据,并转义任何特殊字符。
示例2:
以下Java代码实现了与示例1中相同的功能,但是使用JsonGenerator.writeString()而不是JsonGenerator.writeRawValue()
来序列化数据,因此确保正确分隔和转义了所有不受信任的数据:
...
JsonFactory jfactory= newJsonFactory();
JsonGenerator jGenerator= jfactory.createJsonGenerator(new File("~/ user_info.json"), JsonEncoding.UTF8);
jGenerator.writeStartObject();
jGenerator.writeFieldName("username");
jGenerator.writeString(username);
jGenerator.writeFieldName("password");
jGenerator.writeString(password);
jGenerator.writeFieldName("role");
jGenerator.writeString("default");
jGenerator.writeEndObject();
jGenerator.close();