如何在维护所有非英语字母表支持的同时清理字符串
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 支持传递空字节等,因此很明显不清理数据不是一种选择。
有没有办法从任意命令中清除变量,同时保持这些其他语言的完整 alphabets/chars,但(以通用方式)剥离所有可能的不可打印字符,具有它们中的空值作为 char 的一部分,以及其他此类漏洞利用,同时保持用户输入的实际字符的完整性?上面的命令是完美的并且完全按照它应该做的一切,但是如果有一种方法可以扩展它以允许支持所有语言,那就太棒了。
空字节不是(!)UTF-8,因此假设您在内部使用 UTF-8,您需要做的就是验证传递的变量是 UTF-8。例如,没有必要支持 UTF-16,因为作为 API 的作者或表单定义了正确的编码,您可以将自己限制为 UTF-8。此外,"unicode" 也不是您需要支持的编码,仅仅是因为它不是编码。相反,Unicode 是一个标准,UTF 编码是其中的一部分。
现在,回到PHP,您要查找的函数是mb_check_encoding()。错误处理很简单,如果任何参数未通过该测试,您将回复 "bad request" 响应。无需尝试猜测用户可能想要什么。
虽然问题没有具体问这个,但这里有一些例子以及在输入时应该如何处理它们:
- 非 UTF-8 字节:用 400 ("bad request") 拒绝。
- 包含路径元素的字符串(如
../
):接受。
- 包含路径元素(如
../
)的文件名(不是文件路径):用 400 拒绝。
- 文件名
شعار.jpg
、标志.png
或 логотип.png
:接受。
- 文件名
foo <0> bar.jpg
:接受。
- number
abc
: 用 400 拒绝。
- 人数
1234
:接受。
以下是针对不同输出处理它们的方法:
- 非 UTF-8 字节:不可能发生,它们之前被拒绝了。
- 包含路径元素的文件名:不会发生,它们之前被拒绝了。
- 文件名
شعار.jpg
、标志.png
或 логотип.png
in HTML:如果 HTML 编码为 UTF-8,则逐字使用,替换为 HTML 使用默认 ISO8859-1 时的实体。
- 文件名
شعار.jpg
、标志.png
或 логотип.png
in Bash:逐字使用,假设文件系统的编码为 UTF-8。
- 文件名
شعار.jpg
、标志.png
或 логотип.png
in SQL:可能只是引用,取决于驱动程序、数据库、表等。请查阅手册。
- HTML 中的文件名
foo <0> bar.jpg
:转义为 "foo <0> bar.jpeg"。 space 可以使用“ ”。
- Bash 中的文件名
foo <0> bar.jpg
:使用反斜杠引用或转义“”、“<”和“>”。
- 文件名
foo <0> bar.jpg
in SQL: 只是引用。
- 人数
abc
:不可能,之前被拒了
1234
in HTML: 逐字使用。
- number
1234
in Bash:逐字使用(不确定)。
- 数字
1234
in SQL:逐字使用。
一般程序应该是:
- 定义您的内部类型(字符串、文件名、数字)并拒绝任何不匹配的内容。这些类型创建约束(文件名不包括路径元素)并提供保证(文件名可以附加到目录以在该目录内形成文件名)。
- 使用模板库(想到小胡子)HTML。
- 为 SQL 使用数据库包装器库(PDO、Propel、Doctrine)。
- 转义 shell 参数。我不确定该走哪条路,但我相信你会找到合适的方法。
转义不是定义的过程,而是一系列过程。实际使用的转义算法取决于目标上下文。除了你写的("escaping will also screw up the names"),实际情况应该相反!基本上,它确保在 XML 中包含小于号的字符串仍然是包含小于号的字符串,并且不会变成格式错误的 XML 片段。为了实现这一点,转义转换字符串以防止任何通常不被解释为纯文本的字符获得其正常解释,例如 shell.
中的 space 字符
一般来说,我会使用类似这样的方式去除所有非英语字符:
$file = filter_var($file, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH );
然而,我厌倦了不支持其他语言的用户输入,这些输入可能是以上传文件的形式(文件名可能是西里尔文或中文,或阿拉伯文等)或表单字段,甚至是所见即所得的内容。
与此相关的数据清理示例采用两种形式之一
- 去除所有非英语字符的那些
- 那些将所有非英语字符转换为英语字母替代品的那些。
这种做法的问题在于,您最终会得到一个损坏的框架,该框架假装它支持多种语言,但它实际上并不支持以他们的语言向他们显示标签或内容。
有许多攻击利用 unicode/utf-8/utf-16/etc 支持传递空字节等,因此很明显不清理数据不是一种选择。
有没有办法从任意命令中清除变量,同时保持这些其他语言的完整 alphabets/chars,但(以通用方式)剥离所有可能的不可打印字符,具有它们中的空值作为 char 的一部分,以及其他此类漏洞利用,同时保持用户输入的实际字符的完整性?上面的命令是完美的并且完全按照它应该做的一切,但是如果有一种方法可以扩展它以允许支持所有语言,那就太棒了。
空字节不是(!)UTF-8,因此假设您在内部使用 UTF-8,您需要做的就是验证传递的变量是 UTF-8。例如,没有必要支持 UTF-16,因为作为 API 的作者或表单定义了正确的编码,您可以将自己限制为 UTF-8。此外,"unicode" 也不是您需要支持的编码,仅仅是因为它不是编码。相反,Unicode 是一个标准,UTF 编码是其中的一部分。
现在,回到PHP,您要查找的函数是mb_check_encoding()。错误处理很简单,如果任何参数未通过该测试,您将回复 "bad request" 响应。无需尝试猜测用户可能想要什么。
虽然问题没有具体问这个,但这里有一些例子以及在输入时应该如何处理它们:
- 非 UTF-8 字节:用 400 ("bad request") 拒绝。
- 包含路径元素的字符串(如
../
):接受。 - 包含路径元素(如
../
)的文件名(不是文件路径):用 400 拒绝。 - 文件名
شعار.jpg
、标志.png
或логотип.png
:接受。 - 文件名
foo <0> bar.jpg
:接受。 - number
abc
: 用 400 拒绝。 - 人数
1234
:接受。
以下是针对不同输出处理它们的方法:
- 非 UTF-8 字节:不可能发生,它们之前被拒绝了。
- 包含路径元素的文件名:不会发生,它们之前被拒绝了。
- 文件名
شعار.jpg
、标志.png
或логотип.png
in HTML:如果 HTML 编码为 UTF-8,则逐字使用,替换为 HTML 使用默认 ISO8859-1 时的实体。 - 文件名
شعار.jpg
、标志.png
或логотип.png
in Bash:逐字使用,假设文件系统的编码为 UTF-8。 - 文件名
شعار.jpg
、标志.png
或логотип.png
in SQL:可能只是引用,取决于驱动程序、数据库、表等。请查阅手册。 - HTML 中的文件名
foo <0> bar.jpg
:转义为 "foo <0> bar.jpeg"。 space 可以使用“ ”。 - Bash 中的文件名
foo <0> bar.jpg
:使用反斜杠引用或转义“”、“<”和“>”。 - 文件名
foo <0> bar.jpg
in SQL: 只是引用。 - 人数
abc
:不可能,之前被拒了 1234
in HTML: 逐字使用。- number
1234
in Bash:逐字使用(不确定)。 - 数字
1234
in SQL:逐字使用。
一般程序应该是:
- 定义您的内部类型(字符串、文件名、数字)并拒绝任何不匹配的内容。这些类型创建约束(文件名不包括路径元素)并提供保证(文件名可以附加到目录以在该目录内形成文件名)。
- 使用模板库(想到小胡子)HTML。
- 为 SQL 使用数据库包装器库(PDO、Propel、Doctrine)。
- 转义 shell 参数。我不确定该走哪条路,但我相信你会找到合适的方法。
转义不是定义的过程,而是一系列过程。实际使用的转义算法取决于目标上下文。除了你写的("escaping will also screw up the names"),实际情况应该相反!基本上,它确保在 XML 中包含小于号的字符串仍然是包含小于号的字符串,并且不会变成格式错误的 XML 片段。为了实现这一点,转义转换字符串以防止任何通常不被解释为纯文本的字符获得其正常解释,例如 shell.
中的 space 字符