JSON Injection 解決:
加 JsonSanitizer.sanitize() 進行校驗(這個校驗貌似可以解決很多Json相關的Fortify Issue);
<dependency> <groupId>com.mikesamuel</groupId> <artifactId>json-sanitizer</artifactId> <version>1.0</version> </dependency>
-----------------------------------------------------------------------------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 = 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()執行的,因此不會驗證用戶名和密碼中不受信任的數
據來轉義與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 = new JsonFactory(); 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();
