前言
CSRF(Cross-Site Request Forgery),中文名为跨站请求伪造攻击。这种攻击一般是指攻击者盗用了你的身份信息(比如Cookie),随后用你的身份信息登录了存在此类安全漏洞的重要网站,最后通过你的身份做了一些“合法”的操作,使你蒙受巨大损失。
什么是CSRF漏洞
CSRF(XSRF)全称是Cross-Site Request Forgery跨站请求伪造,你可以这么来理解:攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。
CSRF实现流程
- 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
- 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
- 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
- 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A
- 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
CSRF漏洞危害
例如:
- 修改账户信息
- 利用管理员账号,上传木马文件
- 传播蠕虫病毒(点击、扩散、点击……)
- 和其他攻击手段配合,实现攻击,比如XSS、SQL注入
XSS漏洞危害
- 获取cookie,实现冒充身份的后续操作
- 刷点击
- 弹广告
- 传播蠕虫病毒
CSRF与XSS区别
CSRF:
XSS:
CSRF分类
GET型:
如果一个网站某个地方的功能,比如用户修改邮箱是通过GET请求进行修改的。如:/user.php?id=1&email=123@163.com ,这个链接的意思是用户id=1将邮箱修改为123@163.com。 当我们把这个链接修改为 /user.php?id=1&email=abc@163.com ,然后通过各种手段发送给被攻击者,诱使被攻击者点击我们的链接,当用户刚好在访问这个网站,他同时又点击了这个链接,那么悲剧发生了。这个用户的邮箱被修改为 abc@163.com 了
POST型:
在普通用户的眼中,点击网页->打开试看视频->购买视频是一个很正常的一个流程。可是在攻击者的眼中可以算正常,但又不正常的,当然不正常的情况下,是在开发者安全意识不足所造成的。攻击者在购买处抓到购买时候网站处理购买(扣除)用户余额的地址。比如:/coures/user/handler/25332/buy.php 。通过提交表单,buy.php处理购买的信息,这里的25532为视频ID。那么攻击者现在构造一个链接,链接中包含以下内容。
<form action=/coures/user/handler/25332/buy method=POST>
<input type="text" name="xx" value="xx" />
</form>
<script> document.forms[0].submit(); </script>
当用户点击该链接,访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作,自动购买了id为25332的视频,从而导致受害者余额扣除。
CSRF漏洞案列模拟
接下来我们自己搭建一个靶场来演示一下CSRF漏洞究竟是个什么东西。
可以看到这是一个登录界面:
为了大家能看的更清楚,这是后台数据库中的用户数据:
接下来,我们用用户1100和密码123456去登陆:
如下点击登录后,我们可以看到账户余额有100000人名币:
接下来,我们向用户1101转账1000人名币来测试网站功能是否正常:
看到效果如下图所示,说明网站功能正常:
再来看一下数据库:
可以看到1101用户的账户余额多了1000元。
假设在我们没有关闭这个网页的情况下,我们又打开了恶意一个网站,如下图所示:
我们可以看到这里有一个恶意链接,我们点击他,以模仿那些用户在平时访问恶意网站时一些大家(懂的都懂)的行为:
点击后,出现如下图所示:
这时,因为我们之前的银行转账的网站没有退出,计算机里还保存着银行网站的Cookie信息,我们回到之前的银行网站:
然后我们发现我们的账户余额莫名其妙的少了1000人名币。
我们打开后台的数据库查看,发现我们的钱在没有经过我们1100账户操作的情况下,转给了1102账户1000人名币:
我们想来想去也想不明白这是怎么一回事,回过神,是不是因为我们点了这一个链接的原因呢:
我们再次点击这个链接看一下:
然后回到我们的银行网站,发现我们的钱又少了1000元:
这下我们可以确定了是这个链接的问题,这时问题来了,我们只不过是点了一个链接而已,又没在黄色网站登录用户,他是怎么把我们的钱给转走了呢?
我们来看一下黄色网站前端的源代码:
可以看到黄色页面中有两个img标签,第一个是一张图,而第二个则是一个隐藏的img标签,它调用了银行网站的接口API,只要我们点击了这个链接一次(在我们没有退出银行网站的情况下,浏览器还保存着我们访问银行网站的Cookie信息),我们的钱就会被转到1102账户下1000人名币。
所以到这里为止,这就是一次最简单的CSRF漏洞攻击。
CSRF常用Payload:
我们再来看一些CSRF常用的Payload的代码:
这就是访问bank网站,调取了bank网站的接口信息,恶意执行操作。
这就是构造了一个超链接,调取了bank网站的接口信息,诱惑用户去点击,执行恶意操作。
这里是在恶意网页中设计了一个自动提交的表单,只要我们访问该网页,这个表单就会调取bank网站的接口信息,构造恶意数据,自动提交,在不知不觉中执行恶意操作。
CSRF漏洞挖掘
CSRF漏洞挖掘具体有三个问题:
1、怎么确定一个接口地址有没有CSRF漏洞呢?
2、具体怎么操作?
3、有没有工具可以使用?
检测工具
Burp Suite
CSRF Tester
https://github.com/s0md3v/Bolt
各种云产品
**Burp Suite演示: **
我们进行如上操作,抓包分析:
接下来我们右键,然后进行如下操作:
然后他给我们生成了如下这么一个界面:
他自动生成了这么一串POC,我们把这段POC复制下来:
然后我们构造一个html页面,将复制的代码放进去:
然后我们用浏览器去打开这个html网页:
出现了如图下所示的一个界面:
我们点击这个按钮:
点击前:
点击后:
从上诉的情况可以看出这个网站接口毫无疑问的存在CSRF漏洞。
Bolt 演示:
我们打开这个程序:
我们检测目标页面是否存在CSRF漏洞,执行如下代码:
检测到目标页面存在CSRF漏洞:
CSRF漏洞防御
防御思路
1、我们能不能区分一个请求是来自于自己的前端页面,还是第三方的网站?
2、
怎么让自己的前端页面和伪造的请求变得不一样呢?
我们这里拿一个实际案列演示一下,更方便大家理解:
我们百度搜索左耳朵耗子的博客,点击他:
然后他这里面直接出现了一个警告:
我们通过其他浏览器来访问这个界面:
没有问题。
那么问题来了,他是怎么知道我们是通过百度浏览器来访问他的呢?
其实他这里就是运用了一个Referrer字段来检测的。
HTTP Request Header
我们这里用百度网站随便打开了一个网站,看到Referrer字段如上所示,Referrer字段的作用就是假设我们打开了一个网站或者在网站中执行了跳转到新的网站的操作,而Referrer字段则表示我们是来自哪个网站或者是从哪个网站跳转而来的。
referer的不足:
1、可以任意修改
2、可以为空
我们该如何去防御CSRF漏洞攻击
(1)验证 HTTP Referer 字段
根据 HTTP 协议,在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,比如需要访问 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用户必须先登陆 bank.example,然后通过点击页面上的按钮来触发转账事件。这时,该转帐请求的 Referer 值就会是转账按钮所在的页面的 URL,通常是以 bank.example 域名开头的地址。而如果黑客要对银行网站实施 CSRF 攻击,他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行时,该请求的 Referer 是指向黑客自己的网站。因此,要防御 CSRF 攻击,银行网站只需要对于每一个转账请求验证其 Referer 值,如果是以 bank.example 开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果 Referer 是其他网站的话,则有可能是黑客的 CSRF 攻击,拒绝该请求。
这种方法的显而易见的好处就是简单易行,网站的普通开发人员不需要操心 CSRF 的漏洞,只需要在最后给所有安全敏感的请求统一增加一个拦截器来检查 Referer 的值就可以。特别是对于当前现有的系统,不需要改变当前系统的任何已有代码和逻辑,没有风险,非常便捷。
我们这里拿DVAW-Medium靶场的防御方法来演示,我们来看这个靶场的源码:
他这里是什么意思呢?就是假设说 我的网站ip地址是127.0.0.1,这里去检测对我网站的请求中有没有包含我这个网站的ip值,如果是,那么就表明是在我当前的网站下发起的请求,假如是恶意网站发起的请求的话,那么Referrer字段中是不是就是包含了恶意网站的ip或者域名信息了,那么是不是就不匹配了?所以我们通过以上代码判断用户发起的请求是不是来源于本站的,而不是恶意网站。
然而,这种方法并非万无一失。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个浏览器对于 Referer 的具体实现可能有差别,并不能保证浏览器自身没有安全漏洞。使用验证 Referer 值的方法,就是把安全性都依赖于第三方(即浏览器)来保障,从理论上来讲,这样并不安全。事实上,对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 bank.example 网站支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 bank.example 域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。 即便是使用最新的浏览器,黑客无法篡改 Referer 值,这种方法仍然有问题。因为 Referer 值会记录下用户的访问来源,有些用户认为这样会侵犯到他们自己的隐私权,特别是有些组织担心 Referer 值会把组织内网中的某些信息泄露到外网中。因此,用户自己可以设置浏览器使其在发送请求时不再提供 Referer。当他们正常访问银行网站时,网站会因为请求没有 Referer 值而认为是 CSRF 攻击,拒绝合法用户的访问。
(2)在请求地址中添加 token 并验证token:
在请求中加入一些随机字段(第三方不知道也猜不出来),让第三方网站无法伪造请求
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于 session 之中,然后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来说,要在 form 的最后加上 ,这样就把 token 以参数的形式加入请求了。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。
该方法还有一个缺点是难以保证 token 本身的安全。特别是在一些论坛之类支持用户自己发表内容的网站,黑客可以在上面发布自己个人网站的地址。由于系统也会在这个地址后面加上 token,黑客可以在自己的网站上得到这个 token,并马上就可以发动 CSRF 攻击。为了避免这一点,系统可以在添加 token 的时候增加一个判断,如果这个链接是链到自己本站的,就在后面添加 token,如果是通向外网则不加。不过,即使这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也同样可以通过 Referer 来得到这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的原因。
我们这里拿DVAW-high靶场的防御方法来演示,我们来看这个靶场的源码:
可以看到代码,他这里用了一个叫做token值的东西用来做防御。
验证码:
二次验证:
RECAPTCHA(IP验证):
个人用户建议:
1、不要访问不安全的网站
2、不要随意点开别人发给你的链接
版权归原作者 私ははいしゃ敗者です 所有, 如有侵权,请联系我们删除。