【问题标题】:How do I sanitize a user submitted url? [duplicate]如何清理用户提交的网址? [复制]
【发布时间】:2012-07-31 15:09:45
【问题描述】:

我想将用户的个人网址存储为纯文本,由 htmlspecialchars() 编码。

然后我会检索这些数据并生成并显示一个链接,如下所示:

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

然而,即使使用编码的特殊字符和引号,href 也可能不安全,因为可能插入了 javascript,例如错误链接:

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>
  • 我的意思是普通...这太可笑了,一定有更好的方法

【问题讨论】:

  • 停止使用mysql_*函数。它们正在被弃用。请改用PDOmysqli。如果您不确定要使用哪一个,read this SO article.
  • 我的意思是它们已被弃用,我只是谨慎使用它们。
  • PDO 和 mysqli 具有清理功能。为什么不想你想使用它们?
  • 它们并不总是受支持,因为大多数系统仍然使用旧系统编写。对于任何未来的项目,我会考虑实施 mysqli 或 pdo。
  • 你说得有道理,但是 PHP 4.1 支持 mysqli;从 5.1 开始的 PDO。您服务器上的 PHP 使用了多少年?

标签: php regex security url


【解决方案1】:

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

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

因此,即使脚本到达那里,我也不在乎。然后实际转换字符:

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

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

【讨论】:

  • 这不起作用。您需要将 ENT_NOQUOTES 传递给 htmlspecialchars 以使其转义引号。您的'example.com/"&gt;&lt;script&gt;alert(document.cookie)&lt;/…; 测试将触发 xss。
  • 是的,真的。阅读文档:php.net/manual/en/function.htmlspecialchars.php
  • ENT_NOQUOTES 将不转换双引号和单引号。
  • 抱歉,我引用错误的标志。它是 ENT_QUOTES。默认情况下不转换单引号。
  • @Anonymous:你太粗鲁了。请克制一点。我们是来帮忙的。 stackoverflow.com/faq#etiquette
【解决方案2】:

尝试使用filter_var()

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

【讨论】:

  • 所以我猜我的链接不是示例? :)
  • 是的,这就是你需要做的。 :)
  • 我读过一些关于 filter_var() 的文章,它似乎在很多方面都完全失败了。它不使用 unicode 字符验证国际域,然后以下字符串再次成功通过测试:'example.com/"><script>alert(document.cookie)</…>' - 我的意思是常见的......这太荒谬了
猜你喜欢
  • 2018-07-23
  • 2011-08-16
  • 2015-09-17
  • 2015-11-09
  • 2021-01-12
  • 2018-12-23
  • 1970-01-01
  • 2012-08-25
  • 2020-01-23
相关资源
最近更新 更多