本主题提供有关与国际支持功能相关的安全注意事项的信息。 你可以将其用作起点,然后查看有关技术特定安全注意事项感兴趣的国际技术的文档。
本主题包含以下部分。
- 字符转换函数的安全注意事项
- 比较函数 安全注意事项
- 文件名中字符集的安全注意事项
- 国际化域名的安全注意事项
- ANSI 函数 安全注意事项
- Unicode 规范化 安全注意事项
字符转换函数的安全注意事项
MultiByteToWideChar 和 WideCharToMultiByte 是 Unicode 和字符集函数,通常用于在 ANSI 和 Unicode 之间转换字符。 这些函数有可能导致安全风险,因为它们以不同的方式计算输入和输出缓冲区的元素。 例如,MultiByteToWideChar 采用以字节为单位的输入缓冲区,并将转换后的字符放入 Unicode 字符大小的缓冲区中。 当应用程序使用此函数时,它必须正确调整缓冲区大小以避免缓冲区溢出。
WideCharToMultiByte 默认为代码页的“最适合”映射,例如 1252。 但是,这种类型的映射允许同一字符串的多个表示形式,这可能会使应用程序容易受到攻击。 例如,带二分号的拉丁文大写字母 A (“Ä”) 可能映射到拉丁文大写字母 A (“A”):亚洲语言的 Unicode 字符可能映射到斜杠(“/)。 从安全角度来看,首选使用WC_NO_BEST_FIT_CHARS标志。
某些代码页(例如,5022x(iso-2022-x)代码页本质上不安全,因为它们允许同一字符串的多个表示形式。 正确编写的代码以 Unicode 形式执行安全检查,但这些类型的代码页会扩展应用程序的攻击易感性,并应尽可能避免。
比较函数的安全注意事项
字符串比较可能会带来安全问题。 由于所有比较函数稍有不同,因此一个函数可能会将两个字符串报告为相等,而另一个函数可能认为它们不同。 以下是应用程序可用于比较字符串的几个函数:
- lstrcmpi。 根据区域设置的规则比较两个字符串,而不区分大小写。 该函数通过相互检查第一个字符、彼此对第二个字符等来比较字符串,直到找到不相等或到达字符串的末尾。
- lstrcmp。 使用与 lstrcmpi类似的技术比较字符串。 唯一的区别是,lstrcmp 执行区分大小写的字符串比较。
- CompareString,CompareStringEx(Windows Vista 及更高版本)。 对应用程序提供的区域设置执行字符串比较。 CompareStringEx 类似于 CompareString,但它通过 区域设置名称 来标识区域设置,而不是 区域设置标识符。 这些函数类似于 lstrcmpi 和 lstrcmp,只是它们对特定区域设置而不是用户选择的区域设置进行作。
- CompareStringOrdinal (Windows Vista 及更高版本)。 比较两个 Unicode 字符串以测试二进制等效性。 除了不区分大小写的选项外,此函数将忽略所有非二进制等效性,并测试所有代码点是否相等,包括语言 排序 方案中未给出任何权重的代码点。 请注意,本主题中提到的其他比较函数不会测试所有代码点是否相等。
- FindNLSString,FindNLSStringEx(Windows Vista 及更高版本)。 在另一个 Unicode 字符串中找到 Unicode 字符串。 FindNLSStringEx 类似于 FindNLSString,只不过它通过区域设置名称而不是区域设置标识符来标识区域设置。
- FindStringOrdinal (Windows 7 及更高版本)。 在另一个 Unicode 字符串中找到一个 Unicode 字符串。 应用程序应使用此函数,而不是 FindNLSString 进行所有非语言比较。
与 lstrcmpi 和 lstrcmp一样,CompareString 按字符计算字符串。 但是,多种语言具有多字符元素,例如,传统西班牙语中的双字符元素“CH”。 由于 CompareString 使用应用程序提供的区域设置来标识多字符元素,lstrcmpi,lstrcmp 使用线程区域设置,因此相同的字符串可能不会相等。
CompareString 忽略未定义的字符,因此,对于许多截然不同的字符串对,返回零(表示相等字符串)。 字符串可能包含不映射到任何字符的值,也可能包含应用程序域外的语义字符,例如 URL 中的控制字符。 使用此函数的应用程序应提供错误处理程序和测试字符串,以确保它们在使用前有效。
注意
对于 Windows Vista 及更高版本,CompareStringEx 类似于 CompareString。 这些函数的安全问题完全相同。
类似的安全问题适用于进行隐式比较的函数,例如 FindNLSString。 根据设置的标志,调用 FindNLSString 搜索另一个字符串的结果可能会大相径庭。
注意
对于 Windows Vista 及更高版本,FindNLSStringEx 类似于 FindNLSString。 这些函数的安全问题完全相同。
文件名中字符集的安全注意事项
日语系统上使用的 Windows 代码页和 OEM 字符集包含日元符号 (¥) 而不是反斜杠 (\)。 因此,日元字符是 NTFS 和 FAT 文件系统的禁止字符。 将 Unicode 映射到日语语言代码页时,转换函数会将反斜杠(U+005C)和普通 Unicode 日元符号(U+00A5)映射到同一个字符。 出于安全原因,应用程序通常不允许 Unicode 字符串中的字符 U+00A5,该字符串可能转换为 FAT 文件名。
国际化域名的安全注意事项
国际化域名(IDN)由网络工作组 RFC 3490 指定:在应用程序(IDNA)中国际化域名。 该标准引入了许多安全问题。
表示不同脚本中某些字符的字形可能类似甚至相同。 例如,在许多字体中,西里尔文小写 A (“a”) 与拉丁文小写 A(“a”)不区分。 无法直观地判断“example.com”和“example.com”是两个不同的域名,一个域名是拉丁文小写 A,另一个是西里尔文小写 A。肆无忌惮的主机站点可以使用这种视觉歧义来假装成为欺骗攻击中的另一个站点。
IDNA 允许的扩展字符集在特定的脚本中也具有欺骗潜力。 例如, 连字符减号(“-”U+002D)、连字符(“-”U+2010)中存在强相似之处,即非中断连字符(“-” U+2)011)、数字短划线(“\u2012”U+2012)、短划线(“–”U+2013)和减号(“”U+2212)。
某些兼容性组合也出现了类似的问题。 例如,单个 Unicode 字符 NUMBER 20 FULL STOP (“20.”, U+249B) 转换为“20”。(U+0032 U+0030 U+002E)在 NamePrep 步骤中,在转换为 Punycode 之前。 换句话说,此组合插入句点(完全停止)。 这种合成具有欺骗潜力。
在 IDN 中混合不同脚本并不一定表示欺骗或欺骗意图。 技术报告 #36:Unicode 安全注意事项 提供了几个包含脚本组合的合理 IDN 的示例,例如XML-Документы.com(“Документы”)是俄语的“文档”。
欺骗攻击不限于 IDN。 例如,“rnicrosoft.com”看起来非常类似于“microsoft.com”,但它是 ASCII 名称。 此外,可以通过名称损坏来制造欺骗攻击。 在知名品牌名称后添加额外的标签,或在标记为安全的 URL 路径中包含品牌名称,可能会混淆新手用户,而不考虑使用 IDN。 对于某些区域设置,IDN 是必需的,并且这些名称的 Punycode 形式是不能接受的,因为它使名称看起来很乱。
有关此处提到的安全问题的详细信息,以及大量与 IDNA 相关的其他问题,请参阅 技术报告 #36:Unicode 安全注意事项。 除了详细讨论与 IDNA 相关的安全问题,此报告还提供了在应用程序中处理可疑 IDN 的建议。
ANSI 函数的安全注意事项
注意
如果可能,建议在全球化应用程序中使用 Unicode,尤其是新应用程序。 仅当没有使用 Unicode 的替代原因(例如,符合不支持 Unicode 的旧协议)时,才应使用 ANSI 函数。
许多国家语言支持 (NLS) 函数(如 GetLocaleInfo 和 GetCalendarInfo)具有特定的 ANSI 版本,在本例中分别 GetLocaleInfoA 和 GetCalendarInfoA。 当应用程序将 ANSI 版本的函数与基于 Unicode 的作系统(如 Windows NT、Windows 2000、Windows XP 或 Windows Vista)配合使用时,该函数可能会失败或产生未定义的结果。 如果有一个令人信服的理由将 ANSI 函数用于此类作系统,请确保应用程序传递的数据对 ANSI 有效。
Unicode 规范化的安全注意事项
由于 Unicode 规范化可以更改字符串的形式,因此通常应在规范化后实现安全机制或字符验证算法。 例如,假设应用程序具有接受文件名但不接受路径名称的 Web 接口。 全角 U+FF43 U+FF1A U+FF3C U+FF57 U+FF49 U+FF4E U+FF44 U+FF4F U+FF57 U+FF53 (c : \ w i n d o w s)
更改为 U+006 3 U+001A U+003C U+0077 U+0069 U+006E U+0064 U+006F U+0077 U+0073 (c:\windows)
形式为 KC 规范化。 如果应用程序在实现规范化之前测试是否存在冒号和反斜杠字符,则结果可能是无意中的文件访问。
虽然 Unicode 规范化是使作系统安全化的一个元素,但请记住,规范化不是对全面安全策略的替代。
相关主题