一个随机的 Codica Studio 包。

2.6.2 2020-10-18 21:04 UTC

This package is auto-updated.

Last update: 2024-09-21 00:14:21 UTC


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)。有关更多信息,请参阅 许可证文件