文章目录
简介
CSRF(Cross-site request forgery)跨站请求伪造
:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
一个典型的CSRF攻击有着如下的流程:
- 受害者登录a.com,并保留了登录认证信息(会话令牌、Cookie)。
- 攻击者引诱受害者访问了b.com。
- b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的会话令牌、Cookie。
- a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
- a.com以受害者的名义执行了act=xx。
- 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。
举例
假设有一个银行网站(a.com
),该网站允许用户通过发送HTTP请求来转账。正常情况下,用户登录到自己的银行账户后,通过填写转账表单(包括收款人账户、转账金额等信息)并提交,银行服务器会验证用户的身份和请求信息,并执行相应的转账操作。
然而,如果一个恶意网站或攻击者构造了一个包含恶意代码的页面,当受害者访问该页面(b.com
)时,恶意代码会自动发送一个伪造的转账请求到银行网站。由于受害者已经登录到银行网站,浏览器会自动携带受害者的认证信息(如会话令牌、Cookie等)一起发送到银行服务器。银行服务器接收到请求后,由于携带了有效的认证信息,会误以为是受害者本人发起的请求,并执行转账操作。
举个例子,攻击者可以在恶意页面中嵌入一个隐藏的表单,表单的action属性设置为银行网站的转账接口,同时表单中包含伪造的转账信息(如收款人账户为攻击者的账户,转账金额为较大数额)。当受害者访问该恶意页面时,浏览器会自动提交该表单,导致受害者的资金被转移到攻击者的账户中。
常见的攻击类型
GET类型的CSRF
GET类型的CSRF利用非常简单,只需要一个HTTP请求,一般会这样利用:
<img src="http://bank.example/withdraw?amount=10000&for=hacker" >
在受害者访问含有这个img的页面后,浏览器会自动向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker
发出一次HTTP请求。bank.example就会收到包含受害者登录信息的一次跨域请求。
⚡️form表单类型的CSRF
这种类型的CSRF通常利用的是自动提交表单,如:
<form action="http://bank.example/withdraw" method=POST>
<input type="hidden" name="account" value="xiaoming" />
<input type="hidden" name="amount" value="10000" />
<input type="hidden" name="for" value="hacker" />
</form>
<script> document.forms[0].submit(); </script>
访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作。
链接类型的CSRF
链接类型的CSRF并不常见,比起其他两种用户打开页面就中招的情况,这种需要用户点击链接才会触发。这种类型通常是在论坛中发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:
<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
重磅消息!!
<a/>
由于之前用户登录了信任的网站A,并且保存登录状态,只要用户主动访问上面的这个PHP页面,则表示攻击成功。
CSRF的特点
-
利用用户信任:CSRF攻击依赖于用户对网站的信任。攻击者利用这种信任,伪装成合法用户的请求,执行未经授权的操作。
-
伪造用户请求:攻击者通过伪造用户请求,如修改设置、发布信息或执行其他敏感操作,以达到攻击目的。这些请求看似来自用户本人,因此能够绕过同源策略等安全机制。
-
多种攻击方式:CSRF攻击可以通过多种方式实现,包括利用图片请求、自动提交的表单、AJAX请求等。攻击者还可以利用第三方网站的漏洞,如XSS漏洞,来执行CSRF攻击。
-
数据泄露与非法操作:CSRF攻击可能导致用户数据泄露,如账户密码、信用卡信息等,从而造成隐私泄露和财产损失。此外,攻击者还可以利用CSRF攻击对受信任的网站进行非法操作,如篡改数据、发布虚假信息等,给企业或个人带来损失。
-
难以察觉:由于CSRF攻击通常发生在用户不知情的情况下,用户很难察觉到攻击的发生。这使得CSRF攻击成为一种隐蔽且高效的攻击方式。
注意:
- 攻击一般发起
在第三方网站
,而不是被攻击的网站。被攻击的网站无法防止攻击发生。 - 攻击
利用受害者在被攻击网站的登录凭证,冒充受害者提交操作
;而不是直接窃取数据。 - 整个过程攻击者
并不能获取到受害者的登录凭证,仅仅是“冒用”
。 - 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。
CSRF通常是跨域的,因为外域通常更容易被攻击者掌控。但是如果本域下有容易被利用的功能,比如可以发图和链接的论坛和评论区,攻击可以直接在本域下进行,而且这种攻击更加危险。
CSRF攻击并不直接违反同源策略,因为它利用了受害者的浏览器,而浏览器已经与银行网站建立了会话(例如,通过Cookie)。当受害者访问恶意网站时,恶意网站上的脚本可以构造一个表单或者发起一个AJAX请求(如果使用了一些技术来绕过同源策略,如JSONP),这个请求会被浏览器发送到银行网站,并且浏览器会自动附带上之前与银行网站建立的会话信息(如Cookie)。这样,即使请求是从恶意网站发起的,它仍然看起来像是由受害者本人在银行网站上执行的合法请求。
⚡️防护策略
CSRF通常从第三方网站发起,被攻击的网站无法防止攻击发生,只能通过增强自己网站针对CSRF的防护能力来提升安全性。
为了防止CSRF攻击,可以采取以下措施:
1. 验证请求的来源:
确保请求是从合法的网站或应用程序发出的,服务器可以检查请求头中的Origin
或Referer
字段,来验证请求是否来自合法的源。
然而,这两个字段都可以被伪造,因此它们通常只作为辅助手段,而不是主要的防御措施。
.
2. ⚡️使用CSRF令牌(CSRF Token)
这是防止CSRF攻击最常用和有效的方法。
-
服务器端生成和验证令牌
在服务器端,你需要在用户登录或创建会话时生成一个随机的CSRF令牌,并将其存储在用户的会话中。
然后,每次处理敏感请求时,都需要验证请求中是否包含了正确的令牌。 -
客户端包含令牌
在客户端,你需要在渲染表单时将CSRF令牌作为隐藏字段包含在内。
这样,当表单提交时,令牌会自动包含在请求中。<form method="post" action="/transfer"> <!-- 其他表单字段... --> <input type="hidden" name="csrf_token" value="{{ csrf_token }}"> <button type="submit">转账</button> </form>
.
3. ⚡️设置安全的Cookie属性
服务器在响应头中设置Cookie的HttpOnly
、Secure
、Samesite
属性
-
HttpOnly属性:可以防止客户端脚本(如JavaScript)访问Cookie,从而降低跨站脚本攻击(XSS) 的风险(不能直接防止CSRF攻击)。
-
Secure属性:确保Cookie只能通过HTTPS协议传输,这有助于防止Cookie在不安全的网络中被截获。
-
Samesite属性:用来标明这个cookie是否是“同站cookie”。同站cookie只能在本域名中使用,不能作为第三方cookie, 限制第三方Cookie,从而帮助减少安全风险
在Java Servlet中,你可以使用Cookie类的构造函数和setMaxAge(), setPath(), setSecure(), setHttpOnly()方法来设置Cookie:
Cookie cookie = new Cookie("cookieName", "cookieValue");
cookie.setMaxAge(60 * 60 * 24); // 设置有效期为30天
cookie.setSecure(true); // 设置Secure属性:仅通过HTTPS传输
cookie.setHttpOnly(true); // 设置HttpOnly属性:防止JavaScript访问
cookie.setSameSite("Strict"); // 设置SameSite属性为Strict
response.addCookie(cookie); // 将Cookie添加到响应中
这样当服务器响应客户端请求时,就会在HTTP响应头中包含这些设置了属性的Cookie。
.
4. 限制敏感操作的频率和权限
对于涉及资金转账、密码修改等敏感操作,可以设置限制条件,如:
- 需要二次确认
- 验证码验证