如何对用户提交的URL进行清理处理?

14

我想将用户的个人网址作为纯文本存储,并使用htmlspecialchars()进行编码。

然后,我会检索这些数据并按照以下方式生成和显示链接:

echo '<a href="'.$retrieved_string.'" target="_blank">';

即使进行了特殊字符和引号的编码,由于可能插入的javascript代码,href链接仍然不安全。以下是一个糟糕链接的示例:

javascript:alert(document.cookie);

所以我的想法是在进行特殊字符编码之前,先查找潜在的“javascript”标签,并将其去除,具体如下:

preg_replace('/^javascript:?/', '', $submitted_and_trimmed_input);

因此,让我们总结一下:

$input=htmlspecialchars(preg_replace('/^javascript:?/', '', trim($_POST['link'])),11,'UTF-8',true);
mysql_query("update users set link='".mysql_real_escape_string($input)."'");

//And retrieving:

$query=mysql_query("select link from users");
$a=mysql_fetch_assoc($query);
echo '<a href="'.$a['link'].'" target="_blank">';

现在的问题是,仅仅使用一个安全的url链接是否足够,还是有其他潜在的意外情况需要注意?

编辑:

我已经了解到filter_var()的一些信息,它在很多方面都无法胜任。它无法验证包含Unicode字符的国际域名,而且下面这个字符串也可以成功通过测试:

http://example.com/"><script>alert(document.cookie)</script>
  • 我的意思是...那简直太荒谬了,一定有更好的方法

2
停止使用mysql_*函数,它们已被弃用。改用PDO或者mysqli。如果不确定该使用哪个,请阅读这篇SO文章 - Matt
我的意思是它们已经被弃用了,只是需要谨慎使用,而我会注意到这一点。 - Anonymous
PDO和mysqli都具有净化功能。为什么你不想使用它们呢? - Matt
它们并不总是被支持,因为大多数系统仍然使用旧的系统。对于任何未来的项目,我会考虑实现mysqli或pdo。 - Anonymous
你说得有道理,但mysqli在PHP 4.1中就已经被支持了;PDO从5.1开始支持。你的服务器上的PHP版本有多久了? - Matt
显示剩余2条评论
2个回答

11

尝试使用filter_var()

filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)

所以我猜应该是我的链接,而不是示例吧? :) - Anonymous
是的,这就是你需要做的。 :) - John Conde
11
我已经了解了filter_var()一些内容,它似乎在很多方面都会彻底失败。它不能验证具有Unicode字符的国际域名,然后以下字符串成功地通过了测试:'" rel = "nofollow noreferrer">http://example.com/"><script>alert(document.cookie)</script>' - 我的意思是...这太荒谬了。 - Anonymous
针对example.com返回false。 - Fanky

-1

这是我要做的。在我看来,最好的方法是在前面加上http:

$link=preg_replace('/^(http(s)?)?:?\/*/u','http$2://',trim($_POST['website']));

所以即使有一个脚本到达,我也不在乎。然后实际转换字符:

$link= htmlspecialchars($link, 11,'UTF-8',true);

就这样。不拐弯抹角,也应该兼容utf-8。


这个不起作用。你需要传递 ENT_NOQUOTEShtmlspecialchars,以使其转义引号。你的 'example.com/"><script>alert(document.cookie)</…; 测试将触发 xss。 - Billy ONeal
是的,真的。请阅读文档:http://www.php.net/manual/en/function.htmlspecialchars.php。 - Billy ONeal
ENT_NOQUOTES会保留双引号和单引号并不进行转换。 - Anonymous
2
@匿名用户:你的态度有些粗鲁。请克制一下自己。我们在这里是来帮助你的。http://stackoverflow.com/faq#etiquette - Jens
重点是防止任何东西注入到用户的个人资料“网站”中(除了链接)。例如,这将防止JavaScript的注入。如果该URL不存在,那不是我们的问题。 - Anonymous
显示剩余3条评论

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