CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
http://baike.baidu.com/view/1609487.htm
CSRF的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。
client.php
1 <?php 2 function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) { 3 4 $ckey_length = 4; 5 $key = md5($key ? $key : time()); 6 $keya = md5(substr($key, 0, 16)); 7 $keyb = md5(substr($key, 16, 16)); 8 $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : ''; 9 10 $cryptkey = $keya.md5($keya.$keyc); 11 $key_length = strlen($cryptkey); 12 13 $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string; 14 $string_length = strlen($string); 15 16 $result = ''; 17 $box = range(0, 255); 18 19 $rndkey = array(); 20 for($i = 0; $i <= 255; $i++) { 21 $rndkey[$i] = ord($cryptkey[$i % $key_length]); 22 } 23 24 for($j = $i = 0; $i < 256; $i++) { 25 $j = ($j + $box[$i] + $rndkey[$i]) % 256; 26 $tmp = $box[$i]; 27 $box[$i] = $box[$j]; 28 $box[$j] = $tmp; 29 } 30 31 for($a = $j = $i = 0; $i < $string_length; $i++) { 32 $a = ($a + 1) % 256; 33 $j = ($j + $box[$a]) % 256; 34 $tmp = $box[$a]; 35 $box[$a] = $box[$j]; 36 $box[$j] = $tmp; 37 $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); 38 } 39 40 if($operation == 'DECODE') { 41 if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) { 42 return substr($result, 26); 43 } else { 44 return ''; 45 } 46 } else { 47 return $keyc.str_replace('=', '', base64_encode($result)); 48 } 49 50 } 51 52 function formhash($specialadd = '') { 53 $username = $_COOKIE['username']; 54 $uid = $_COOKIE['uid'];
$auth_code = authcode($string, $operation = 'DECODE', $key = '', $expiry = 0);
55 return substr(md5(substr(time(), 0, -7).$username.$uid.$auth_code.$specialadd), 8, 8); 56 } 57 58 $hash = formhash(); 59 ?> 60 <form method=”POST” action=”transfer.php”> 61 <input type=”text” name=”toBankId”> 62 <input type=”text” name=”money”> 63 <input type=”hidden” name=”hash” value=”<?=$hash;?>”> 64 <input type=”submit” name=”submit” value=”Submit”> 65 </form>
在服务器端进行hash认证
server.php
1 <?php 2 if(isset($_POST['submit'])) { 3 $hash = md5($_COOKIE['token']); 4 if($_POST['hash'] == $hash) { 5 doJob(); 6 } else { 7 //... 8 //非法请求 9 } 10 } else { 11 //... 12 } 13 ?>
延伸阅读:
http://www.baidu.com/s?wd=csrf
http://www.sogou.com/web?query=csrf
http://www.so.com/s?q=csrf
http://www.baidu.com/s?wd=csrf%20php
http://www.sogou.com/web?query=csrf%20php
http://www.so.com/s?q=csrf%20php
http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html