当前位置:首页 > PHP教程 > php应用 > 列表

php防止伪造跨站请求实现程序

发布:smiling 来源: PHP粉丝网  添加日期:2014-08-23 08:57:02 浏览: 评论:0 

CSRF站外类型的漏洞其实就是传统意义上的外部提交数据问题,一般程序员会考虑给一些留言评论等的表单加上水印以防止SPAM问题,但是为了用户的体验性,一些操作可能没有做任何限制,所以攻击者可以先预测好请求的参数,在站外的Web页面里编写javascript脚本伪造文件请求或和自动提交的表单来实现GET、POST请求,用户在会话状态下点击链接访问站外的Web页面,客户端就被强迫发起请求.

浏览器的安全缺陷

现在的Web应用程序几乎都是使用Cookie来识别用户身份以及保存会话状态,但是所有的浏览器在最初加入Cookie功能时并没有考虑安全因素,从 WEB页面产生的文件请求都会带上COOKIE,如下所示,Web页面中的一个正常的图片所产生的请求也会带上COOKIE:

<img src=”http://website/logo.jpg”>

GET http://website.com/log.jpg

Cookie:session_id,客户端,服务器,咱们按照这个思路,山寨一个crumb的实现,代码如下:

  1. class Crumb {                                                                                                                                                                                                           
  2.     CONST SALT = "your-secret-salt";                                                          
  3.                                                                   
  4.     static $ttl = 7200;                                                                                           
  5.                                                                                                       
  6.     static public function challenge($data) {                                                                     
  7.         return hash_hmac('md5'$data, self::SALT);                                                               
  8.     }                                                                                                             
  9.     //开源代码phpfensi.com               
  10.     static public function issueCrumb($uid$action = -1) {                                                       
  11.         $i = ceil(time() / self::$ttl);                                                                           
  12.         return substr(self::challenge($i . $action . $uid), -12, 10);                                             
  13.     }                                                                                                             
  14.                                                                                                                   
  15.     static public function verifyCrumb($uid$crumb$action = -1) {                                               
  16.         $i = ceil(time() / self::$ttl);                                                                           
  17.                                                                                                                   
  18.         if(substr(self::challenge($i . $action . $uid), -12, 10) == $crumb ||                                      
  19.             substr(self::challenge(($i - 1) . $action . $uid), -12, 10) == $crumb)                                 
  20.             return true;                                                                                           
  21.                                                                                                                   
  22.         return false;                                                                                             
  23.     }                                                                                                             
  24.                                                                                                                   

代码中的$uid表示用户唯一标识,而$ttl表示这个随机串的有效时间.

应用示例,在表单中插入一个隐藏的随机串crumb,代码如下:

  1. <form method="post" action="demo.php"> 
  2. <input type="hidden" name="crumb" value="<?php echo Crumb::issueCrumb($uid)?>"> 
  3. <input type="text" name="content"> 
  4. <input type="submit"> 
  5. </form> 

处理表单 demo.php,对crumb进行检查,代码如下:

  1. if(Crumb::verifyCrumb($uid$_POST['crumb'])) { 
  2.     //按照正常流程处理表单 
  3. else { 
  4.     //crumb校验失败,错误提示流程 

注意:CSRF攻击和相关web蠕虫的爆发,并且针对这类web攻击制定有效的应急措施,同建议程序员不要滥用$_REQUEST类变量,在必要的情况下给某些敏感的操作加上水印,考虑使用类似DISCUZ论坛的formhash技术提高黑客预测请求参数的难度,注意JSON数据接口的安全问题等.

Tags: php防止 php伪造跨站请求

分享到: