入力の検証や表現の問題は、メタキャラクター、代替エンコーディング、数値表現などによって引き起こされます。セキュリティの問題は、入力を信頼することに起因します。この問題に含まれるのは、「Buffer Overflow」、「Cross-Site Scripting」攻撃、「SQL Injection」などです。
username
および password
から C:\user_info.json
にある JSON ファイルに、権限を与えられていないユーザー (「default」ロールのユーザーです。これに対し権限が付与されたユーザーのロールは「admin」です) のユーザー アカウントの認証情報をシリアライズします。
...
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
writer.WriteStartObject();
writer.WritePropertyName("role");
writer.WriteRawValue("\"default\"");
writer.WritePropertyName("username");
writer.WriteRawValue("\"" + username + "\"");
writer.WritePropertyName("password");
writer.WriteRawValue("\"" + password + "\"");
writer.WriteEndObject();
}
File.WriteAllText(@"C:\user_info.json", sb.ToString());
JsonWriter.WriteRawValue()
を使用して実行されるため、username
および password
内の信頼できないデータに対して、JSON 関連の特殊文字をエスケープするための検証がされなくなります。これにより、ユーザーが、シリアライズされた JSON の構造を変更する可能性がある JSON キーを随意に挿入できるようになります。この例では、権限を与えられていないユーザー mallory
(パスワード Evil123!
) が username
変数の値を設定するプロンプトでユーザー名を入力するときに自身のユーザー名に ","role":"admin
を追加する場合、結果として C:\user_info.json
に保存される JSON は次のようになります。
{
"role":"default",
"username":"mallory",
"role":"admin",
"password":"Evil123!"
}
JsonConvert.DeserializeObject()
を使用して Dictionary
オブジェクトにデシリアライズされた場合はこのようになります。
String jsonString = File.ReadAllText(@"C:\user_info.json");
Dictionary<string, string> userInfo = JsonConvert.DeserializeObject<Dictionary<string, strin>>(jsonString);
Dictionary
オブジェクト内で username
、password
、および role
キーの結果として得られる値はそれぞれ mallory
、Evil123!
、および admin
になります。デシリアライズされた JSON 値が有効かについてこれ以上検証しないと、アプリケーションは誤ってユーザー mallory
に「admin」権限を割り当てます。username
および password
から ~/user_info.json
にある JSON ファイルに、権限を与えられていないユーザー (「default」ロールのユーザーです。これに対し権限が付与されたユーザーのロールは「admin」です) のユーザー アカウントの認証情報をシリアライズします。
...
func someHandler(w http.ResponseWriter, r *http.Request){
r.parseForm()
username := r.FormValue("username")
password := r.FormValue("password")
...
jsonString := `{
"username":"` + username + `",
"role":"default"
"password":"` + password + `",
}`
...
f, err := os.Create("~/user_info.json")
defer f.Close()
jsonEncoder := json.NewEncoder(f)
jsonEncoder.Encode(jsonString)
}
username
および password
内の信頼できないデータに対して、JSON 関連の特殊文字をエスケープするための検証がされなくなります。これにより、ユーザーが、シリアライズされた JSON の構造を変更する可能性がある JSON キーを随意に挿入できるようになります。この例では、権限を与えられていないユーザー mallory
(パスワード Evil123!
) がユーザー名を入力するときに ","role":"admin
を追加する場合、結果として ~/user_info.json
に保存される JSON は次のようになります。
{
"username":"mallory",
"role":"default",
"password":"Evil123!",
"role":"admin"
}
mallory
に「admin」権限を割り当てます。username
および password
から ~/user_info.json
にある JSON ファイルに、権限を与えられていないユーザー (「default」ロールのユーザーです。これに対し権限が付与されたユーザーのロールは「admin」です) のユーザー アカウントの認証情報をシリアライズします。
...
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();
JsonGenerator.writeRawValue()
を使用して実行されるため、username
および password
内の信頼できないデータに対して、JSON 関連の特殊文字をエスケープするための検証がされなくなります。これにより、ユーザーが、シリアライズされた JSON の構造を変更する可能性がある JSON キーを随意に挿入できるようになります。この例では、権限を与えられていないユーザー mallory
(パスワード Evil123!
) が username
変数の値を設定するプロンプトでユーザー名を入力するときに自身のユーザー名に ","role":"admin
を追加する場合、結果として ~/user_info.json
に保存される JSON は次のようになります。
{
"username":"mallory",
"role":"admin",
"password":"Evil123!",
"role":"default"
}
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
オブジェクト内で username
、password
、および role
キーの結果として得られる値はそれぞれ mallory
、Evil123!
、および admin
になります。デシリアライズされた JSON 値が有効かについてこれ以上検証しないと、アプリケーションは誤ってユーザー mallory
に「admin」権限を割り当てます。
var str = document.URL;
var url_check = str.indexOf('name=');
var name = null;
if (url_check > -1) {
name = decodeURIComponent(str.substring((url_check+5), str.length));
}
$(document).ready(function(){
if (name !== null){
var obj = jQuery.parseJSON('{"role": "user", "name" : "' + name + '"}');
...
}
...
});
name
で信頼されていないデータは検証されずに JSON 関連の特殊文字がエスケープされません。これにより、ユーザーが、シリアライズされた JSON の構造を変更する可能性がある JSON キーを随意に挿入できるようになります。この例では、権限のないユーザー mallory
が URL の名前パラメーターに ","role":"admin
を追加すると、JSON は次のようになります。
{
"role":"user",
"username":"mallory",
"role":"admin"
}
jQuery.parseJSON()
によってパースされてプレーン オブジェクトに設定されます。つまり、obj.role
は "user" の代わりに "admin" を返すようになります。_usernameField
および _passwordField
から JSON に、権限を与えられていないユーザー (「default」ロールのユーザーです。これに対し権限が付与されたユーザーのロールは「admin」です) のユーザー アカウントの認証情報をシリアライズします。
...
NSString * const jsonString = [NSString stringWithFormat: @"{\"username\":\"%@\",\"password\":\"%@\",\"role\":\"default\"}" _usernameField.text, _passwordField.text];
NSString.stringWithFormat:
を使用して実行されるため、_usernameField
および _passwordField
内の信頼できないデータに対して、JSON 関連の特殊文字をエスケープするための検証がされなくなります。これにより、ユーザーが、シリアライズされた JSON の構造を変更する可能性がある JSON キーを随意に挿入できるようになります。この例では、権限を与えられていないユーザー mallory
(パスワード Evil123!
) がユーザー名を _usernameField
フィールドに入力するときに自身のユーザー名に ","role":"admin
を追加する場合、結果として JSON は次のようになります。
{
"username":"mallory",
"role":"admin",
"password":"Evil123!",
"role":"default"
}
NSJSONSerialization.JSONObjectWithData:
を使用して NSDictionary
オブジェクトにデシリアライズされた場合はこのようになります。
NSError *error;
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
NSDictionary
オブジェクト内で username
、password
、および role
キーの結果として得られる値はそれぞれ mallory
、Evil123!
、および admin
になります。デシリアライズされた JSON 値が有効かについてこれ以上検証しないと、アプリケーションは誤ってユーザー mallory
に「admin」権限を割り当てます。
import json
import requests
from urllib.parse import urlparse
from urllib.parse import parse_qs
url = 'https://www.example.com/some_path?name=some_value'
parsed_url = urlparse(url)
untrusted_values = parse_qs(parsed_url.query)['name'][0]
with open('data.json', 'r') as json_File:
data = json.load(json_File)
data['name']= untrusted_values
with open('data.json', 'w') as json_File:
json.dump(data, json_File)
...
name
内の信頼できないデータに対して、JSON 関連の特殊文字をエスケープするための検証がされなくなります。これにより、ユーザーが JSON キーを随意に挿入できるようになり、シリアライズされた JSON の構造を変更する可能性があります。この例では、権限を与えられていないユーザー mallory
が URL の名前パラメータに ","role":"admin
を追加する場合、JSON は次のようになります。
{
"role":"user",
"username":"mallory",
"role":"admin"
}
usernameField
および passwordField
から JSON に、権限を与えられていないユーザー (「default」ロールのユーザーです。これに対し権限が付与されたユーザーのロールは「admin」です) のユーザー アカウントの認証情報をシリアライズします。
...
let jsonString : String = "{\"username\":\"\(usernameField.text)\",\"password\":\"\(passwordField.text)\",\"role\":\"default\"}"
usernameField
および passwordField
内の信頼できないデータに対して、JSON 関連の特殊文字をエスケープするための検証がされなくなります。これにより、ユーザーが、シリアライズされた JSON の構造を変更する可能性がある JSON キーを随意に挿入できるようになります。この例では、権限を与えられていないユーザー mallory
(パスワード Evil123!
) がユーザー名を usernameField
フィールドに入力するときに自身のユーザー名に ","role":"admin
を追加する場合、結果として JSON は次のようになります。
{
"username":"mallory",
"role":"admin",
"password":"Evil123!",
"role":"default"
}
NSJSONSerialization.JSONObjectWithData:
を使用して NSDictionary
オブジェクトにデシリアライズされた場合はこのようになります。
var error: NSError?
var jsonData : NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonString.dataUsingEncoding(NSUTF8StringEncoding), options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
NSDictionary
オブジェクト内で username
、password
、および role
キーの結果として得られる値はそれぞれ mallory
、Evil123!
、および admin
になります。デシリアライズされた JSON 値が有効かについてこれ以上検証しないと、アプリケーションは誤ってユーザー mallory
に「admin」権限を割り当てます。