Php 如何在保持所有非英语字母表支持的同时清理字符串

Php 如何在保持所有非英语字母表支持的同时清理字符串,php,sanitization,Php,Sanitization,一般来说,我会使用以下方法去除所有非英语字符: $file = filter_var($file, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH ); 但是,我厌倦了不支持来自其他语言的用户输入,这些语言可能是上传文件(文件名可能是西里尔文、中文或阿拉伯语等)或表单字段,甚至是所见即所得的内容 与此相关的数据消毒示例有两种形式之一 那些去除所有非英语字符的字符 将所有非英语字符转换为英语字母替代的

一般来说,我会使用以下方法去除所有非英语字符:

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

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

  • 那些去除所有非英语字符的字符
  • 将所有非英语字符转换为英语字母替代的字符
这种做法的问题是,最终你会发现一个框架被破坏了,它假装支持多种语言,但实际上除了用他们的语言向他们显示标签或内容之外,它并没有

有许多攻击利用unicode/utf-8/utf-16/etc支持传递空字节等,因此很明显,不清理数据不是一个选项

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

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

现在,回到PHP,您正在寻找的函数是。错误处理很简单,如果任何参数未通过测试,您将使用“错误请求”响应进行回复。无需猜测用户可能想要什么

虽然问题没有明确提出这一点,但以下是一些示例,以及在输入时应如何处理这些示例:

  • 非UTF-8字节:拒绝400(“错误请求”)
  • 包含路径元素的字符串(如
    。/
    ):接受
  • 包含路径元素(如
    。/
    )的文件名(非文件路径):用400拒绝
  • 文件名
    标志.png
    аБГаП.png
    :接受
  • 文件名
    foo bar.jpg
    :接受
  • 编号
    abc
    :以400拒绝
  • 编号
    1234
    :接受
以下是如何针对不同的输出处理它们:

  • 非UTF-8字节:不可能发生,它们以前被拒绝过
  • 包含路径元素的文件名:不可能,它们以前被拒绝过
  • 文件名
    标志.HTML中的png
    аБПП.png
    如果HTML编码为UTF-8,则使用逐字逐句,使用默认ISO8859-1时替换为HTML实体
  • 文件名
    标志.在Bash中,png
    аБГаП.png
    :假设文件系统的编码为UTF-8,则使用逐字记录
  • 文件名
    标志.png
    在SQL中:可能只是引用,取决于驱动程序、数据库、表等。请参阅手册
  • HTML中的文件名
    foo bar.jpg
    :转义为“foo bar.jpeg”。可能用“”表示空格
  • Bash:Quote或escape“”中的filename
    foo bar.jpg
    ,带反斜杠
  • SQL中的filename
    foo bar.jpg
    :只需引用即可
  • 编号
    abc
    :不可能发生,他们以前被拒绝过
  • HTML中的数字
    1234
    :使用逐字记录
  • Bash中的number
    1234
    :使用逐字记录(不确定)
  • SQL中的数字
    1234
    :使用逐字记录
一般程序应为:

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

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

我使用null作为示例。简单地检查UTF-8或不检查UTF-8并不能清除输入中的“坏”字符或字符串。我所说的坏,是指有害的。如果您看看
过滤器\u var
示例的功能,您就会明白我在寻找什么。它不只是一个字符。我个人的做法是,在将它们集成到html或SQL查询之前,修复我的软件以正确地转义它们。更好的是,在一个框架上构建软件,使它几乎可以