Blogger Information
Blog 6
fans 0
comment 0
visits 5927
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
安全:PHP防止站外表单跨站提交的几种办法详解
新月网络的博客
Original
1036 people have browsed it

在众多功击手段中,有一种是功击者自己伪造了一个和你网站一样的表单,然后在他自己站内或别处,向你的网站提交。

这种跨站和XSS不一样,是为了提交表单数据到你的网站,给安全造成了问题。


对于这类的功击,有几种方式:

1、传统的浅层阻止:这个是最常用的。但是其实根本没用

$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : NULL;$host = $_SERVER['HTTP_HOST'];echo '提交过来的地址:'.$referer;echo '<br>本站域名:'.$host; echo substr($referer,7,strlen($host));if(substr($referer,7,strlen($host)) != $host){       echo '非法操作';}else{       echo '正常操作';}


因为REFERER可以伪造。所以没有意义。


2、加密令牌:

很多CMS会用到这个方式,就是生成一个随机串,比如VEPHP , 然后随表单生成一个隐藏域<input type="hidden" value="vephp" name="chk" /> 并把这个值保存到服务器的SESSION上。

等到用户提交后,检查这个表单值和SESSION对比,不符就阻止。

不过,这个方式如果用户多的话,会造成大量的SESSION,消耗服务器资源。不推荐。一种优化的方式是把这个口令放在CACHE系统中,但是因为缓存会不定时清除,所以也有问题。


3、加密方式:

推荐这种方式:分为单向加密和可逆向加密。

就是生成一个随机且变换频繁加密字符串(可逆和不可逆)。跟方式2一样放在表单中。等到表单提交后检查。

这个随机字符串如果和当前用户身份相关联的话,那么攻击者伪造请求会比较麻烦。

对付伪造跨站请求的办法是在表单里加入一个叫.crumb的随机串;而facebook也有类似的解决办法,它的表单里常常会有post_form_id和fb_dtsg。这种方式中,字符串的有效时间要设置好,太短了用户体验不好,比如好不容易写好文章提交,令牌却到期了。不得不重写,这很糟糕的体验。因此,TTL过期时间应可设置。

下面是一个网上的不可逆的验证方式,值的推荐:

class Crumb {       CONST SALT = "http://www.vephp.com";       static $ttl = 7200;   #很重要,不要太短,看表单用途修改issueCrumb()过期时间        /** 生成加密串,可以添加到表单中        * @param $uid  用户ID        * @param int $action        * @return bool|string        */       static public function issueCrumb($uid, $ttl=7200, $action = -1) {              if(intval($ttl)>7200) self::$ttl = $ttl;              $i = ceil(time() / self::$ttl);              return substr(self::challenge($i . $action . $uid), -12, 10);       }        /** 解密        * @param $uid        * @param $crumb  加密时 Crumb::issueCrumb($uid)生成的字串。        * @param int $action        * @return bool        */       static public function verifyCrumb($uid, $crumb, $action = -1) {              $i = ceil(time() / self::$ttl);               if(substr(self::challenge($i . $action . $uid), -12, 10) == $crumb ||                     substr(self::challenge(($i - 1) . $action . $uid), -12, 10) == $crumb)                     return true;              return false;       }        //内用       static public function challenge($data) {              return hash_hmac('md5', $data, self::SALT);       }}


使用:

在表单中插入一个隐藏的随机串crumb,其中,$uid可以是会员的ID,这样就有独立性。

   <input type="hidden" name="crumb" value="<?php echo Crumb::issueCrumb($uid)?>">


在PHP服务器接收端,这样检验。默认下这个字串的有效期是7200秒。

<?phpif(!Crumb::verifyCrumb($uid, $_POST['crumb'])) echo "验证失败";


上面这种是不可逆的加密,

有时,我们还希望在表单中加入私密数据,跟随用户表单加密串一直生成,在前端不被用户看到,这样就可以用到可解密的函数,生成的字串在PHP端解密,起到2个作用:

1、得到私密数据。

2、验证表单来源的合法性。


我推荐可逆的加密方式。

转载请注明本页网址:
http://www.vephp.com/jiaocheng/61.html


Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!