PHP strpos()返回奇怪的结果

4
我已经为我的Web应用程序编写了一个基本的“安全检查程序”。我需要一眼就能看到用户提交的代码是否包含恶意内容。

这是我现在运行的代码的截图:http://cl.ly/677a6dc40034f096697f

以下是我对这三段代码使用的PHP代码:

<!-- The View -->
<h2>Security analysis</h2>
<?php echo securitycheck($html, $css, $js); ?>

-

// The controller
function securitycheck($html, $css, $js)
{
    // The code is the html, css, and js, appended together. We're scanning it all.
    $code = $html." ".$css." ".$js;

    // $insecure is our array of naughty things to search for.
    $insecure = array(
                        /* HTML Elements */
                        'applet',
                        'basefont',
                        'base',
                        'behavior',
                        'bgsound',
                        'blink',
                        'embed',
                        'expression',
                        'frameset',
                        'frame',
                        'ilayer',
                        'iframe',
                        'isindex',
                        'javascript',
                        'layer',
                        'link',
                        'meta',
                        'object',
                        'plaintext',
                        'style',
                        'script',
                        'xml',
                        'xss',
                        /* Javascript Elements */
                        'alert',
                        'cmd',
                        'passthru',
                        'eval',
                        'exec',
                        'expression',
                        'system',
                        'fopen',
                        'fromcharcode',
                        'fsockopen',
                        'file',
                        'file_get_contents',
                        'readfile',
                        'unlink',
                        /* Misc Elements */
                        'vbscript:',
                        '<?',
                        '<?php',
                        '?>'
                    );

    $found = "";
    $output = "<p><strong>Potentially insecure items found:</strong> ";

    foreach($insecure as $item)
    {
        if (($pos = strpos($code, $item)) !== FALSE)
        {
            $found .= "$item, ";
        }
    }

    if ($found == "")
    {
        $output .= "None.<br/>";
    }
    else
    {
        $output .= "<span class=\"alert\">".substr($found, 0, -2)."</span>"."</p><br/>";  // cuts trailing comma and space from $found
    }

    return $output;
}

最后,这里是返回输出(HTML格式)的截图:http://cl.ly/f246dc419fb499dd6bd7

看到截图了吗?有几个问题。尾随的空格和逗号没有被去掉(我使用了substr()来做这件事),而且正如你从第一个截图中可以看到的那样,它报告了两个alert,但实际上只运行了一个。

我做错了什么?

谢谢!

杰克

编辑:正如Fosco友好地指出的那样,我的数组中重复列出了alert(呃!)。我已经修复了这个问题,但是留下的尾随逗号问题仍然存在。我知道这是一个较小的问题,但我发誓它不应该存在...


2
你的数组中 alert 被列出了两次。 - Fosco
4个回答

1

处理找到的物品更简单的方法是使用...

$found = array();

foreach($insecure as $item)
{
    if (($pos = strpos($code, $item)) !== FALSE)
    {
        $found[] $item;
    }
}
$found = implode(', ', $found);

字符串中只有一个警告,但它在您的$insecure列表中出现了两次,因此它会出现两次输出。为了避免这种情况,您需要分别扫描每个部分。


非常感谢!我看到第二个警报已经被移除了,现在我正在使用这个array()方法。 - Jack

1
一眼看上去,您的代码似乎应该输出您想要的结果。但我不确定出了什么问题。
建议您将$found构建为一个数组,而不是字符串,并使用implode()将其转换为字符串:
  • $found = "";替换为$found = array();
  • $found .= "$item, ";替换为$found[] = $item;
并替换此代码块:
if ($found == "")
{
    $output .= "None.<br/>";
}
else
{
    $output .= "<span class=\"alert\">".substr($found, 0, -2)."</span>"."</p><br/>";  // cuts trailing comma and space from $found
}

使用这个:

if (!count($found))
{
    $output .= "None.<br/>";
}
else
{
    $output .= "<span class=\"alert\">".implode(', ',$found)."</span>"."</p><br/>";  // cuts trailing comma and space from $found
}

谢谢Hammerite,我现在把这个做成了一个数组,我觉得这是个更好的主意!唯一的问题是——它仍然在eval,之后输出了一个尾随逗号,正如@Joseph所说,这可能与<?php有关——我打算手动编辑代码并查看一下。 - Jack
我明白了。但是禁止应该要谨慎进行... 用户可能只是不知情地从其他地方粘贴了HTML代码。 - Vladislav Rastrusny
1
@FractalizeR,该网站的主题是发布原创的CSS3、HTML5和JS片段。任何触发安全警告的内容都会受到我特别关注。显然,如果它看起来像是明显的恶意攻击尝试,他们将被禁止;如果只是复制粘贴错误,我们会发送礼貌的电子邮件要求他们修改提交内容。 - Jack

1

感谢@FractalizeR,我不是在重新发明轮子 - 当我需要将其“实时”输出给用户时,我实际上将使用HTML Purifier。这只是一种快速查看用户是否插入了不良内容的方式,以便我可以确定是否需要采取进一步的预防措施(例如禁止)。 - Jack

1
你试过仅回显$found然后查看源代码吗? 我猜问题可能是由于一个项目基于HTML编码('<?')而不被显示,实际上有一个逗号和空格被删除。
但我会echo @Hammerite的解决方案。

你说得对,是 <? 的输出导致了它的错误。有什么办法可以修复这个问题吗? - Jack
1
在屏幕上显示之前,请使用htmlentities进行编码:htmlentities(substr($found, 0, -2)) -- http://us3.php.net/manual/en/function.htmlentities.php - Joseph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接