2009-12-11 77 views
0

我已经作出如下功能的URL的安全性。我只是想知道是否有什么我需要重新考虑或更改下面的代码。在阅读了关于各种来源的安全性的文章之后,我已经完成了这个功能。的URL安全

下面是函数:

// filters possible malacious stuff from URLs 
private function filter_url($url) 
{ 
    if (is_array($url)) 
    { 
    foreach($url as $key => $value) 
    { 
     // recurssion 
     $url[$key] = filter_url($value); 
    } 

    return $url; 
} 
else 
{ 
    // Allow only one ? in URLs 
    $total_question_marks = substr_count($url, '?'); 

    if ($total_question_marks >= 2) 
    { 
     exit('You can not use 2 question marks (?) in URLs for security reasons!!'); 
    } 

    // decode URLs 
    $url = rawurldecode($url); 
    $url = urldecode($url); 
    // remove bad stuff 
    $url = str_replace('../', '', $url); 
    $url = str_replace('..\\', '', $url); 
    $url = str_replace('..%5C', '', $url); 
    $url = str_replace('%00', '', $url); 
    $url = str_ireplace('http', '', $url); 
    $url = str_ireplace('https', '', $url); 
    $url = str_ireplace('ftp', '', $url); 
    $url = str_ireplace('smb', '', $url); 
    $url = str_replace('://', '', $url); 
    $url = str_replace(':\\\\', '', $url); 
    $url = str_replace(array('<', '>'), array('&lt;', '&gt;'), $url); 

    // Allow only a-zA-Z0-9_/.-?=& 
    $url = preg_replace("/[^a-zA-Z0-9_\-\/\.\?=&]+/", "", $url); 

    //print $url; 
    return $url; 
    } 
} 

我可以简单地使用此功能是这样的:

$_GET = filter_url($_GET); 

甚至是这样的:

$_SERVER['QUERY_STRING'] = filter_url($_SERVER['QUERY_STRING']); 
+0

你想要保护什么?一个URL本身并不是可以防范的。应用程序如何处理输入是发生可能的入侵的地方,而这个简单的过滤器不会自动保护每个后续层。 – deceze 2009-12-11 09:14:50

+0

基本上我做了一个框架MVC,在它所有的URL都重新路由。 – Sarfraz 2009-12-11 14:34:20

回答

5

任何企图,试图建立某种形式的包罗万象的这样的过滤器总是会失败,此外,因为你总是“腐败”的数据,你就会有麻烦的时候,你真的需要接受一段数据带有“不合格”字符或字符序列。

你真的需要围绕网络安全的主题阅读了一下,充分了解常见的攻击,如(最小的)跨站点脚本,跨站请求伪造和SQL注入。

你需要采取2方面入手,以安全的方式使用用户提供的数据。这是

这样想的过程:

  1. 验证并拒绝对数据的方式上的出路

输入验证 检查

  • 编码数据。每一块的输入,以确保它仅包含正确的数据类型和长度以及范围边界之内适合 - 根据数据的每个INIDIVIDUAL PIECE的含义 - 。即确保号码只包含数字。确保年份在合理的范围内,确保字符串不会过长或空白,确保文件名不会传送目录,确保ID仅包含合法字符。 etc.etc。等等。这里最重要的是,尽可能说明什么是允许的;不要说明什么是泄露。测试什么是允许的,否则拒绝一切被称为白名单和是一件好事,因为你知道你会得到干净的数据(或接近它是明智的)。寻找不好的模式并拒绝它们被称为黑名单,并且是不太安全的想法。要使黑名单成功,您需要确保您的黑名单已完成,而且这通常是一项不可能完成的任务。在一些有限的情况下,黑名单方法可能是有益的,但只有当你确信清单是详尽无遗的时候。

    存储数据 一旦您只有可接受的干净数据,请将其保存在变量或会话中。也许采取变量命名的方法,指出这个数据现在是干净的。这里最重要的是,当我们保存这些数据时,我们还没有改变它。这意味着数据可以在任何环境中使用而无需我们有“扔任何东西”

    输出编码 当您将数据发送到外部系统 - 如文件名,饼干,网页,文件或保存在您自己的数据库中 - 您必须对数据进行编码,以确保不会中断输出中使用的语言语法或文件格式。数据可以在这里转换。

    你需要对数据进行转换将根据您如何以及在何处使用数据是不同的。转换用于Windows文件名的字符串对于linux文件名是不同的,如果插入到PDF文档或网页或数据库等等中,则再次不同。但是,让我们更详细地查看2个示例:

    输出为HTML 在将字符串插入某些HTML的最常见情况下,您需要确保不允许用户向页面中注入任意内容,这不仅允许他们编辑页面另一个用户可以看到,但他们也可以注入JavaScript形式的代码,可以做任何他们想要的。该脚本将以查看页面的用户身份运行,并可能允许攻击者窃取他们的信息和登录凭据。这被称为跨站脚本。 HTML和Javascript的语法规则意味着您需要进行不同的编码,具体取决于您在HTML中插入用户数据的位置。在http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet有一个非常有价值的页面,它解释了如何转换6种不同类别的地方的数据,您可以在其中插入字符串到HTML页面。

    输出到数据库 如果用户的数据保存到数据库中,您有效地必须包括在SQL语句中的字符串。您必须确保不允许用户更改SQL语句的含义,并且只能更改数据值。如果他们可以更改语句的含义,则称为SQL注入。

    这是一个特殊的情况下,虽然可以使用输出编码是解决这个问题,你最好使用一个名为“绑定参数”技术。这可确保您的数据始终用作数据,而不会在与数据库交谈时用作代码。 PHP支持包括“PDO”(跨数据库)和“Mysqli”(MySQL)在内的许多数据库库中的绑定参数。应该指出,“Mysql”库不支持绑定参数。

    有更多的信息遍布网络和StackOverflow的有关跨站点脚本(XSS)和和SQL注入(SQLI),这是很值得一读围绕的主题。当然还有许多其他类型的攻击,但如果按照上述流程进行操作,应该尽量减少风险。数据验证和编码例程构成安全Web应用程序的重要组成部分并非不合理。但是您必须将安全方法学融入您的标准工作流程中。添加它作为事后的想法要困难得多。有时候回头看看你的验证代码,看看是否可以添加更多的规则。总会有你第一次错过的东西。

  • +0

    哎感谢这么好的解释,学到了很多:) – Sarfraz 2009-12-11 13:32:00

    3

    过滤器依靠黑名单失败。如果您认真检测攻击模式,请检查PHPIDS

    +0

    嘿谢谢你让我知道 – Sarfraz 2009-12-11 09:55:53

    +1

    请注意,所有Web应用程序IDS设备只能捕获极少数的恶意攻击媒介,它们通常很微不足道。只有使用这样的IDS方法作为额外的安全层,并且永远不要期望它为您开发的自己的应用程序提供任何真正的安全性。他们可能阻止一些常见的蠕虫,但对人类攻击者没有真正的威胁。 – Cheekysoft 2009-12-11 13:27:17

    +0

    嘿谢谢你让我知道这件事。 – Sarfraz 2009-12-11 13:32:33