一文从容应对CSRF

本文详细介绍了CSRF(跨站请求伪造)攻击的概念、实现方式及危害,并提出了两种常见的预防策略:Referer验证和Token验证。通过实例阐述了CSRF攻击的过程,指出Referer验证的局限性,并分享了一个实际项目中采用的CSRF拦截器代码,以双重验证确保系统安全。
摘要由CSDN通过智能技术生成


前言:
在开发中相信相信很多人都会注意到CSRF这个东西,那这个是什么呢,隐隐约约只知道这是个安全策略。但是具体做什么,有什么用,防哪些安全隐患的却知道的不甚清楚。笔者带着疑问查了一些资料,在这里做个总结。

一、CSRF

1.CSRF是什么?

跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。以上的解释就是官方给的CSRF的解释,解释比较简短,若是需要深刻理解CSRF的攻击方式还需要通过例子来说明CSRF的攻击过程。下面就来详细说下CSRF的攻击过程。

2.CSRF如何实现攻击?

在这里插入图片描述
上面这张图就是一个典型的CSRF攻击的流程:
第一步:Tom登录银行网站没有退出,此时Tom使用的浏览器中包含了Tom在银行的身份验证信息。
第二步:黑客或者称为攻击人员在一个帖子中加入了超链接,这个超链接就是Tom已经登录的银行的转账地址。
第三步:Tom在没有正常退出银行网站时,就去点击了第二步攻击人员设置的帖子。
第四步:银行收到攻击人员设置的转账请求,然后发现当前请求是Tom发起的(因为浏览器Cookie中仍存在Tom的登录信息),银行发起转账此时Tom的账户资金就被窃取了。
我们可以发现以上攻击可以实施的前提是第一步和第二步都满足了,只有满足了这两步Tom去浏览攻击者的帖子才会有账户被盗的风险,有人觉得这只是一个低概率事件,并不一定会触发这种场景,但是在安全的范围内这是一个漏洞,是企业中严令禁止的。我们不能将风险放任到客户自己的操作上,这样一旦客户操作失误,就会出现重大的生产事故,所以这种CSRF的攻击方式是需要每个项目去考虑的,那这种风险应该怎么去解决呢?下面就来说下如何预防CSRF这种攻击方式。

二、预防CSRF攻击的方式

要说预防CSRF的攻击,必须要说Referer,那Referer是什么呢?

1.Referer是什么?

Referer是Http请求头header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。Referer的正确英语拼法是referrer。由于早期HTTP规范的拼写错误,为了保持向后兼容就将错就错了。其它网络技术的规范企图修正此问题,使用正确拼法,所以拼法出现了不统一的情况。
上面是官方给出的Referer的定义,现在已经清楚了,当使用浏览器访问web服务器时,请求头中就会有Referer这个字段,这个字段用来表示请求的来源,下面是一个例子:
在这里插入图片描述
可以看到笔者打开的W3Cschool网站中点开的一个链接,当前的请求头中就出现了referer这个字段。这里必须要说明的是该字段可以实现不发送,因为笔者是后端开发,对于实现的机制也不是太了解。但是是可以实现的,所以很多请求点开是不会有Referer这个字段的。那我们要怎么使用Referer来预防CSRF攻击呢?

2.使用Referer来预防CSRF攻击

上面给的Tom账户被盗的例子,这里接着用这个例子来说明,当Tom登录了银行系统去发起转账时,那么此时转账请求中的Referer的值应该是银行网站的域名,但是当Tom点击了攻击者的帖子而发起转账时Referer的值应该是帖子所在的域名。这两者是不同的。所以如果银行系统在每次发起转账时对请求头中的Referer进行验证,只对于Referer是本站内的域名时才放行操作,就可以杜绝这种攻击。这种预防CSRF攻击的解决方案是最简单的一种,也是应用最多的一种,笔者目前正在做的项目就是使用的这种方法。
那Referer是绝对安全的吗?
当然也不是,没有一种技术是无懈可击的,这种使用Referer来判断请求来源的方式也不是百分百安全的。因为有工具可以篡改Referer的值,让你以为是真的客户发送的请求,此外Referer是http的规范,有的浏览器并没有实现,当然了主流的浏览器基本全都实现了,但是不能保证所有人使用的浏览器都是主流浏览器,所以这种解决方式并不是百分百安全的。

3.另一种预防CSRF攻击的策略

CSRF的攻击策略很明显就是借助用户浏览器的cookie信息来完成伪登录的,那么只要我们使用的验证信息不在cookie中,CSRF就不能完成攻击,现在常用的就是前端每次访问接口都是需要验证token,前后端的交互依赖token来进行,至于前端token存储在哪,反正不能存在cookie中,可以存sessionstorage等地方,这样一旦token验证失败,就认为是不正常的操作。

三、生产预防CSRF实践

笔者目前所在的项目是一个电商项目,对于预防CSRF的攻击使用了Referer验证与Token验证的方式来预防。双重保证下基本不会有CSRF攻击的出现,具体的措施是使用了两个拦截器,一个token登录拦截器,该拦截器拦截用户传递的token然后去统一用户进行验证,一个是CSRF拦截器验证请求头中的Referer是否是已信任的域名。
下面展示下CSRF拦截器关键代码。

1.CSRF拦截器

这种拦截很简单,就是获取请求头中的Referer然后和已配置的白名单进行比对,发现是白名单一员,则允许通过,若不是则拒绝。

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        String referer = request.getHeader("Referer");
        String flag = getFlagValue();//拦截器开关
        String whiteUrls = getWhiteUrlValues();//获取Referer白名单,只有白名单成员的请求才可以进入到系统
        //判断是否启用refer过滤 1:开启; 0:关闭
        if ("1".equals(flag)) {
            if (StringUtil.isNotNull(referer)) {
                if (StringUtil.checkUrlCSRF(referer, whiteUrls)) {
                    return true;
                } else {
                    returnCSRF(response);
                    return false;
                }
            } else {
                returnCSRF(response);
                return false;
            }
        }
        return true;
    }
    
    public static boolean checkUrlCSRF(String refer, String whileUrls)
	{
		if(isNotNull(refer)){
			List<String> whiteUrlList = new ArrayList<String>();
			whiteUrlList = Arrays.asList(whileUrls.split(";"));

			if(whiteUrlList != null && whiteUrlList.size() > 0){
				for(int i = 0; i < whiteUrlList.size(); i++){
					if(refer.indexOf(whiteUrlList.get(i)) == 0){
						return true;
					}
				}
				return false;
			}
		}

		return true;
	}
	
	private void returnCSRF(HttpServletResponse response) throws Exception {
	        ResultDTO resultDTO = new ResultDTO(ExceptionEnum.AUTHORITY_CSRF_30.getResultCode(), null, ExceptionEnum.AUTHORITY_CSRF_30.getResultMsg());
	
	        response.setStatus(403);
	        response.setHeader("Access-Control-Allow-Origin", "-");
	        response.setHeader("Access-Control-Allow-Credentials", "false");
	
	        JSONObject jsonObject = new JSONObject();
	        jsonObject.put("resultDTO", resultDTO);
	        JsonSerializerUtil.returnJson(response, jsonObject.toString());
	        resultDTO = null;
	    }

四、总结

这篇文章总结了CSRF攻击的原理,以及怎么去预防CSRF的攻击。然后说明了现在互联网公司是如何来解决CSRF攻击的场景,希望看到此篇文章的人从此对CSRF都不在迷惑,也可以从容应对这种攻击手段。CSRF攻击是一种偏向于安全的东西,但是作为后端开发确实是必须掌握的,假如需要你设计一个系统架构,架构是设计出来了,但是安全漏洞有很多等于没用,如果攻击者可以轻松的攻击你的系统,那这个系统还有什么存在的意义呢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

归去来 兮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值