我整天都在阅读有关保护我的输出免受 xss 攻击的内容。目前我正在使用:
htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
它非常适合在我的 html 中显示时阻止代码。不过,我遇到了另一个问题,那就是显示可用的 url。
url 由用户提交并存储在数据库中。我在插入时使用带有准备好的语句/绑定(bind)的 PDO,所以我不担心 SQL 注入(inject),而是在输出和使用这些 url 时担心 xss。
典型的例子是这样的:
-
$str = "http://www.example.com/
存储在数据库中的值 - 我跑
htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
逃避它(默认情况下,我对从数据库获得的所有值执行此操作,因为我在我的 html 中显示了其中的大部分值) - 格式为
'<a href="'.$str.'" data-window="external"><i class="fa fa-external-link"></i> '.$str.'</a>'
$str 已经转义的地方 - 它们通过
json_encode(array of all the values)
传递给 js - 接收 js 将值输出到我的 html 中的表格
一切都好吧?没有。我正在运行一些测试,发现这个 xss 是可能的。这是一个测试值,在生成的 html 表中单击时显示 js 警报:
javascript://%0Aalert('XSS');
所以,除了在数据库插入时过滤它(出于显示目的,我仍然希望完全按照数据库中的原样显示)...我怎样才能防止这里的 xss?我今天读了很多东西,很多都提到了 urlencode,但是,这不适用于完整的 url。其他人提到 FILTER_VALIDATE_URL,但是,这似乎根本不能很好地工作。
是否没有办法按原样显示但阻止 url 实际工作(xss 工作)?
编辑:
好的,所以查看我得到的“骗局”给出了以下解决方案:
$url = 'http://username:password@hostname/path?arg=value#anchor';
$tmp = parse_url($url);
if ($tmp['scheme'] === 'http') {
echo 'is http://';
}
if (in_array($tmp['scheme'], array('http', 'skype', 'call')) {
echo 'is allowed protocol';
}
在这种情况下,它确实没有解决我的问题,因为我更希望按原样显示,只需确保链接不起作用。不过,这似乎是不可能的。
关于上述解决方案,似乎答案是在数据库输入上进行过滤,因此 javascript 作为协议(protocol)永远不会输入到数据库中,或者我在触发此协议(protocol)时显示“错误”消息而不是实际 url。
还有其他想法或可能性吗?
最佳答案
Is there no way to display as is yet prevent the url from actually working (xss working)?
是的,有:不要将它放在 anchor 标记内。如果过滤 URL 就像通过 native PHP 函数传递它一样简单,该函数可以神奇地在可点击的 anchor 标记中显示一种类型的 URL,而另一种类型的 URL 在 anchor 标记中显示为不可点击,那么 XSS 将降级为 PHP Web 的脚注应用程序安全性,即使如此。
您必须在输出之前分析每个 URL。该分析将以两种可能性之一结束:
- URL 可以在 anchor 标记的
href
属性中安全输出。 - URL 不能在 anchor 标记的
href
属性中安全输出。
如果是后者,要么将 href
属性留空,要么使用另一个 HTML 标签,点击时不会执行某些浏览器操作; span
标签是一个很好的选择。
需要说明的是,如果不进行额外的工作,您将无法做到这一点。没有单一的功能可以保留 URL 的外观并且不会使其在 anchor 中可点击。
关于javascript - 用户在标记中显示时提交了 URL 和安全性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24583752/