欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

小议 CSRF 攻击

程序员文章站 2022-05-15 21:31:01
...

CSRF(Cross-site request forgery),即跨站请求伪造,本质就是攻击者伪造你的身份发送请求。

攻击流程

在 Google 上找了一张流程图:

小议 CSRF 攻击

  1. 用户访正常登录访问 mybank.com 网站,登录成功后,mybank 服务端会产生 Cookie 信息给浏览器;
  2. 在用户不登出 mybank.com 的情况下访问攻击网站 attacker.com 的攻击链接,此链接会直接访问 mybank.com,此时会携带着 mybank 的 Cookie,从而执行恶意脚本;

首先这里不能只局限于 Cookie,比如 Token,也是可以通过抓包分析获取的。也就是说 CSRF 的本质就是攻击者伪造你的身份发送请求,那么身份用什么体现呢,就是 Cookie 或者 Token。

示例

先看一个简单的模拟例子:

用户登录页面:
小议 CSRF 攻击

<form action="/login" method="post" enctype="multipart/form-data">
    <p> 用户名:<input type="text" name="username">
    <p> 密码:<input type="text" name="password">
        <input type="submit" value="提交">
</form>

后台代码:

    @RequestMapping("login")
    public Object login(@RequestParam("username")String username, @RequestParam("password")String password, HttpServletResponse response){
        Cookie cookie = new Cookie("8080Cookie", "123456");
        cookie.setPath("/");
        response.addCookie(cookie);
        return "OK";
    }

用户登录成功后这里会生成一个 Cookie:

小议 CSRF 攻击
攻击页面:

小议 CSRF 攻击

<h2>attack</h2>
<form action="http://localhost:8080/pay" method="post" enctype="multipart/form-data">
    <input type="text" name="money" value = "1000" style="visibility: hidden;">

    <input type="submit" value="恭喜你中奖了">
</form>

这里可以做成比如超链接等,如果用户点击了这个按钮,那么实际会携带着用户的 Cookie 信息去访问之前的系统,即“伪造你的身份发送请求”:

小议 CSRF 攻击

后端代码:

    @RequestMapping("pay")
    public Object pay(@RequestParam("money")Integer money, HttpServletRequest request){
        System.out.printf("获取了 Cookie:%s",
                Stream.of(request.getCookies()).collect(Collectors.toMap(Cookie::getName, Cookie::getValue)).get("8080Cookie"));
        return String.format("扣掉了 %d 元钱",money);
    }

这样会出现跨站请求成功:

小议 CSRF 攻击

如果无法获取 Cookie 的话,后端代码会抛出 NPE 异常。

防御方式

总得来说没有绝对的防御方式,其实将**过程设置的越复杂,也算是一种成功的防御。

通过 HTTP 请求头中的 Referer 和 Origin 属性

这两种方式其实并不算可靠,这里借用一篇博客中的描述(相关链接在文末):

  • referer属性

记录了该http请求的来源地址,但有些场景不适合将来源URL暴露给服务器,所以可以设置不用上传,并且referer属性是可以修改的,所以在服务器端校验referer属性并没有那么可靠

  • origin属性

通过XMLHttpRequest、Fetch发起的跨站请求或者Post方法发送请求时,都会带上origin,所以服务器可以优先判断Origin属性,再根据实际情况判断是否使用referer判断。

CSRF Token

这种应该是常用的一种方式,就是浏览器向服务器发送请求后,服务器端生成一个随机的 Token,然请求的时候就携带这个 Token,服务器端再进行校验,关于这个可以参看这两篇博客:

  • https://blog.csdn.net/Dongguabai/article/details/81150989
  • https://blog.csdn.net/Dongguabai/article/details/81151035

设置 SameSite 属性

Chrome 51 开始,浏览器的 Cookie 新增加了一个 SameSite 属性,用来防止 CSRF 攻击和用户追踪。

关于 SameSite 属性,可以参看:

  • http://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html

但是在动静分离的情况下,这时候静态资源会单独部署,这时候 SameSite 属性限制比较大。所以最常见的还是基于 Token 的方式去处理。

References

相关标签: safe