csp

全称: Content-Security-Policy 内容安全策略

是一种通过给浏览器加资源白名单的方式,进行站点保护的手段

可以有效的预防和阻止 类似XSS、运营商劫持之类的攻击

 

 CSP报告

如果你的站点目前还不适合强制使用CSP拦截, 那么可以开启Content-Security-Policy-Report-Only

开启方法如下

在服务端响应时,加入 Content-Security-Policy-Report-Only的头部,

指定规则和report-uri

注: Content-security-policy 规则可以直接在meta头部标签指定, 但是report-uri属性不支持在meta设置

report-uri将接受到一个POST请求

参数JSON包含如下属性

document-uri:发生违规的文档的URI。

referrer:违规发生处的文档引用(地址)。

blocked-uri:被CSP阻止的资源URI。如果被阻止的URI来自不同的源而非文档URI,那么被阻止的资源URI会被删减,仅保留协议,主机和端口号。

violated-directive: 违反的策略名称。

original-policy: 在 Content-Security-Policy HTTP 头部中指明的原始策略。

 

使用

1. nodejs下

利用helmet-csp

范例如下

var express = require('express');
const csp = require('helmet-csp')
var app = express();


app.use(csp({
    // Specify directives as normal.
    directives: {
        defaultSrc: ["'self'", 'default.com'],
        scriptSrc: ["'self'", "'unsafe-inline'"],
        styleSrc: ['style.com'],
        fontSrc: ["'self'", 'fonts.com'],
        imgSrc: ['img.com', 'data:'],
        reportUri: 'http://localhost:9999/api/track/csp-report/group/test',
        objectSrc: ["'none'"],
    },

    // This module will detect common mistakes in your directives and throw errors
    // if it finds any. To disable this, enable "loose mode".
    loose: false,

    // Set to true if you only want browsers to report errors, not block them.
    // You may also set this to a function(req, res) in order to decide dynamically
    // whether to use reportOnly mode, e.g., to allow for a dynamic kill switch.
    reportOnly: true,

    // Set to true if you want to blindly set all headers: Content-Security-Policy,
    // X-WebKit-CSP, and X-Content-Security-Policy.
    setAllHeaders: false,

    // Set to true if you want to disable CSP on Android where it can be buggy.
    disableAndroid: false,

    // Set to false if you want to completely disable any user-agent sniffing.
    // This may make the headers less compatible but it will be much faster.
    // This defaults to `true`.
    browserSniff: true
}))

app.get('/', function (req, res) {
    res.send(`
        <html>
        <head>
             <style>
            body{
                color: red;
            }
            </style>
        </head>
        <body>this is a csp test</body>
        </html>
    `);
});

app.listen(3000, function () {
    console.log('Example app listening on port 3000!');
});

访问localhost:3000,会触发css拦截报告的消息

[Report Only] Refused to apply inline style because it violates the following Content Security Policy directive: "style-src style.com". Either the 'unsafe-inline' keyword, a hash ('sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='), or a nonce ('nonce-...') is required to enable inline execution.

同时发送一条记录到report 服务

服务端需要设置bodyParser.json 支持 application/csp-report格式的数据

 显示结果如下, 样式并不会被影响

2. pathon

def middleware(request, response):
    response['Content-Security-Policy-Report-Only'] = \
        "default-src 'self'; " \
        "report-uri http://locahost:9000/api/track/csp-report/group/test"
    return response