PHP URL安全问题

时间:2010-04-01 14:21:42

标签: php mysql htmlpurifier

我希望用户将url存储在我的数据库中我正在使用php mysql和htmlpurifier我想知道以下代码是否是在将数据存储到数据库之前过滤掉错误数据的好方法?

这是部分PHP代码。

$url = mysqli_real_escape_string($mysqli, $purifier->purify(htmlspecialchars(strip_tags($_POST['url'])));

6 个答案:

答案 0 :(得分:4)

您无需在数据上调用htmlspecialchars()HTMLPurifier - 您实际上只有一个问题,并且确保URL不包含SQL注入 - { {1}}将对此进行排序。

或者,如果您要将数据输出到页面/ HTML(而不是将其用作HTTP重定向标头),则需要使用mysqli_real_escape_string()来保护数据,以防止您输出数据。黄金法则是情境意识:

  

HTML实体编码可以   您放入的不受信任的数据   HTML文档的正文,例如   在标签内。它甚至有点儿   适用于不受信任的数据   进入属性,特别是如果   你虔诚地使用引号   围绕你的属性。但HTML   如果你是实体编码不起作用   将不受信任的数据放入    标记任何地方或事件   处理程序属性,如onmouseover,或   在CSS内部或URL中。即便如此   您使用HTML实体编码方法   无处不在,你仍然是最有可能的   易受XSS攻击。你必须使用   HTML部分的转义语法   记录您正在提供不受信任的数据   成。

要深入参考XSS预防,请查看OWASP

最好在使用之前对数据进行编码(针对相关攻击)(即MySQL转义字符串用于输入数据库以防止SQLi,HTML转义字符串输出到屏幕以防止XSS,而不是同时)。这允许您通过应用程序跟踪数据流,并且您知道数据库中的所有数据都可以用于任何目的。如果您在将数据放入数据库之前对其进行HTML编码,则在将其用作HTTP标头之前,必须对其进行解码。

如果您必须在数据进入数据库之前对其进行编码,请确保列名称反映了这一点,以供将来的开发人员/维护人员使用!

修改

根据VolkerK的评论,在URL输出中阻止XSS的最佳方法是检查协议 - 如果它与您允许的协议(可能是http / https)不匹配则拒绝它:

htmlentities()

这具有在$url = 'http://hostname/path?arg=value#anchor'; $parsedUrl = parse_url( $url ); if( $parsedUrl['scheme'] != 'http' ) { // reject URL } else { $url = mysqli_real_escape_string( $mysqli, $url ); $sql = "INSERT INTO table (url) VALUES ('$url')"; // insert query } 情况下防止javascript:alert('xss')攻击的优势。在<a href="$url">上运行htmlentities()没有任何影响(因为javascript:alert('xss')等字符的有限子集不存在要转义),因此恶意用户可以在您的域上执行JS

答案 1 :(得分:1)

在将值放入数据库之前,只需要mysqli_real_escape_string()

为了防范XSS,应该在显示时显示的所有数据(在HTML中)调用htmlspecialchars(),而不是在存储之前。

想象一下,有一天你可能需要以HTML以外的格式输出数据;那么你会后悔在它存储在你的数据库之前就所有内容都调用了htmlspecialchars()

我不知道你为什么要使用purifierstrip_tags(),也许你有一个特殊的原因,但它看起来像是“我使用的更多层数据清理” , 更好”。 htmlspecialchars()无论如何都会使HTML无害。

答案 2 :(得分:0)

如果您担心SQL注入,这将清除它并防止它。否则,不确定你究竟在问什么。

答案 3 :(得分:0)

如果您只需要将URL存储在数据库中并将其取回,只需将字符串通过mysqli_real_escape_string一次即可。不需要任何其他东西。当您想要将其输出回HTML页面中的用户时,您只需要使用htmlspecialchars。

HTMLPurifier根本不属于此处,因为它清除HTML而不是URL。

答案 4 :(得分:0)

我将url存储在我的数据库中,它只是经过xss清理,但是被orm自动转义。这基本归结为:

mysqli_real_escape_string(strip_tags($var));

首先清理它,然后确保可以保存在db中,然后保存未更改的URL。

关于它的出路然而你会拉它然后在你的模板中使用htmlentities()以防万一它可能会干扰html。

你真的不需要过度设计这样的东西。

PS。如果你正在使用POST,你可以这样做:

$fixed = $_POST;
$fixed = array_map('strip_tags', $fixed);
$fixed = array_map('mysqli_real_escape_string', $fixed);

然后使用$ fixed数组。

答案 5 :(得分:0)

您需要区分过滤和转义。收到数据后,应该对其进行过滤。这意味着要删除不良角色和有缺陷的数据。

使用过滤器扩展和适当的过滤器将数据从超全局数组传输到应用程序变量。

在此之后,您可能想要清空$ _POST以避免再次使用未过滤的数据。

然后你将它按到你想要的形状。

转义是在发送或保存数据之前的步骤,应该根据输出介质完成。

使用mysqli_real_escape_string转义以存储在MySQL数据库中。如果您使用其他DBMS,则应使用其他功能。

更好的是,使用准备好的语句和占位符来存储用户数据。

当输出为HTML时,htmlentities可能是明智的。如果您不希望数据中包含任何HTML代码。如果您这样做,请使用HTMLPurifier之类的可信库。

我建议您不要尝试在一行代码中执行所有操作,如示例中所示。这更难阅读,更难维护。

对于网址,htmlentities是一种避免未转义的&amp; amp;字符。它们当然应该是&amp;它还确保你没有使用任何引号,因为你当然也使用旗帜来引用那些 - 对吗?

但是在存储数据时不应该应用此功能。它应该在发送给用户时应用。

过滤输入 - 转义输出! (引用Chris Schifflett)