跨站请求伪造,由客户端发起,是一种劫持受信任用户向服务器发送非预期请求的攻击方式,与XSS相似,但比XSS更难防范,常与XSS一起配合攻击
攻击者盗用了你的身份信息,以你的名义发送恶意请求,对服务器来说这个请求是你发起的,却完成了攻击者所期望的一个操作
修改用户信息,修改密码,以你的名义发送邮件、发消息、盗取你的账号等
实体 | 对象 |
---|---|
用户 | User Q |
存在CSRF漏洞的网站 | Web A |
攻击者构造的恶意网站 | Web B |
主:浏览器cookie不过期,不关闭浏览器或退出登录,都会默认为已登录状态
次:对请求合法性验证不严格
抓取正常请求的数据包,如果不存在token验证,去掉请求头中Referer字段再重新提交,如果服务器返回正常页面,基本可以确定存在CSRF漏洞
1.同源策略
同源策略规定了不同源的javascript脚本在没有明确授权的情况下,不能读写对象的资源
同源:同协议、同域名、同端口
2.内容安全策略CSP策略
基于同源策略,所有资源需来自同一个源,但是会带来诸多限制,限制了资源必须在同服务器上,所以浏览器允许页面嵌入第三方资源,同时带来的安全问题由CSP机制解决,让服务器决定浏览器能够加载哪些资源,从而限制其任意下载第三方资源。
3.跨域资源共享CORS策略
基于同源策略,浏览器默认不允许XMLHttpRequest对象访问非同一站点下的资源,而CORS机制使我们能安全的跨域访问资源,实现CORS通信的关键是服务器,只要服务器实现了CORS接口,就可以跨源通信。
4.Cookie策略
Session Cookie:临时Cookie,不指定过期时间
Third-party-Cookie:本地Cookie,可指定过期时间
两者的区别在于“Third-party-Cookie”是服务器在set-Cookie时指定了Expire时间,只有到了Expire时间后Cookie才会失效,所以这种Cookie会保存在本地;而Session Cookie没有指定Expire时间,所以浏览器关闭后,Session Cookie就失效了。
如果浏览器从一个域页面加载另一个域的资源,由于安全原因,某些浏览器会阻止Third-party Cookie的发送。
img标签不受同源策略的限制,使用img标签的src属性产生的跨域请求被浏览器认为是合法请求,诱导用户点击链接产生攻击
<img src="http://www.hack.com?money=1000&from=sam&to=john" />
为什么说CSRF没有获取cookie,却能利用cookie进行攻击?
攻击者的网站虽然是跨域的,但是他构造的链接是源网站的,因为源网站存在CSRF,构造的链接跟源网站同源,所以浏览器自动携带cookie发起访问
Low级别没有做任何预防CSRF的机制
构造攻击页面,并诱骗受害者访问达到修改密码的目的
<!DOCTYPE html> <html> <head> <title>CSRF</title> </head> <img src="http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=hack&password_conf=hack&Change=Change#" border="0" style="display:none;"/> <h1>404<h1> <h2>file not found.<h2> <body> </body> </html>
访问此页面后,用户误认为点击了一个404页面,其实密码已修改为hack
Medium级别对Referer字段做了校验,检查referer是否与主机名SERVER_NAME一致,使用stripos函数从referer字段里查找主机名,如果找到则可以修改密码
<?php if( isset( $_GET[ 'Change' ] ) ) { // Checks to see where the request came from if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) { ...... ...... ?>
只需要在Low级别基础上把攻击页面命名为127.0.0.1.html再访问链接即可修改密码
http://127.0.0.1/dvwa/127.0.0.1.html
High级别验证了token,而token令牌为随机值,无法猜解
<?php if( isset( $_GET[ 'Change' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); ...... ...... // Generate Anti-CSRF token generateSessionToken(); ?>
要绕过token验证,关键要获取到token值,在本地环境可以实现High级别CSRF,在实战环境涉及到跨域问题,域名不同,浏览器不允许跨域请求,由于跨域是不能实现的,所以我们要将攻击代码注入到目标服务器中,才有可能完成攻击。
1.验证HTTP Referer字段
referer字段表明了请求来源,通过在服务器端添加对请求头字段的验证拒绝一切跨站请求,但是请求头可以绕过,XHR对象通过setRequestHeader方法可以伪造请求头
2.添加token验证
客户端令牌token通常作为一种身份标识,由服务器端生成的一串字符串,当第一次登录后,服务器生成一个token返回给客户端,以后客户端只需带上token来请求数据即可,无需再次带上用户名和密码。如果来自浏览器请求中的token值与服务器发送给用户的token不匹配,或者请求中token不存在,则拒绝该请求,使用token验证可以有效防止CSRF攻击,但增加了后端数据处理的工作量
3.验证码
发送请求前需要输入基于服务端判断的验证码,机制与token类似,验证码强制用户与web完成交互后才能实现正常请求,最简洁而有效的方法,但影响用户体验
4.设置cookie的same-site属性
在 HTTP 的响应头中,same-site 有两种值:strict或lax。当 设置为 strict 时,表示该服务器发送的 cookie 值不允许附带在第三方请求中;当设置为lax 时,表示如果请求类型为同步请求且请求方式为 GET,则允许此 cookie 作为请求头的附带信息。将 same-site 的值设为 strict 可破坏产生 CSRF 攻击的必要条件。
关于CSRF漏洞有太多分支,包括浏览器安全策略的内部机制原理,CSRF配合XSS攻击方法,CSRF与XSS的区别,跨域解决方案等等