这种消毒方法安全吗?

信息安全 php xss 注射
2021-08-20 18:08:40

我实施了这个清理修复:

function san($str, $type="full") {
    switch ($type) {
        case "full":
            $str = preg_replace("/[^a-zA-Z0-9_\-]/i", "", $str);
        break;
        case "mid":
            $str = preg_replace("/</i", "&gt;", $str);
            $str = preg_replace("/>/i", "&lt;", $str);
        break;
        case "low":
            if ($str == "true" || $str == true)
                $str = true;
            else
                $str = false;
        break;
    }

我想睡个安稳觉,但我不是安全专家。什么可以通过那个过滤器?我知道如何使用正则表达式,但是可以编码str绕过这个功能吗?

mid级别旨在防止 XSS 和full命令注入级别,例如:

$str = san($_REQUEST['cmd']);
$cmd = "cmd1 foo | cmd2 -arg=". $str; 
shell_exec($cmd); // is this secure?
1个回答

通用输入过滤器是否足够?

不,输入卫生不能正确防御任何攻击,所以仅仅因为你有一些过滤器就没有理由收工。

您确实需要针对典型攻击采取适当的防御措施,例如为 SQL 注入准备的语句、针对 XSS 的输出编码变量等。

话虽如此,强烈建议使用额外的输入过滤作为深度防御。

函数的可用性

可用性很重要。如果没有人知道你的函数究竟做了什么以及如何正确使用它,那么它提供的安全性就会降低,因为人们——这可能包括将来的你——会错误地使用它或更改它。

不过,您的功能并不是那么有用。如果我看到san($x, "full"),我不知道发生了什么。同样适用于midlow作为论点(并且命名甚至似乎没有意义;低应该不太安全 - 对抗......某物...... - 比完整或中?)。

通用的“完整”还可以很容易地更改代码的功能。也许您认为;在其他情况下您需要,那么为什么不添加它呢?它似乎没有造成任何伤害,并且仍然符合“完整”描述。

我会建议一些Input具有诸如getInt($name), getAlphaNum($name), getCleanHTML($name), getRaw($name),getFilter($name, $regex)等方法的通用类。使用这样的名称,您可以立即看到您得到的内容,以及它是否适合输入和情况。你也知道不要改变实现(getInt应该总是返回一个整数,getAlphaNum总是字母数字)。

防御代码执行

你的例子应该是安全的。我无法跳出当前上下文或添加新命令,因为我既没有空格也没有分号,也没有任何其他可以在不同 shell 中用于添加新命令的字符。

不过,如上所述,我会重写它。所以它可能看起来像这样:

$str = Input::getFilter("cmd", [^a-zA-Z0-9_\-]);
$cmd = "cmd1 foo | cmd2 -arg=". escapeshellarg($str); 
shell_exec($cmd); // is this secure?

现在您正在使用推荐的方法 (escapeshellarg),并有一个额外的过滤器,很清楚该过滤器当前做什么或将来可能做什么。

防御 XSS

首先,你的代码有问题。<$lt(小于)。

其次,这将在某些情况下防御 XSS,但不是全部。<img src="[USERINPUT]">如果您已经在标签上下文(例如)或 JavaScript 上下文(例如)中,它不会防御 XSS <script>var = "[USERINPUT]";</script>

这也是输入过滤不足以防止 XSS 的原因之一(除了非常严格的过滤,例如只接受整数)。您需要了解上下文以正确防御它。在大多数情况下,htmlspecialcharswithENT_QUOTES就足够了,请参阅本指南以获取更多信息。