CSRF攻击与防御

CSRF原理

CSRF:Cross-site request forgery,跨站请求伪造,也被称为 one-click attack / session riding,缩写: CSRF 或者 XSRF。
攻击方式:挟制用户在当前已登录的Web应用程序上执行非本意的操作。简单理解为盗用用户的身份,发送恶意请求,此攻击容易造成个人隐私泄露和财产安全。
与跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。

浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户的Cookie信息以用户的权限处理该请求,导致来自网站B的恶意代码被执行。
如上图所示,完成一次CSRF攻击,需要用户:
1、登录受信任网站A,并在本地浏览器存储Cookie
2、在Cookie有效期内,同一浏览器访问恶意网站B
示例1:
银行网站A,用户以GET方式完成银行转账操作:https://www.mybank.com/transfer.php?userID=1&money=1000
恶意网站B,有一段HTLML代码:

<img src="https://www.mybank.com/transfer.php?userId=1&money=1000"/>

网站B以GET方式请求银行网站A,浏览器会带着用户访问银行网站A时的Cookie发出GET请求,银行网站服务器收到请求后,认为是合理操作,所以就继续进行转账操作.
示例2:
为了杜绝上面问题,银行网站A改用POST方式提交:

<form action="transfer.php" method="POST">
   <p>userId: <input type="text" name="userId" /></p>
   <p>Money: <input type="text" name="money" /></p>
   <p><input type="submit" value="transfer" /></p>
</form>

transfer.php处理如下:

<?php
   session_start();
   if (isset($_REQUEST['userId'] && isset($_REQUEST['money'])){
        buy_stocks($_REQUEST['userId'], $_REQUEST['money']);
   }
?>

这里恶意网站B仍然可以利用

<img src="https://www.mybank.com/transfer.php?userId=1&money=1000"/>

完成恶意操作,因为$_REQUEST可以获取POST和GET提交的数据。

示例3:

银行网站A把获取数据方法改成$_POST,transfer.php代码如下:

<?php
   session_start();
   if (isset($_POST['userId'] && isset($_POST['money'])){
        buy_stocks($_POST['userId'], $_POST['money']);
   }
?>

恶意网站B通过隐藏表单完成恶意攻击,代码如下:

<html>
  <head>
    <script type="text/javascript">
      function steal()
      {
               iframe = document.frames["steal"];
               iframe.document.Submit("transfer");
      }
    </script>
  </head>
  <body onload="steal()">
    <iframe name="steal" display="none">
      <form method="POST" name="transfer" action="http://www.myBank.com/transfer.php">
        <input type="hidden" name="userId" value="1">
        <input type="hidden" name="money" value="1000">
      </form>
    </iframe>
  </body>
</html>

通过以上示例可以看出:

CSRF攻击是源于web的隐式身份验证机制!web的身份验证虽然可以保证一个请求是来自某个用户的浏览器,但却无法保证该请求是用户允许发送的。

CSRF防御

CSRF防御可以从客户端、服务端两方面考虑,从服务端进行防御效果比较好。
预防CSRF只要在关键部分增加一些小操作即可。

  1. 验证码:使用验证码与用户互动,可以有效防御CSRF攻击,但频繁输入验证码可能会影响用户体验,所以一般在登录或者注册时使用。
  2. 检测Referer:通过检查Referer值可以判断请求是否合法,PHP可以通过$_SERVER[‘HTTP_REFERER’]获取referer值。但有时服务器不是随时能接收到Referer值,故Referer Check 一般用于监控CSRF攻击的发生,而不用来抵御攻击。
    注:一般在浏览器直接打开的url,或者https跳转到http会产生空Referer值。
  3. Token:服务端在每次页面加载时生成随机令牌,并隐藏在表单中。django中在Setting.py中启用CsrfViewMiddleware。服务端会检查随机字符串Token是否存在或者正确。
 <form action="transfer.php" method="POST">
   <p>userId: <input type="text" name="userId" /></p>
   <p>Money: <input type="text" name="money" /></p>
   <p><input type="hidden" value="token" /></p>
   <p><input type="submit" value="transfer" /></p>
</form>

注意:1)Token要足够随机,使攻击者无法预测;2)Token具有一次性,每次请求都要更新Token;3)Token具有保密性,敏感操作使用POST,防止Token出现在URL中。
4. 检查Origin:Origin字段只存在于POST请求,包含是谁发起的请求(URL格式、主机名和端口)。
参考文章:谈谈对web安全的理解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值