安全的方式获得字母数字字符串从用户输入?没有preg_replace()


Safe way to get alpha-numeric string from user input? (without preg_replace)

我读过许多其他关于如何将字符串过滤为"Alpha-numeric"的问题,但它们都建议使用preg_replace()方法。

根据OWASP:

函数preg_replace()不应该与未消毒的用户一起使用输入,因为负载将是eval() ' ed13。

preg_replace("/。*/e"、"系统"(回波/etc/passwd));

反射也可以有代码注入缺陷。参考适当的反射文档,因为它是一个高级主题。

那么现在我如何实现这个没有preg_replace?

$result = preg_replace("/[^a-zA-Z0-9]+/", "", $_POST['data']);
// Notice the $_POST['data']

使用preg_replace()过滤用户输入没有问题。你所引用的OWASP建议是关于模式不是用户输入本身。

然而,我想说使用过滤输入本身就是一个问题-您应该进行验证。例如,不接受无效输入。

  1. 正如其他人指出的那样,您链接的OWASP漏洞仅在您评估表达式时适用,而您无论如何都不应该这样做。
  2. 根据我的经验,对于PHP内置字符串函数足够的简单操作,正则表达式是非常不适合的。字符串函数也更快。
  3. 如果数据无效,那么你不应该过滤它,你应该拒绝它。

例子:

$result = ctype_alnum($_POST['data']) ? $_POST['data'] : null;

我们也有类似的情况,我们使用了以下语句:

if ( ! preg_match('/^[a-z0-9:_'/|-]+$/i', $str))
{
//do your stuff
}

你可以这样写:

<?php
$unsafe_input = 'some"""''t&%^$@!`hing~~ unsafe '':[]435^%$^%*$^#'; // input from user
$safe_input = ''; // final sanitized string
// we want to allow 0-9 A-Z and a-z
// merge and flip so that we can use isset() later
$allowed_chars = array_flip(array_merge(range(0, 9), range('A', 'Z'), range('a', 'z')));
// loop each byte of the string
for($i = 0; $i < strlen($unsafe_input); ++$i)
{
    // isset() is lightyears faster than in_array()
    if(isset($allowed_chars[$unsafe_input[$i]]))
    {
        // good, sanitized, data
        $safe_input.= $unsafe_input[$i];
    }
}
echo $safe_input;