CSRF攻击详解

一、csrf简介
Cross-site request forgery,跨站请求伪造,通常缩写为CSRF或者XSRF。

下面get和post请求攻击的前提都是假设网站A存在csrf漏洞以及用户已登录网站A。

二、csrf之get请求攻击
发起get请求攻击比较简单,只需通过img标签即可。

因为受同源策略限制,不能通过ajax来发起get请求。

  1. Demo验证

代码:

// src的值就是网站A下的get请求

    
    csrf之get请求攻击


 

效果:
用户打开攻击者网站B,自动发起get请求,状态码是200表示成功:

通过抓包详细查看,请求带上了cookie登录态,响应也是正常的:

三、csrf之post请求攻击
相比之下,get请求的危害没有post请求伤害大,但想要发起post请求攻击,就没那么容易实现。

首先我们知道,在网站B是不能通过ajax发起网站A的post请求的,因为同源策略限制了。
但需要注意的是,同源策略只是限制了XMLHttpRequest和Fetch API,但html的form标签则不受同源策略限制。同样,上面get请求的img标签也不受同源策略。

  1. 正常form表单验证

代码:


    
    csrf-post



    

效果:

结论:
很明显请求是不成功的。但能把网站A的登录态带过去,所以算是成功了一部分。
对比网站A下的post请求,发现数据格式不一样。
上图的是Form Data,网站A的是Request Payload,如下图所示:

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

  1. text/plain的form表单再次验证

代码:

// 在上面的代码的基础上,把form标签新增enctype属性即可


效果:

结论:
成功将数据格式改为Request Payload了,但为啥接口依然报错?
再仔细对比下网站A的正常请求,可发现网站A那边是JSON格式,但我们这边不是JSON,就是纯文本加换行的一个格式,这样肯定不会成功的。

分析:
那有什么好办法?只能继续对form表单的参数进行深入挖掘了。
form表单的参数就是input标签等的name和value组成的一些列参数,那可否只用一个input来把所有参数都拼接起来?

经过多次验证,是可以拼接的。

  1. 再次验证form的参数

代码:

// 在上面的代码的基础上,把input改为如下所示:


效果:

结论:
成功了!

  1. 补充说明

1 数据格式如果不是Request payload,而是Form Data,则可直接用form表单来发请求,不用再增加上面2和3的方法。一、csrf简介

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

下面get和post请求攻击的前提都是假设网站A存在csrf漏洞以及用户已登录网站A。

二、csrf之get请求攻击

发起get请求攻击比较简单,只需通过img标签即可。

因为受同源策略限制,不能通过ajax来发起get请求。

1. Demo验证

代码:

// src的值就是网站A下的get请求

    
    csrf之get请求攻击


    

效果:
用户打开攻击者网站B,自动发起get请求,状态码是200表示成功:
CSRF攻击详解_第1张图片

通过抓包详细查看,请求带上了cookie登录态,响应也是正常的:
CSRF攻击详解_第2张图片

三、csrf之post请求攻击

相比之下,get请求的危害没有post请求伤害大,但想要发起post请求攻击,就没那么容易实现。

首先我们知道,在网站B是不能通过ajax发起网站A的post请求的,因为同源策略限制了。
但需要注意的是,同源策略只是限制了XMLHttpRequest和Fetch API,但html的form标签则不受同源策略限制。同样,上面get请求的img标签也不受同源策略。

1. 正常form表单验证

代码:


    
    csrf-post



    

效果:
CSRF攻击详解_第3张图片

结论:
很明显请求是不成功的。但能把网站A的登录态带过去,所以算是成功了一部分。
对比网站A下的post请求,发现数据格式不一样。
上图的是Form Data,网站A的是Request Payload,如下图所示:
CSRF攻击详解_第4张图片

分析:
form请求的数据格式跟enctype属性有关系,默认的是application/x-www-form-urlencoded,此时就是Form Data
编码类型总共三种(参考),还有两种是:multipart/form-datatext/plain
前者是上传文件用的,后者用的比较少。但正是通过text/plain来将数据格式改为Request Payload

2. text/plain的form表单再次验证

代码:

// 在上面的代码的基础上,把form标签新增enctype属性即可

效果:
CSRF攻击详解_第5张图片

结论:
成功将数据格式改为Request Payload了,但为啥接口依然报错?
再仔细对比下网站A的正常请求,可发现网站A那边是JSON格式,但我们这边不是JSON,就是纯文本加换行的一个格式,这样肯定不会成功的。

分析:
那有什么好办法?只能继续对form表单的参数进行深入挖掘了。
form表单的参数就是input标签等的name和value组成的一些列参数,那可否只用一个input来把所有参数都拼接起来?

经过多次验证,是可以拼接的。

3. 再次验证form的参数

代码:

// 在上面的代码的基础上,把input改为如下所示:

    

效果:
CSRF攻击详解_第6张图片

结论:
成功了!

4. 补充说明

1 数据格式如果不是Request payload,而是Form Data,则可直接用form表单来发请求,不用再增加上面2和3的方法。

你可能感兴趣的:(xss前端csrf安全)