一、CSRF跨站请求伪造

CSRF(Cross-site request forgery)跨站请求伪造:(“One Click Attack”或者Session Riding),通常缩写为CSRF或者XSRF是一种对网站的恶意利用,一种可以被攻击者用来通过用户浏览器冒充用户身份向服务器发送伪造请求并被目标服务器成功执行的漏洞

csrf漏洞的成因:网站的cookie一次会话在浏览器中,只要不关闭浏览器或者退出登录就是不会过期(除非特殊设置自动过期时间),那以后只要是访问这个都网站,会默认你已经登录的状态。而在这个期间,攻击者发送了构造好的csrf脚本或包含csrf脚本的链接,可能会执行一些用户不想做的功能(比如是添加账号等)js(可以发送数据包) ajax。 比如以你的名义发送邮件、发消息,盗取你的账号,甚至于购买商品、转账等。

CSRF通过伪造来自受信任用户的请求来利用受信任的网站,通过社会工程学手段(发送邮件链接)来蛊惑受害者进行一些敏感性操作,如修改密码、修改E-Mail、转账等,而受害者还不知道已经中招。

CSRF与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站
XSS是通过插入恶意的攻击脚本到用户信任的网站,代码被前端解析后,请求服务器。
CSRF是伪装成用户信任的网站发起请求到服务器。
CSRF攻击不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

二、CSRF攻击攻击原理及过程如下:

1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
5.浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

java 怎么解决跨站点请求伪造 跨站请求伪造以及防范_java 怎么解决跨站点请求伪造


java 怎么解决跨站点请求伪造 跨站请求伪造以及防范_前端_02


java 怎么解决跨站点请求伪造 跨站请求伪造以及防范_前端_03

三、CSRF漏洞危害

CSRF攻击特点:

  • 攻击时机:网站的cookie在浏览器中没有过期,不关闭浏览器或者退出登录
  • 攻击前提:对目标网站接口有一定了解
  • 攻击难度:攻击难度高于XSS与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

危害:

java 怎么解决跨站点请求伪造 跨站请求伪造以及防范_前端_04

四、防御方案

Referer校验

根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer(浏览器会自动加上这个字段),它记录了该 HTTP 请求的来源地址。

java 怎么解决跨站点请求伪造 跨站请求伪造以及防范_前端_05

我们可以利用Referer校验区分是否为伪造请求,Refer记录了该http请求的来源地址,访问一个安全受限页面请求必须来自同一个网站,如果不是则请求不合法无法生效 [可绕过]。
你可以:

  • 在网关过滤器中校验
  • 在对应的微服务中定义拦截器
  • 具体的业务代码中实现
  • 登录

伪代码相关实现:
SpringMVC__自定义简单的拦截器

重新preHandle方法:

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws
            Exception {
        logger.debug("拦截器拦截到对:{}的访问", request.getRequestURI());
        String referer = request.getHeader("referer");
        logger.debug("referer:{}", referer);
        StringBuilder sb = new StringBuilder();
        sb.append(request.getScheme()).append("://").append(request.getServerName());
        logger.debug("basePath:{}", sb.toString());
        if (referer == null || referer == "" || !referer.startsWith(sb.toString())) {
            response.setContentType("text/plain; charset=utf-8");
                    response.getWriter().write("非法访问,请通过页面正常问!");
            return false;
        }
        return true;
    }

Referer的优势与劣势:

1.简单易行,开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以,非常便捷。
2.Referer 的值是由浏览器提供的,并不能保证浏览器自身没有安全漏洞。对于某些浏览器,目前已经有一些方法可以篡改 Referer 值,黑客完全可以修改 Referer 值,这样就可以通过验证,从而进行CSRF 攻击。
3.即便黑客无法篡改 Referer 值,因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,因此用户自己可以设置浏览器使其在发送请求时不再提供Referer。当他们正常访问网站时,网站会因为请求没有 Referer 值而拒绝合法用户的访问。

token校验

Token就是一段字母数字的随机值,访问时服务端会生成一个随机的token值并传回到前端的表单里,当我们提交表单时,token会作为一个参数提交到服务端进行验证 [终极方案]

  • 当客户端第一次请求时,发送用户信息至服务器(用户名、密码),服务器对用户信息使用HS256算法及密钥进行签名,再将这个签名和数据一起作为Token一起返回给客户端
  • 服务器不保存Token,客户端保存Token(比如放在Cookie里或者Local Storage里)
  • 当客户端再次发送请求时,在请求信息中将Token一起发给服务器
  • 服务器用同样的HS256算法和同样的密钥,对数据再进行一次签名,和客户端返回的Token的签名进行比较,如果验证成功,就向客户端返回请求的数据

实现:
SpringBoot__JWT无状态服务和Spring Security登入认证

分布式token

借鉴:
跨站点请求伪造(CSRF)