似乎有很多方法可以创建恶意输入,以至于将好的输入列入白名单通常感觉是更安全、更简单的选择。
例如,可以相当容易地制作一个包含好东西的白名单正则表达式 [a-zA-Z0-9],但在考虑国际内容时,这似乎很快就崩溃了。澄清一下,上面的简单示例正则表达式将保留有效的英文字母单词,但会去除例如带有变音符号或中文字符的有效西班牙字母。
这种类型的国际输入验证是否有最佳实践?
似乎有很多方法可以创建恶意输入,以至于将好的输入列入白名单通常感觉是更安全、更简单的选择。
例如,可以相当容易地制作一个包含好东西的白名单正则表达式 [a-zA-Z0-9],但在考虑国际内容时,这似乎很快就崩溃了。澄清一下,上面的简单示例正则表达式将保留有效的英文字母单词,但会去除例如带有变音符号或中文字符的有效西班牙字母。
这种类型的国际输入验证是否有最佳实践?
这就是字符类 [[:alnum:]] 存在的原因;它包括在当前活动区域设置中被视为有效字母数字的字符。当然,当埃及的某人试图通过表单提供输入时,这在美国的 Web 服务器上效果不佳 - 而且它不适用于标点符号。但它也不包括空格,这可能完全不相关。
---编辑---建立在马克的回答下面并使用http://www.regular-expressions.info/unicode.html作为参考,人们也可以[\p{L}\p{N}]
在最常见的正则表达式实现中使用代替 alnum 字符类来识别使用的正则表达式引擎已知的所有语言环境中的“所有”unicode 字母/数字。选择基本上归结为进行比较的应用程序是否知道输入来自哪个语言环境。当然,输入是字母和数字,还是其他东西(例如,专有名称有时包含标点符号)。:) - -编辑 - -
为了更直接地回答这个问题 - 是的,白名单总是更可取的。不过,这并不总是实用的。只有熟悉特定应用程序的人才能决定什么是实际实用的。
您可以使用简单的正则表达式验证来检测适当的字符集。但是,您也可能成为安全剧院的受害者:输入卫生不是解决办法。
如果您尝试验证特定语言环境,并且不想接受任何其他语言环境,则可以使用 Regex 选择特定语言环境。这是一个例子:
\p{InHan}
对于汉字。\p{InArabic}
阿拉伯语\p{InThai}
泰语但是,我在这里支持 O'Rooney:您应该接受所有内容(只要它经过验证:长度、null、格式、白名单),并使用Prepared Statements
with output sanitation
.
如果您坚持使用基于 unicode-range 的白名单,请记住您仍然应该 allow [a-zA-Z0-9]
,即使您只接受其他语言环境。在中国互联网上,人们经常使用英文字母打字。例如,他们可能试图通过缩写字符(只是维基百科上的文字,但仍然是NSFW)来逃避审查。许多人还使用拼音和罗马数字。
您也可以使用Unicode 范围,但是当您使用组合的表意文字/语言集(例如CJK
(中文、日文和韩文;我相信\p{IsHan}
是CJK
))时,您将遇到许多验证问题。
如果您想按语言排除,当您期望日语输入时,您会遇到这个概念的问题,而是获得中文输入,反之亦然。同样的概念也适用于韩国人对抗中国人或日本人。您将需要找到适当的 unicode 范围,但请注意,某些语言偶尔会重叠:中文(汉字)和日语(汉字)共享一些字符。
因为您担心接受的输入,所以听起来您正在寻找输入卫生。这是错误的做法。您不应该“清理”进入数据库的输入。白名单很好(例如,可接受的值)。
清理和验证输入是两件不同的事情。有什么不同?
stripApostrophesFromString(input);
if (input != null && input.Length == acceptableNumber && regexFormatIsValid(input) && isWithinAcceptableRanges(input)) { } else { }
对于字符集验证,列出的正则表达式的变体就足够了,但不会验证长度、格式等。如果您担心 SQL 注入(而且您应该担心),您应该使用prepared statements
with output sanitation
。
输出清理本质上是将诸如脚本标签之类的坏字符转换为等效的 HTML 实体。例如,<
变成<
,>
变成>
。
我们的回答是,对于一个真正的国际应用程序,对于一般输入(例如人名),您应该接受所有内容并在显示时对其进行编码。诚然,(在某种程度上)将问题传递给编写编码算法的人。
但是,如果您有一个特定的输入,例如车牌号或企业识别码,那么您应该根据这些规则对其进行验证,无论是国际申请。同样,进一步的警告是,这些规则可能仍然难以定义,例如车牌符号会因国家/地区而异。
(编辑)为什么我更喜欢编码而不是验证:
在验证时,这些数据可能会出现在任何地方:CSV 文本文件、SQL 查询、网页、配置设置。你不知道,也不可能知道有风险的角色是什么。
在编码时,根据定义,您知道数据的去向,因此您可以明确地对有风险的字符进行编码。