CSRF介绍及Python实现

CSRF

1. CSRF是什么?

  • CSRF(Cross-Site Request Forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。

2. CSRF可以做什么?

  • 你这可以这么理解CSRF攻击:**攻击者盗用了你的身份,以你的名义发送恶意请求。**CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。

3. CSRF漏洞现状

  • CSRF这种攻击方式在2000年已经被国外的安全人员提出,但在国内,直到06年才开始被关注,08年,国内外的多个大型社区和交互网站分别爆出CSRF漏洞,如:NYTimes.com(纽约时报)、Metafilter(一个大型的BLOG网站),YouTube和百度HI…而现在,互联网上的许多站点仍对此毫无防备,以至于安全业界称CSRF为“沉睡的巨人”。

4. CSRF的原理

  • 下图简单阐述了CSRF攻击的思想:

在这里插入图片描述

  • 从上图可以看出,要完成一次 CSRF攻击,受害者必须依次完成两个步骤:

    1. 登录受信任网站A,并在本地生成Cookie。
    2. 在不登出A的情况下,访问危险网站B。
  • 看到这里,你也许会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:

    1. 你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
    2. 你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了…)
    3. 上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。

5. 举例说明

  • 上面大概地讲了一下CSRF攻击的思想,这里用个例子详细说说具体的CSRF攻击,这里我以一个银行转账的操作作为例子(仅仅是例子,真实的银行网站没这么傻)

  • 银行网站A,它以GET请求来完成银行转账的操作:如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000

  • 危险网站B,它里面有一段HTML的代码如下:

    <img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

  • 首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块…
    为什么会这样呢?原因是银行网站A违反了HTTP规范,使用GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中的<img>以GET的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏览器会带上你的银行网站A的Cookie发出Get请求,去获取资源http://www.mybank.com/Transfer.php?toBankId=11&money=1000,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账操作),所以就立刻进行转账操作…

  • 理解了例子中的攻击模式,其实可以看出,CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!

6. CSRF的防御

  • Python 不提供针对 CSRF 攻击的内置built-in保护;开发人员必须通过检查 anti-CSRF tokens 或使用许多经过良好测试的库和框架中的一个来手动实现这一功能。

Python示例

以下步骤展示了如何使用登录时生成的每个会话 token 手动保护 Flask 端点 /delete_user 免受 CSRF 攻击。

  1. 身份验证成功后,会以安全方式生成一个随机 token,并作为用户的会话变量存储起来。

    @login.route("/login", methods=['POST'])
     def login():
         username = request.form.get("username")
         password = request.form.get("password")
    
         if validate_credentials(username, password):
             session['anti_crf_token'] = get_random_token()
             # ...
    

    函数 get_random_token() 必须返回用户会话唯一的强随机字符串。请参阅 uuid 或 Python3 secrets 库生成加密安全令牌。

  2. 为了保护任何改变状态的 endpoint,表单必须将 anti-CSRF token 设置为隐藏值。在下面的代码中, /users endpoint将渲染 users.html Jinja2 template。

    @login.route("/users", methods=['GET'])
    def users():
      if session_is_authenticated():
        return render_template('users.html', anti_crf_token=session['anti_crf_token'])
    

    users.html template 定义了包含标记 anti_crf_token 的 HTML 表单。

    <form action="/delete_user" method="post">
      <!-- ... -->
      <input type="hidden" name="anti_crf_token" value="{{anti_crf_token}}">
     </form>
    
  3. 现在,可以通过检查表单 POST 参数中发送的 anti_csrf_token 是否与 session['anti_crf_token'] 是否匹配来确保 /delete_user 的安全。

    @login.route("/delete_user", methods=['POST'])
    def delete_user():
       anti_csrf_token = request.form.get("anti_csrf_token")
       if session['anti_crf_token'] != anti_csrf_token:
           return "Error, wrong anti CSRF token", 401
       # Continue with a valid token
    

还可以使用其他库(如 WTFormsFlask-WTF)来自动执行部分反计算机资源框架保护。

相关推荐

  1. <span style='color:red;'>CSRF</span>

    CSRF

    2024-04-09 00:16:02      50 阅读
  2. spring(三):IOC介绍代码实现

    2024-04-09 00:16:02       33 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-09 00:16:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-09 00:16:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-09 00:16:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-09 00:16:02       18 阅读

热门阅读

  1. 前端开发教程

    2024-04-09 00:16:02       16 阅读
  2. SpringBoot实现增删改查

    2024-04-09 00:16:02       13 阅读
  3. 复试专业课问题

    2024-04-09 00:16:02       13 阅读
  4. css外边距合并和BFC

    2024-04-09 00:16:02       12 阅读
  5. Leetcode 8. 字符串转换整数 (atoi)

    2024-04-09 00:16:02       13 阅读
  6. 蓝桥杯嵌入式之模块驱动

    2024-04-09 00:16:02       14 阅读
  7. 线程同步的四项原则

    2024-04-09 00:16:02       11 阅读
  8. 解决Redission的RList查询list数据过慢的问题

    2024-04-09 00:16:02       14 阅读
  9. 自动导入和注册在当前目录下的所有自定义指令

    2024-04-09 00:16:02       11 阅读