Content-Security-Policy

介绍:

HTTP 响应头 Content-Security-Policy 允许站点管理者控制用户代理能够为指定的页面加载哪些资源。主要针对js代码的执行,针对xss进行防御,CSP设置参数较多,这里针对常用的参数和内容进行讲解,加深对csp的理解和运用。

常用指令:

指令名demo说明
default-src‘self’ cdn.example.com默认策略,如果某个 fetch 指令在 CSP 头部中未定义,那么浏览器就会寻找default-src 指令的值来替代。

当设置了default-src后会影响以下标签,如果未另行设置则统一按照default-src设置走:

child-src,connect-src,default-src,font-src,frame-src,img-src,manifest-src,media-src,object-src,script-src,style-src,worker-src

script-src‘self’ js.example.com对js代码执行进行过滤设置
style-src‘self’ css.example.com定义css文件的过滤策略
img-src‘self’ img.example.com定义图片文件的过滤策略
connect-src‘self’定义请求连接文件的过滤策略
font-srcfont.example.com定义字体文件的过滤策略
object-src‘self’定义页面插件的过滤策略,如 <object>, <embed> 或者<applet>等元素
media-srcmedia.example.com定义媒体的过滤策略,如 HTML6的 <audio>, <video>等元素
frame-src‘self’定义加载子frmae的策略

指令值:

demo说明
*img-src *允许任意地址的url,但是不包括 blob: filesystem: schemes.
‘none’object-src ‘none’所有地址的咨询都不允许加载
‘self’script-src ‘self’同源策略,即允许同域名同端口下,同协议下的请求
data:img-src ‘self’ data:允许通过data来请求咨询 (比如用Base64 编码过的图片).
domain.example.comimg-src domain.example.com允许特性的域名请求资源
*.example.comimg-src *.example.com允许从 example.com下的任意子域名加载资源
https://cdn.comimg-src https://cdn.com仅仅允许通过https协议来从指定域名下加载资源
https:img-src https:只允许通过https协议加载资源
‘unsafe-inline’script-src ‘unsafe-inline’允许行内代码执行
‘unsafe-eval’script-src ‘unsafe-eval’允许不安全的动态代码执行,比如 JavaScript的 eval()方法

实际使用:

default-src:

再实际使用中如果使用了 default-src,类似如下代码:

<%
    response.setHeader("Content-Security-Policy","default-src 'self'");
%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    hello world!
    <script>
        alert(1);
        console.log(eval('2 + 2'));
    </script>
</body>
</html>

执行后会报错,是因为我们设置了default-src,相当于也设置了script-src为self

所以当我们再设置default-src的时候一定要注意会不会对页面功能造成影响,如果页面功能复杂建议不要设置这个,采用单独设置,当然页面功能简单可以使用。

connect-src:

测试代码如下使用connect-src会影响远程连接:

<a ping="https://not-example.com">
    <script>
        const xhr = new XMLHttpRequest();
        xhr.open("GET", "https://not-example.com/");
        xhr.send();
        const ws = new WebSocket("wss://not-example.com/");
        const ws2 = new EventSource("http://localhost:1234/");
        const es = new EventSource("https://not-example.com/");
        navigator.sendBeacon("https://not-example.com/", {
        });
    </script></a
>

当我们设置为如下:

response.setHeader("Content-Security-Policy","connect-src *"); 
response.setHeader("Content-Security-Policy","connect-src not-example.com");

测试发现使用*可以对任意协议进行访问,但是只能使用对应的网址仅允许http协议。

response.setHeader("Content-Security-Policy","connect-src 'self'");

当使用self,会默认当前url,注意其子域名也不被允许

script-src:

针对script-src这个设置的算是比较多的,也是我们防御中比较重要的,设置这个要配合对页面进行设置:

response.setHeader("Content-Security-Policy","script-src 'self'");

当被设置为了以上模式:下列两种代码均不能执行: 

<script src="https//aaa.localhost:1234/js/library.js"></script>
<button id="btn" οnclick="doSomething()">

 按钮的需要修改为以下代码才可以执行,上述代码会报错。

document.getElementById("btn").addEventListener('click', doSomething);
<%
    response.setHeader("Content-Security-Policy","script-src 'self'");
%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    hello world!
    <script src="http://www.localhost:1234/test.js"></script>
</body>
</html>

js代码:
alert(1);
console.log(eval('2 + 2'));

 执行时可以发现

可以看到虽然设置了self但是对应js代码中的eval是不能执行:

如果是页面中内嵌的script代码,使用self是无法执行,想要执行有两种方法

response.setHeader("Content-Security-Policy","script-src 'nonce-2726c7f26c'");
response.setHeader("Content-Security-Policy","script-src 'sha256-ThXj6yK/lTbpsAsMwOpQuhWzHJkOL99FVjTSwNXadDA='");

页面js代码如下:

    <script nonce="2726c7f26c">
        console.log(eval('2 + 2'));
    </script>

    <script>console.log(eval('4 + 4'));</script>

如果采用sha256则要注意加密的内容,不包含<script>另外要注意空格等特殊符号 

 

当然如果不想这么麻烦,想直接可以运行页面内嵌的脚本可以使用'unsafe-inline'

response.setHeader("Content-Security-Policy","script-src ''unsafe-inline'");

如果要执行eval内容需要添加'unsafe-eval'

response.setHeader("Content-Security-Policy","script-src 'nonce-2726c7f26c' 'sha256-ThXj6yK/lTbpsAsMwOpQuhWzHJkOL99FVjTSwNXadDA=' 'unsafe-eval' ");

如果使用‘none’将会关闭一切js代码执行,即禁止页面执行任何js代码,外部内联均禁止

总结:

        首先是对执行来源的控制,使用'self'或自己设置可以保证访问或来源的数据是安全的。

        然后就是对js代码执行的控制,使用中最安全的为使用sha256对代码进行计算后,虽然这样可以保证仅会执行固定的代码,但是不适用于比较复杂逻辑的系统,使用nonce-***,这种可以保证我们允许执行的js空间是可控的,如果其他标签未过滤导致了xss也无法执行,但是要保证每次返回的数字为一个随机数据,不能被预测,否则攻击者可以拼接预测的结果执行js,导致xss,最后就是使用'unsafe-inline',使用参数则相当于关闭了对页面js执行的控制,这样使用csp意义就不大了,最后就是视情况使用'unsafe-eval'。

插件:

在工作中可以使用插件CSP Evaluator,在浏览器应用商店下载,下载完成后,访问页面的时候可以显示其csp设置是否安全:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值