2010-04-01 101 views
0

我想让用户在我的数据库中存储网址我使用的是php mysql和htmlpurifier我想知道在将数据存储到数据库之前,以下代码是否可以过滤掉不良数据?PHP URL安全问题

这是部分PHP代码。

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

定义“坏数据” – 2010-04-01 14:23:47

+0

什么意思是坏数据? – 2010-04-01 14:25:23

+0

XSS和SQL注入。 – TaG 2010-04-01 14:25:27

回答

0

如果你担心SQL注入,它会清除它并阻止它。否则,不确定你在问什么。

4

你不需要在数据上调用htmlspecialchars()和​​3210 - 你真的只有一个问题在这里,这是确保该URL不包含SQL注入 - mysqli_real_escape_string()将排序。

或者,如果您要将数据输出到页面/ HTML(而不是将其用作HTTP重定向标头),则需要使用htmlentities()来防止数据输出时发生XSS。金科玉律是背景感知:

HTML实体编码是好的,为你把 体的HTML文档的 不可信数据,如 一个标签内。它甚至可以用于 适用于不可信数据的 属性,特别是如果您对使用围绕您的属性的引用 信仰宗教信仰 。但是,如果您将 不受信任的数据放入任何地方的 标记或处理器属性(如CSS中的onmouseover或 )或URL中的事件 ,但HTML 实体编码不起作用。因此,即使您使用的HTML实体编码方法 无处不在,您仍然最有可能的 容易受到XSS。对于要将不可信数据 置入的HTML 文档部分,您必须使用 转义语法。

有关XSS预防的深入参考,请查看OWASP

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

如果您必须在数据进入数据库之前对其进行编码,请确保列名反映了未来的开发人员/维护人员!

编辑:

按VolkerK的评论,以防止XSS在URL输出的最好方法是检查协议 - 如果它不符合您的允许的协议(可能是HTTP/HTTPS)拒绝:

$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 
} 

这具有防止在<a href="$url">情况javascript:alert('xss')攻击的优势。在javascript:alert('xss')上运行htmlentities()没有任何影响(因为<>等字符的有限子集不存在被转义),因此恶意用户将能够在您的域上执行JS。

+0

$ url正在被'javascript:alert(“hello”)'?这不是关于文本/内容,而是URL/URI/URN,它是属性的值。所以htmlenties/htmlspecialchars()不是一个安全的选择。 – VolkerK 2010-04-01 15:02:07

+0

@VolkerK只能在window.location重定向(即在Javascript标记)中执行,或者当设置为HTML标记参数时执行,而不是在作为HTML内容输出或作为HTTP标头的一部分输出时执行。授予的OP没有指定数据的使用,所以所有的基地应该被答案覆盖。在数据库中存储数据时,XSS预防不成问题,在输出编码时相关。 OWASP参考添加从http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting))_Prevention_Cheat_Sheet – Andy 2010-04-01 15:14:18

+0

无论如何,你打开门“你需要使用htmlentities()”,我认为不会做(整个)工作,如果URL是例如在href属性中。我会检查模式并将其限制为http,https可能是ftp,不管是否合理。这是在将值存储在数据库之前可以执行的操作。 $ url ='skype:whatever'->错误(除非这正是你想要允许的---))。 – VolkerK 2010-04-01 16:18:23

1

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

为了防止XSS,htmlspecialchars()应在您显示的所有数据上显示时调用(以HTML格式),而不是在存储之前调用。

想象一下,您可能有一天需要以非HTML格式输出数据;那么在将它存储在数据库中之前,你会后悔的称呼它为htmlspecialchars()

我不知道为什么你使用purifierstrip_tags(),也许你有一个特别的原因,但它只是看起来像一起“数据清洗的层数越多我用,精益求精”的行矫枉过正。无论如何,htmlspecialchars()将使任何HTML无害。

0

如果您只需要将网址存储在数据库中并将其取回,只需将该字符串传递给mysqli_real_escape_string即可。无需其他任何东西。您只需要使用htmlspecialchars当您想要将其输出回HTML页面中的用户。

HTMLPurifier根本不属于这里,因为它清理HTML而不是URL。

0

我在我的数据库中存储网址,它只是被xss清除,但是被orm自动转义。这基本上可以归结为:

mysqli_real_escape_string(strip_tags($var)); 

所以你先清洗,然后确保这是确定在数据库保存,然后保存不变网址。

在它的出路,然而你会拉它,然后在你的模板使用htmlentities(),以防万一有可能会干扰HTML的任何东西。

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

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

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

然后使用$ fixed数组。

0

您需要区分过滤和转义。当收到数据时,应该过滤它。这意味着剥离不良的角色和有缺陷的数据。

使用过滤器扩展名和适当的过滤器将数据从超全局数组转换为应用程序变量。

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

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

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

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

更好的是,为用户数据使用预先准备好的语句和占位符。

以HTML格式输出时,htmlentities可能是明智的。假设您不想在数据中拥有任何HTML代码。如果这样做,请使用HTMLPurifier之类的可信库。

我建议你不要试图在一行代码中做所有事情,就像你的例子。这是更难以阅读和更难维护。

对于URL,htmlentities是避免非转义字符的好方法。他们当然应该是&它也确保你没有使用任何引号,因为你当然使用标志来引用这些引号 - 对吗?

但是在存储数据时不应该使用这个函数。它在发送给用户时应该应用。

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