项目进行安全测试时需要预防CSRF攻击,记录一下学习的过程。

一.CSRF攻击是什么?

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。举个例子,你登录了信任网站www.aaa.com(A网站),A网站服务器里的session存放了你的登录状态,并调用接口 http://api.aaa.com/getUserInfo 以获取你的个人信息,你在未登出时,又点击了恶意网站www.bbb.com(B网站),此时如果B网站上有类似<img src="http://api.aaa.com/getUserInfo">,<script src="http://api.aaa.com/getUserInfo></script>的代码,当A网站没有做CSRF预防,A网站的服务端就收到了http://api.aaa.com/getUserInfo的请求,并且因为cookie的存在,判断你处于登录的状态,返回了数据,至此,B网站就窃取了你的个人信息。

二.如何预防?

CSRF攻击是源于Web的会话身份验证机制,虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的,这个情况是有可能发生的,预防一般是服务端来做。

1.检测请求的referer,这种方式可以预防相当一部分的攻击,但是不全,因为referer可以被伪造。

2.添加csrf_token,项目为后端渲染成html时可以生成一个csrftoken到表单中,请求时携带这个token,前后端分离时的具体方法如下:

  1.用户登录时,服务端可以初始化一个不可预测的,随机csrftoken放到服务端session中,同时又放到前端cookie中;

  2.前端通过js抓取cookie里面的csrftoken放到请求的head中去;

  3.服务端收到请求后,会验证前端传递来的csrftoken与之前存在session中的csrftoken是否一致,一致则说明没别劫持;

  4.原因是,黑客可以构造请求数据,并且携带cookie去请求,但是却无法获取cookie的值,而且请求中的csrftoken是变化的,黑客就无法通过服务端的验证,请求就会失败;

 

下面是生成和检测csrftoken的php代码

<?php
//基于tp5.0框架的代码
class Csrf{
  
    public static function refreshToken(){
        $token = md5(makeHash());//自定义的一个生成参数的函数
        session('csrf_token',$token);
        cookie('csrf_token',$token);
    }
    public static function checkToken(){
        $token = getallheaders()['X-CSRFToken'];//前端自定的header头属性为 X-CSRFToken
        if(session('csrf_token')&&session('csrf_token')==$token){

        }else{
            throw \Exception('非法请求',100012);
        }
    }
}