codicastudio / csp
一个随机的 Codica Studio 包。
Requires
- php: ^7.4
- illuminate/http: ^8.0
- illuminate/support: ^8.0
Requires (Dev)
- mockery/mockery: ^1.3.1
- orchestra/testbench: ^6.0
- phpunit/phpunit: ^9.3
README
默认情况下,网页上的所有脚本都被允许向任何网站发送和获取数据。这可能会成为安全问题。想象一下,你的一个 JavaScript 依赖项将所有的按键,包括密码,发送到第三方网站。
安装
您可以通过 composer 安装此软件包
composer require codicastudio/csp
您可以使用以下命令发布配置文件
php artisan vendor:publish --provider="codicastudio\csp\cspServiceProvider" --tag="config"
此文件内容将被发布到 config/csp.php
return [ /* * A policy will determine which CSP headers will be set. A valid CSP policy is * any class that extends `codicastudio\csp\Policies\Policy` */ 'policy' => codicastudio\csp\Policies\Basic::class, /* * This policy which will be put in report only mode. This is great for testing out * a new policy or changes to existing csp policy without breaking anything. */ 'report_only_policy' => '', /* * All violations against the policy will be reported to this url. * A great service you could use for this is https://report-uri.com/ * * You can override this setting by calling `reportTo` on your policy. */ 'report_uri' => env('CSP_REPORT_URI', ''), /* * Headers will only be added if this setting is set to true. */ 'enabled' => env('CSP_ENABLED', true), /* * The class responsible for generating the nonces used in inline tags and headers. */ 'nonce_generator' => codicastudio\csp\Nonce\RandomString::class, ];
您可以通过在 http 核心中注册 codicastudio\csp\AddcspHeaders::class
来添加 CSP 标头到您应用程序的所有响应中。
// app/Http/Kernel.php ... protected $middlewareGroups = [ 'web' => [ ... \codicastudio\csp\AddcspHeaders::class, ],
或者,您可以在路由或路由组级别应用中间件。
// in a routes file Route::get('my-page', 'MyController')->middleware(codicastudio\csp\AddcspHeaders::class);
您还可以将策略类作为参数传递给中间件
// in a routes file Route::get('my-page', 'MyController')->middleware(codicastudio\csp\AddcspHeaders::class . ':' . MyPolicy::class);
提供的策略将覆盖配置文件中为特定路由或路由组配置的策略。
使用方法
此软件包允许您定义 CSP 策略。CSP 策略确定将设置在响应头中的哪些 CSP 指令。
一个 CSP 指令的示例是 script-src
。如果此值为 'self' www.google.com
,则您的网站只能从其自身域名或 www.google.com
加载脚本。您可以在 Mozilla 优秀的开发者网站上找到所有 CSP 指令的列表。
根据规范,某些指令值需要用引号括起来。这些示例包括 'self'
、'none'
和 'unsafe-inline'
。当使用 addDirective
函数时,您无需手动将指令值用引号括起来。我们将自动添加引号。脚本/样式哈希也将自动检测并括起来。
// in a policy ... ->addDirective(Directive::SCRIPT, Keyword::SELF) // will output `'self'` when outputting headers ->addDirective(Directive::STYLE, 'sha256-hash') // will output `'sha256-hash'` when outputting headers ...
您可以在同一指令中添加多个策略选项,将数组作为 addDirective
的第二个参数,或者将每个选项用一个或多个空格分隔的单个字符串。
// in a policy ... ->addDirective(Directive::SCRIPT, [ Keyword::STRICT_DYNAMIC, Keyword::SELF, 'www.google.com', ]) ->addDirective(Directive::SCRIPT, 'strict-dynamic self www.google.com') // will both output `'strict_dynamic' 'self' www.google.com` when outputting headers ...
也有几种情况,您不需要或不需要指定值,例如 upgrade-insecure-requests、block-all-mixed-content 等。在这种情况下,您可以使用以下值
// in a policy ... ->addDirective(Directive::UPGRADE_INSECURE_REQUESTS, Value::NO_VALUE) ->addDirective(Directive::BLOCK_ALL_MIXED_CONTENT, Value::NO_VALUE); ...
这将输出以下 CSP
Content-Security-Policy: upgrade-insecure-requests;block-all-mixed-content
创建策略
默认情况下,在 csp
配置文件的 policy
键中设置为 \codicastudio\csp\Policies\Basic::class
。此类允许您的网站仅使用自身站点的图片、脚本和表单操作。这个类看起来是这样的。
namespace codicastudio\csp\Policies; use codicastudio\csp\Directive; use codicastudio\csp\Value; class Basic extends Policy { public function configure() { $this ->addDirective(Directive::BASE, Keyword::SELF) ->addDirective(Directive::CONNECT, Keyword::SELF) ->addDirective(Directive::DEFAULT, Keyword::SELF) ->addDirective(Directive::FORM_ACTION, Keyword::SELF) ->addDirective(Directive::IMG, Keyword::SELF) ->addDirective(Directive::MEDIA, Keyword::SELF) ->addDirective(Directive::OBJECT, Keyword::NONE) ->addDirective(Directive::SCRIPT, Keyword::SELF) ->addDirective(Directive::STYLE, Keyword::SELF) ->addNonceForDirective(Directive::SCRIPT) ->addNonceForDirective(Directive::STYLE); } }
您可以通过扩展此类允许从 www.google.com
获取脚本
namespace App\Services\csp\Policies; use codicastudio\csp\Directive; use codicastudio\csp\Policies\Basic; class MyCustomPolicy extends Basic { public function configure() { parent::configure(); $this->addDirective(Directive::SCRIPT, 'www.google.com'); } }
别忘了将 csp
配置文件中的 policy
键设置为策略类的名称(在这种情况下,将是 App\Services\csp\Policies\MyCustomPolicy
)。
使用内联脚本和样式
当使用 CSP 时,您必须明确允许使用内联脚本或样式。使用此软件包推荐的方式是通过使用 nonce
。nonce 是每个请求都是唯一的数字。nonce 必须在 CSP 头部和 html 标签的属性中指定。这样,攻击者就没有注入恶意脚本或样式的途径。
首先,您必须将 nonce 添加到策略中的正确指令
// in a policy public function configure() { $this ->addDirective(Directive::SCRIPT, 'self') ->addDirective(Directive::STYLE, 'self') ->addNonceForDirective(Directive::SCRIPT) ->addNonceForDirective(Directive::STYLE) ... }
然后,您必须将 nonce 添加到 html 中
{{-- in a view --}}
<style nonce="{{ csp_nonce() }}">
...
</style>
<script nonce="{{ csp_nonce() }}">
...
</script>
还有一些其他选项可以用于内联样式和脚本。请查看Mozilla 开发者网站上关于 CSP 的文档以获取更多信息。
报告 CSP 错误
在浏览器中
您不必完全阻止所有违规行为,可以将策略设置为仅报告模式。在这种情况下,所有请求都将执行,但所有违规行为都会显示在您最喜欢的浏览器的控制台中。
要将策略设置为仅报告模式,只需在报告的 configure()
函数中调用 reportOnly()
即可。
public function configure() { parent::configure(); $this->reportOnly(); }
到外部URL。
违反策略的任何违规行为都可以报告给指定的URL。您可以在 csp
配置文件的 report_uri
键中设置该URL。一个专为处理这些违规报告而构建的出色服务是 http://report-uri.io/。
使用多个策略
要测试对您的CSP策略的更改,您可以在 csp
配置键中的 report_only_policy
中指定第二个策略。在 policy
中指定的策略将被强制执行,而在 report_only_policy
中的策略则不会。这对于在不破坏任何内容的情况下测试新策略或现有CSP策略的更改非常出色。
使用whoops
Laravel附带了一个名为 whoops 的错误处理框架,它可以帮助您通过异常的精美可视化来调试您的应用程序。由于whoops无法对其使用环境做出任何假设,因此它使用内联脚本和样式,所以除非您允许脚本和样式的 unsafe-inline
,否则它将不起作用。
解决这个问题的一种方法是在设置策略时检查 config('app.debug')
。遗憾的是,这存在忘记在所有CSP规则启用的情况下测试您的代码,以及在部署时应用程序崩溃的风险。作为替代方案,您可以通过向异常处理程序的 render
方法(通常在 app/Exceptions/Handler.php
中)添加以下内容,只允许错误页面上的 unsafe-inline
:
$this->container->singleton(AppPolicy::class, function ($app) { return new AppPolicy(); }); app(AppPolicy::class)->addDirective(Directive::SCRIPT, Keyword::UNSAFE_INLINE); app(AppPolicy::class)->addDirective(Directive::STYLE, Keyword::UNSAFE_INLINE);
其中 AppPolicy
是您的CSP策略的名称。这也适用于其他所有情况,在这些情况下,应在服务提供者而不是异常处理器中完成单例注册。
请注意,unsafe-inline
仅在您没有同时发送nonce或 strict-dynamic
指令的情况下才有效,因此要能够使用此工作区,您必须指定所有内联脚本和样式的哈希值,并将其放在CSP头中。
测试
您可以使用以下命令运行所有测试:
composer test
变更日志
有关最近更改的更多信息,请参阅 变更日志。
许可证
MIT许可证(MIT)。有关更多信息,请参阅 许可证文件。