如何在保持所有非英语字母表支持的情况下净化字符串


How can I sanitize a string while maintaining all non-English alphabet support

一般来说,我会用之类的东西去掉所有非英语字符

$file = filter_var($file, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH );

然而,我厌倦了不支持来自其他语言的用户输入,这些语言可能是上传文件(文件名可能是西里尔文、中文或阿拉伯语等)或表单字段,甚至是所见即所得的内容。

与此相关的清除数据的示例有两种形式之一

  • 那些去掉所有非英语字符的字符
  • 那些将所有非英语字符转换为英语字母替代品的字符

这种做法的问题是,你最终会得到一个破碎的框架,它假装支持多种语言,但实际上除了用他们的语言向他们显示标签或内容之外。

有许多攻击利用了unicode/utf-8/utf-16/etc对传递空字节等的支持,因此很明显,不清除数据不是一种选择。

是否有任何方法可以在维护这些其他语言的完整字母表/字符的同时,从任意命令中清除变量,但(以通用的方式)去除所有可能的不可打印字符、作为字符一部分的带有null的字符以及其他此类漏洞,同时保持用户输入的实际字符的完整性?上面的命令是完美的,可以完全按照它应该做的来做任何事情,但是如果有一种方法可以扩展它以支持所有语言,那将是非常酷的。

Null字节不是(!)UTF-8,所以假设您在内部使用UTF-8,您所需要做的就是验证传递的变量是UTF-8。例如,不需要支持UTF-16,因为您作为API或表单的作者定义了正确的编码,并且您可以将自己限制为UTF-8。此外,"unicode"也不是您需要支持的编码,因为它不是一种编码。相反,Unicode是一种标准,UTF编码是其中的一部分

现在,回到PHP,您要查找的函数是mb_check_encoding()。错误处理很简单,如果任何参数都没有通过测试,您将以"坏请求"响应进行回复。无需尝试猜测用户可能想要什么。

虽然这个问题并没有特别提出这个问题,但这里有一些例子以及应该如何处理输入:

  • 非UTF-8字节:以400拒绝("错误请求")
  • 包含路径元素的字符串(如../):Accept
  • filename(不是文件路径)包含路径元素(如../):用400拒绝
  • 文件名شعار.jpg标志.pngлоготип.png:接受
  • filename foo <0> bar.jpg:接受
  • number abc:以400拒绝
  • number 1234:接受

以下是如何针对不同的输出处理它们:

  • 非UTF-8字节:不可能,它们以前被拒绝过
  • filename包含路径元素:不可能发生,它们以前被拒绝过
  • HTML中的文件名شعار.jpg标志.pngлоготип.png:如果HTML编码为UTF-8,则逐字使用,使用默认ISO8859-1时替换为HTML实体
  • Bash中的文件名شعار.jpg标志.pngлоготип.png:逐字使用,假设文件系统的编码为UTF-8
  • SQL中的文件名شعار.jpg标志.pngлоготип.png:可能只是引号,取决于驱动程序、数据库、表等。请参阅手册
  • HTML中的文件名foo <0> bar.jpg:转义为"foo<0>bar.jpeg"。可能使用" "作为空格
  • Bash中的filename foo <0> bar.jpg:引号或带反斜杠的转义符"、"<"answers">"
  • SQL中的filename foo <0> bar.jpg:仅引用一句
  • 数字abc:不可能,他们以前被拒绝过
  • HTML中的数字1234:逐字使用
  • Bash中的数字1234:逐字使用(不确定)
  • SQL中的数字1234:逐字使用

一般程序应为:

  • 定义您的内部类型(字符串、文件名、数字),并拒绝任何不匹配的内容。这些类型创建约束(文件名不包括路径元素)并提供保证(文件名可以附加到目录中以在该目录中形成文件名)
  • 使用HTML的模板库(脑海中浮现出"胡子")
  • 为SQL使用DB包装库(PDO、Propel、Doctrine)
  • 转义shell参数。我不知道该走哪条路,但我相信你会找到合适的路的

逃跑不是一个明确的程序,而是一系列程序。实际使用的转义算法取决于目标上下文。除了你写的("逃避也会把名字搞砸"),实际情况应该相反!基本上,它确保在XML中包含小于号的字符串保持为包含小于号,并且不会变成格式错误的XML片段。为了实现这一点,转义转换字符串,以防止任何通常不被解释为文本的字符得到正常的解释,比如shell中的空格字符。