2.12 IDS11-J在验证前去掉非字符码点
在早于Unicode 5.2的版本中,条款C7允许删除非字符码点。比如,在Unicode 5.1版本的C7条款中:
条款C7 当一个进程声称不会修改一个合法编码字符序列的意思时,它不应该改变该字符编码序列,除了有可能使用标准化字符编码来取代字符序列,或是删除非字符编码之外。
根据Unicode技术报告第36号的3.5节“删除非字符编码”,在考虑Unicode的安全的时候[Davis 2008b]:
不管一个字符是否被直接删除(不是替代),例如在C7的旧版本中提及的,将会导致安全问题。这个问题是这样的:一个网关可能会对所有的敏感字符串进行处理,比如“delete”。如果传递过来的是“delXlete”。这里“X”是非字符,网关会让它通过:序列“deXlete”可能通过并无害。然而,假设在通过网关之后,一个内部进程直接删除了X。这时,就形成了一个敏感的字符序列,并且会造成安全威胁。
修改任何一个字符串,包括对非字符数据的移除或者替代,必须在对该字符串进行验证之前进行。
2.12.1 不符合规则的代码示例
这个代码示例只接受合法的ASCII字符,并且它会删除所有的非ASCII码字符。同时,它也会检查是否存在
// "\uFEFF" is a non-character code point
String s = "<scr" + "\uFEFF" + "ipt>";?
s = Normalizer.normalize(s, Form.NFKC);
// Input validation
Pattern pattern = Pattern.compile("<script>");
Matcher matcher = pattern.matcher(s);
if (matcher.find()) {
??System.out.println("Found black listed tag");
} else {
??// ...?
}
// Deletes all non-valid characters?
s = s.replaceAll("^\\p{ASCII}]", "");
// s now contains "<script>"
2.12.2 符合规则的方案
这个方案使用Unicode字符序列uFFFD来替代那些未知的或者不可表示的字符。同时,这样的替代是在其他净化之前完成的,比如对
String s = "<scr" + "\uFEFF" + "ipt>";
s = Normalizer.normalize(s, Form.NFKC);
// Replaces all non-valid characters with unicode U+FFFD
s = s.replaceAll("^\\p{ASCII}]", "\uFFFD");?
Pattern pattern = Pattern.compile("<script>");
Matcher matcher = pattern.matcher(s);
if (matcher.find()) {
??System.out.println("Found blacklisted tag");
} else {
??// ...?
}
根据Unicode技术报告第36号, 考虑Unicode编码的安全问题 [Davis 2008b],“U+FFFD通常是没有问题的,因为它就是设计成这样使用的。也就是说,不管是在程序开发语言,还是在结构数据中,因为不会有任何语义上的含义,通常会在解析时出现错误。当输出字符集不是Unicode编码时,这个字符可能是不存在。”
2.12.3 风险评估
将非字符编码删除会允许恶意输入绕过验证检查。
2.12.4 相关规范
2.12.5 参考书目
时间: 2024-10-01 17:51:15