CSP内容安全策略

定义

CSP是一种由浏览器实施的安全机制,其核心目的是减少和防范跨站脚本攻击(XSS)等安全威胁。它通过允许网站管理员定义哪些内容来源是可信任的,从而防止恶意内容的加载和执行。CSP通过HTTP响应头中的Content-Security-Policy字段实现,其核心理念是通过白名单机制来严格限制网页中资源的加载和执行

作用

1、限制资源获取:明确指定哪些外部资源(如脚本、样式表、图片等)可以被加载和执行,有效防止恶意资源的注入。

2、报告资源获取越权:在报告模式下,CSP可以记录违反策略的行为,帮助开发者发现并修复潜在的安全问题,而不影响用户的正常访问。

3、增强用户信任:通过实施CSP,网站可以向用户展示其对安全性的重视,增强用户对网站的信任度。

原理

CSP通过HTTP响应头中的Content-Security-Policy字段向浏览器发送一系列指令,这些指令定义了哪些资源是允许加载和执行的。浏览器在加载和执行资源时,会根据这些指令进行严格的验证,只有符合规则的资源才会被加载和执行。

一句话总结就是服务器通过Content-Security-Policy 响应头告诉浏览器哪些可以执行哪些不能执行,用此方法来网页可以加载的资源和页面,防止XSS攻击

default-src:设置默认加载资源的策略(例如,自身的源、任何地方的源、或者不加载任何外部资源)。
script-src:定义哪些脚本可以执行, 例如script标签, a标签的JavaScript:location.href="" 等.
style-src:定义哪些样式表可以加载。
img-src:定义哪些图片资源可以加载。
connect-src:限制可以通过脚本接口进行连接的URL(例如,AJAX 请求、WebSocket)。
font-src:定义哪些字体资源可以加载。
object-src:限制可以加载哪些插件。
media-src:定义哪些媒体资源(音频和视频)可以加载。
frame-src:定义哪些iframe可以加载。
report-uri:定义接收违反CSP策略报告的URL

配置方式

一、web服务配置示例

response.headers[
        'Content-Security-Policy'] = "default-src 'self'; script-src 'self' https://trustedscripts.com; object-src 'none'; report-uri "

二、nginx配置示例

server {
    add_header Content-Security-Policy "default-src 'self';";
    ...
}

三、HTML配置示例

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://apis.example.com; img-src 'self' https://images.example.com; style-src 'self' 'unsafe-inline';">
    <title>My Secure Page</title>
</head>
<body>
    <!-- 页面内容 -->
</body>
</html>

测试

用python起一个web服务,并构造响应去触发CSP规则

from flask import Flask, jsonify, make_response, request

# 创建一个Flask应用实例
app = Flask(__name__)


# 定义根路由处理函数,当用户访问主页时调用
@app.route('/')
def index():
    # 创建HTML响应内容,包含一些可能会违反CSP规则的元素
    response = make_response("""
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>CSP Test</title>
        </head>
        <body>
            <h1>Hello, World!</h1>
            <!-- 这些标签应该被阻止 -->
            <script src="https://pss.bdstatic.com/static/superman/js/components/tips-e2ceadd14d.js"></script>  <!-- 尝试加载来自不受信任来源的脚本 -->
            <script>alert('This is csp test');</script>                    <!-- 内联JavaScript,通常会被阻止 -->
            <object data="movie.swf" type="application/x-shockwave-flash"></object>  <!-- 尝试加载<object>标签,应该被阻止 -->
            <embed src="movie.swf" type="application/x-shockwave-flash"></embed>     <!-- 尝试加载<embed>标签,应该被阻止 -->
        </body>
        </html>
    """)

    # 设置CSP响应头,定义了哪些资源可以加载
    # default-src 'self':默认情况下,所有资源只能从当前域加载。
    # script-src 'self':允许从当前域和指定的可信域名加载脚本。
    # object-src 'none':禁止加载<object>, <embed>, 和 <applet>标签。
    # report-uri /csp-report-endpoint:当发生CSP违规时,向这个URL发送报告。
    response.headers[
        'Content-Security-Policy'] = "default-src 'self'; script-src 'self' 'unsafe-inline' ; object-src 'none'; report-uri "

    # 返回构建好的HTTP响应给客户端
    return response


# 定义处理CSP违规报告的路由
@app.route('/csp-report-endpoint', methods=['POST'])
def csp_report_endpoint():
    # 打印接收到的CSP违规报告到控制台
    print("CSP violation reported:", request.json)

    # 返回空响应并设置状态码为204 No Content,表示成功接收但无内容返回
    return '', 204


# 如果此文件作为主程序运行,则启动Flask应用
if __name__ == '__main__':
    app.run(debug=True, host='127.0.0.1', port=5005)  # 启动应用,在本地主机上监听端口5005,并开启调试模式

CSP规则如下:

Content-Security-Policy: default-src 'self'; script-src 'self' ; object-src 'none'; report-uri

default-src 'self':只允许加载来自同一来源(即当前网站)的资源。

script-src 'self' 'unsafe-inline':只允许执行来自同一来源的脚本,且允许执行内联脚本例如:<script>alert('This should be blocked');</script> 。

object-src 'none':不允许加载任何来源的对象。

report-uri:当页面违反了CSP规则时,浏览器会将违规详情发送到指定的URI,这可以帮助网站管理员监控和调试CSP规则。

下图可以看到服务器的响应,其中因为配置了unsafe-inline,可以执行内联的JS代码,也就是代码里的<script>alert('This should be blocked');</script>,但是因为https://pss.bdstatic.com/static/superman/js/components/tips-e2ceadd14d.js是没有被允许的所以显示被CSP阻断了,我们尝试把上述外联js代码加入到CSP规则的允许范围

可以看到指定的外联js被成功执行了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值