web上常见的攻击以及应对

csrf(Cross-Site Request Forgery)-跨站请求伪造

攻击者诱导用户进入第三方网站中,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的用户认证凭证(在cookie中),完成冒充用户对被攻击的网站执行某项操作。

一个典型的CSRF攻击有着如下的流程:a.com是被攻击网站,b.com是第三方网站

  1. 受害者登录a.com,并保留了登录凭证(Cookie)。
  2. 攻击者引诱受害者访问了b.com。
  3. b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie
  4. a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
  5. a.com以受害者的名义执行了act=xx。
  6. 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。

特点

  1. 攻击一般发起在第三方网站,而不是被攻击的网站。被攻击的网站无法防止攻击发生。
  2. 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。
  3. 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
  4. 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。
  5. CSRF通常是跨域的,因为外域通常更容易被攻击者掌控。但是如果本域下有容易被利用的功能,比如可以发图和链接的论坛和评论区,攻击可以直接在本域下进行,而且这种攻击更加危险。

防护策略

1.双重Cookie验证(推荐)

请求头中加csrf token,加上cookie中的csrf_token进行验证。第一次的csrf token怎么来,登录的时候允许不使用csrf token,然后登录请求调用后会返回一个csrf token 让其设置在cookie中
Spring security中的**CookieCsrfTokenRepository**就是使用该方式

   @Override
    protected void configure(HttpSecurity http) throws Exception {
        //表单
//        http.authorizeRequests().anyRequest().authenticated().and().formLogin();
//        http.sessionManagement().sessionFixation().migrateSession().maximumSessions(1).maxSessionsPreventsLogin(true);

        //自定义认证方式

        //csrf设置 使用双重cookie校验
        CookieCsrfTokenRepository cookieCsrfTokenRepository = new CookieCsrfTokenRepository();
        cookieCsrfTokenRepository.setCookiePath("/");
        cookieCsrfTokenRepository.setCookieHttpOnly(false);
        http.csrf().ignoringAntMatchers("/login").csrfTokenRepository(cookieCsrfTokenRepository);

        //停用form表单登录
        http.formLogin().disable();

        //防御点击劫持 如果有html页面
        http.headers().frameOptions().disable();

        //自定义认证
        http.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class);

        //url授权设置
        http.authorizeHttpRequests().antMatchers("/login").permitAll().anyRequest().authenticated();

        // 认证 授权失败设置
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandlerConfig).authenticationEntryPoint(authenticationHandlerConfig);
    }

缺点:

  • 如果有其他漏洞(例如XSS),攻击者可以注入Cookie,那么该防御方式失效。
  • 难以做到子域名的隔离。
    1. 如果用户访问的网站为www.a.com,而后端的api域名为api.a.com。那么在www.a.com下,前端拿不到api.a.com的Cookie,也就无法完成双重Cookie认证。
    2. 于是这个认证Cookie的domain属性必须设置.a.com下,这样每个子域都可以访问。
    3. 任何一个子域都可以修改a.com下的Cookie。
    4. 某个子域名存在漏洞被XSS攻击(例如upload.a.com)。虽然这个子域下并没有什么值得窃取的信息。但攻击者修改了a.com下的Cookie。
    5. 攻击者可以直接使用自己配置的Cookie,对XSS中招的用户再向www.a.com下,发起CSRF攻击。

2.使用cookie的same site属性

防止CSRF攻击的办法已经有上面的预防措施。为了从源头上解决这个问题,Google起草了一份草案来改进HTTP协议,那就是为Set-Cookie响应头新增Samesite属性,它用来标明这个 Cookie是个“同站 Cookie”,同站Cookie只能作为第一方Cookie,不能作为第三方Cookie,Samesite 有两个属性值,分别是 Strict 和 Lax

如果SamesiteCookie被设置为Strict,浏览器在任何跨域请求中都不会携带Cookie,新标签重新打开也不携带,所以说CSRF攻击基本没有机会。
但是跳转子域名或者是新标签重新打开刚登陆的网站,之前的Cookie都不会存在。尤其是有登录的网站,那么我们新打开一个标签进入,或者跳转到子域名的网站,都需要重新登录。对于用户来讲,可能体验不会很好。
如果SamesiteCookie被设置为Lax,那么其他网站通过页面跳转过来的时候可以使用Cookie,可以保障外域连接打开页面时用户的登录状态。但相应的,其安全性也比较低。
另外一个问题是Samesite的兼容性不是很好,现阶段除了从新版Chrome和Firefox支持以外,Safari以及iOS Safari都还不支持,现阶段看来暂时还不能普及。
而且,SamesiteCookie目前有一个致命的缺陷:不支持子域。例如,种在topic.a.com下的Cookie,并不能使用a.com下种植的SamesiteCookie。这就导致了当我们网站有多个子域名时,不能使用SamesiteCookie在主域名存储用户登录信息。每个子域名都需要用户重新登录一次。
总之,SamesiteCookie是一个可能替代同源验证的方案,但目前还并不成熟,其应用场景有待观望。

3.csrf token方式

通过服务端生成token,给前端,前端请求时,请求头需要加上csrf token键值对

  1. 将CSRF Token输出到页面中,前后端不分离使用
  2. 页面提交的请求携带这个Token
  3. 服务器验证Token是否正确

参考文档

  1. https://tech.meituan.com/2018/10/11/fe-security-csrf.html
  2. https://yiyige.blog.csdn.net/article/details/121032202

xss(cross site script)-跨站脚本攻击

攻击者在页面中插入恶意的javascript代码,当用户浏览网页的时候,嵌入在web里面的javascript代码会执行,进而达到恶意的目的

防护措施

原则

防护XSS攻击其实就记住两条原则:过滤输入和转义输出

  • 在输入方面对所有用户提交内容进行可靠的输入验证,提交内容包括URL、查询关键字、http头、post数据等;
  • 在输出方面,在用户输内容中使用标签,标签内的内容不会解释,直接显示;
  • 严格执行字符输入字数控制;
  • 在脚本执行区中,应绝无用户输入。

浏览器的 X-XSS-Protection

浏览器内置了一个针对XSS攻击的防护机制,这个浏览器内置的防护机制就是所谓的XSS filter,这个防护机制主要用于减轻反射型XSS 攻击带来的危害
至于怎么设置浏览器的XSS防护机制,其实很简单,只要在HTTP响应报文的头部增加一个X-XSS-Protection 字段,明确地告诉浏览器XSS filter/auditor该如何工作。
X-XSS-Protection 的字段有三个可选配置值

  • 0: 表示关闭浏览器的XSS防护机制
  • 1:删除检测到的恶意代码, 如果响应报文中没有看到X-XSS-Protection 字段,那么浏览器就认为X-XSS-Protection配置为1,这是浏览器的默认设置
  • 1; mode=block:如果检测到恶意代码,在不渲染恶意代码(推荐)

X-XSS-Protection (Headers) - HTTP 中文开发手册 - 开发者手册 - 腾讯云开发者社区-腾讯云

参考文档

  1. https://yiyige.blog.csdn.net/article/details/121032202
  2. https://blog.csdn.net/zhongguowangzhan/article/details/104044178

会话固定攻击

会话固定攻击的根源,即在于会话的 sessionid 不变!如果用户在未登录时拿到的是一个 sessionid,登录之后服务端给用户重新换了一个新的 sessionid,就可以防止会话固定攻击了。

防御措施

更改session

在spring security中,提供了三种防御策略

  1. none: 该策略对会话不做任何变动,登录之后会沿用旧的session;(没有起到防护)
  2. migrateSession: 默认策略,用户登录后创建一个新的session,并将旧session中的数据复制过来;(对应实现类**SessionFixationProtectionStrategy**
  3. newSession: 用户登录后会创建一个新的session;(对应实现类**SessionFixationProtectionStrategy**)newSession: 用户登录后会创建一个新的session;(对应实现类**SessionFixationProtectionStrategy**

image.png

  1. changeSessionId: 表示 session 不变,不会创建新的session,但是会修改 sessionid,内部使用由Servlet容器提供的会话固定保护。(对应实现类**ChangeSessionIdAuthenticationStrategy**

image.png

参考

  1. url重写:https://www.cnblogs.com/wonderKK/p/3393490.html
  2. https://yiyige.blog.csdn.net/article/details/120716322

点击劫持

原理

点击劫持是视觉欺骗,用户只看到了底层页面,与页面进行交互时却是与上层页面在交互。这是由于透明的iframe造成的,通过控制iframe的位置,导致上层页面的按钮等覆盖到下层上。
image.png
注:红色按钮(上层页面中的)应该是完全覆盖在黄色按钮(底层页面中的),由于看的不是很清楚,我稍微错位了一下。

示例

<html>
<head>
<title>
来和鹿鸣Lumi互动吧!!!
</title>
<head>
<style>
iframe {
	width: 1440px;
	height: 900px;
	position: absolute;
	top: 30px;
	left: 450px;
	z-index: 2;
	-moz-opacity: 0;
	opacity: 0;
	filter: alpha(opacity=0);
}
</style>
</head>
</head>
<body>
<center>
<div>
<img src="https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1242777858,3501957407&fm=11&gp=0.jpg" height="60%">
<br>
<button>点击进行互动</button>
</div>
</center>
<iframe src="https://blog.csdn.net/lady_killer9" scrolling="no"></iframe>
 
</body>
</html>

opacity为0.5,即上层页面为半透明状态。
image.png
可以看到关注按钮覆盖在了下方的点击进行互动按钮上。
image.png

opacity为0时,此时,上层页面完全无法看见,这时如果你登录csdn后点击"点击进行互动"按钮,就会关注我

防御

前端

一般是通过禁止跨域的iframe来防范,X-Frame-Options HTTP响应头是用来确认是否浏览器可以在frame或iframe标签中渲染一个页面,网站可以用这个头来保证他们的内容不会被嵌入到其它网站中,以来避免点击劫持。

<meta http-equiv="X-FRAME-OPTIONS" content="DENY">

**TIP:在实际项目中使用了,但不起作用,还是推荐通过后端Nginx配置来禁止iframe嵌套 **

DENY:表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。
SAMEORIGIN:表示该页面可以在相同域名页面的 frame 中展示。
ALLOW-FROM uri:表示该页面可以在指定来源的 frame 中展示。

X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM https://example.com/

X-Frame-Options (Headers) - HTTP 中文开发手册 - 开发者手册 - 腾讯云开发者社区-腾讯云

服务器端

nginx

在配置文件的 http 、server 或者 location 中加入如下代码,来防止被嵌套。

add_header X-Frame-Options "SAMEORIGIN";

参考文档

  1. https://blog.csdn.net/qq_31851435/article/details/128369756
  2. https://blog.csdn.net/lady_killer9/article/details/108017437

计时攻击

计时攻击是旁路攻击的一种,在密码学中,旁道攻击又称侧信道攻击、边信道攻击
计时攻击(Timing attack),通过设备运算的用时来推断出所使用的运算操作,或者通过对比运算的时间推定数据位于哪个存储设备,或者利用通信的时间差进行数据窃取。
spring security中耗时的地方主要是 不同加密算法后的 用户输入明文密码和数据库中加密密码比对
1.spring security使用下面的代码进行防御计时攻击
image.png
2.首先方法一进来调用了 prepareTimingAttackProtection 方法,从方法名字上可以看出,这个是为计时攻击的防御做准备
image.png

  1. 接下来调用 loadUserByUsername 方法,根据登录用户传入的用户名去数据库中查询用户,如果查到了,就将查到的对象返回。

如果查询过程中抛出 UsernameNotFoundException 异常,按理说直接抛出异常,接下来的密码比对也不用做了,因为根据用户名都没查到用户,这次登录肯定是失败的,没有必要进行密码比对操作!但是为了防御计时攻击。springsecurity会进行密码比对
这里首先获取到登录用户传入的密码即 presentedPassword,然后调用 passwordEncoder.matches 方法进行密码比对操作,本来该方法的第二个参数是数据库查询出来的用户密码,现在数据库中没有查到用户,所以第二个参数用 userNotFoundEncodedPassword 代替了,userNotFoundEncodedPassword 就是我们一开始调用 prepareTimingAttackProtection 方法时赋值的变量。这个密码比对,从一开始就注定了肯定会失败
image.png

参考文档

  1. https://blog.csdn.net/qq3164069700/article/details/121872535
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值