martijnc / php-csp
PHP 内容安全策略助手
Requires
- php: >=5.4.0
This package is not auto-updated.
Last update: 2024-07-20 15:21:43 UTC
README
A PHP helper class to dynamically construct Content Security Policy headers as defined by the W3C in the Content Security Policy specification (http://www.w3.org/TR/CSP2/).
如何使用
将 php-csp
添加到您的项目中,创建一个 ContentSecurityPolicyHeaderBuilder
类的实例,并使用它来设置您的CSP策略。一旦策略完成,使用 ContentSecurityPolicyHeaderBuilder::getHeaders()
获取您的CSP头。
use Phpcsp\Security\ContentSecurityPolicyHeaderBuilder; $policy = new ContentSecurityPolicyHeaderBuilder(); // Set the script-src directive to 'none' $policy->addSourceExpression(ContentSecurityPolicyHeaderBuilder::DIRECTIVE_SCRIPT_SRC, 'none'); // Enable the browsers xss blocking features $policy->setReflectedXssPolicy(ContentSecurityPolicyHeaderBuilder::REFLECTED_XSS_BLOCK); // Set a report URL $policy->setReportUri('https://example.com/csp/report.php'); // Get your CSP headers $headers = $policy->getHeaders(false);
ContentSecurityPolicy::getHeaders()
返回一个您应该发送的HTTP头数组。对于上面的示例,这将得到以下数组
array (size=1)
0 =>
array (size=2)
'name' => string 'Content-Security-Policy' (length=23)
'value' => string 'script-src 'none'; reflected-xss block; report-uri https://example.com/csp/report.php;' (length=86)
源表达式
此类的最直接用途是通过添加您选择的源到指令,例如在这个例子中
use Phpcsp\Security\ContentSecurityPolicyHeaderBuilder; $policy = new ContentSecurityPolicyHeaderBuilder(); // Set the default-src directive to 'none' $policy->addSourceExpression(ContentSecurityPolicyHeaderBuilder::DIRECTIVE_DEFAULT_SRC, 'none'); // Add a single origin for the script-src directive $policy->addSourceExpression(ContentSecurityPolicyHeaderBuilder::DIRECTIVE_SCRIPT_SRC, 'https://example.com/scripts/'); // Add a single origin for the style-src directive $policy->addSourceExpression(ContentSecurityPolicyHeaderBuilder::DIRECTIVE_STYLE_SRC, 'https://example.com/style/'); foreach ($policy->getHeaders(true) as $header) { header(sprintf('%s: %s', $header['name'], $header['value'])); }
此示例将输出以下头
array (size=1)
0 =>
array (size=2)
'name' => string 'Content-Security-Policy' (length=23)
'value' => string 'default-src 'none'; script-src https://example.com/scripts/; style-src https://example.com/style/;' (length=98)
源集
您可以定义源集并将它们链接到您想要的任何CSP指令。例如
use Phpcsp\Security\ContentSecurityPolicyHeaderBuilder; $policy = new ContentSecurityPolicyHeaderBuilder(); // Set the default-src directive to 'none' $policy->addSourceExpression(ContentSecurityPolicyHeaderBuilder::DIRECTIVE_DEFAULT_SRC, 'none'); // Define two source sets $policy->defineSourceSet('my-scripts-cdn', [ 'https://cdn-scripts1.example.com/scripts/', 'https://cdn-scripts2.example.com/scripts/' ]); $policy->defineSourceSet('my-style-cdn', [ 'https://cdn-style1.example.com/css/', 'https://cdn-style2.example.com/css/' ]); // Add both to a directive $policy->addSourceSet(ContentSecurityPolicyHeaderBuilder::DIRECTIVE_SCRIPT_SRC, 'my-scripts-cdn'); $policy->addSourceSet(ContentSecurityPolicyHeaderBuilder::DIRECTIVE_STYLE_SRC, 'my-style-cdn'); $headers = $policy->getHeaders(false);
将导致以下头
array (size=1)
0 =>
array (size=2)
'name' => string 'Content-Security-Policy' (length=23)
'value' => string 'default-src 'none'; script-src https://cdn-scripts1.example.com/scripts/ https://cdn-scripts2.example.com/scripts/; style-src https://cdn-style1.example.com/css/ https://cdn-style2.example.com/css/;' (length=198)
非ces
CSP阻止内联脚本,但可以通过将unsafe-inline
添加到script-src
指令来再次启用它们。这样做将违背使用CSP的整个目的,因此不推荐使用unsafe-inline
。如果您出于任何原因需要内联脚本,应使用非ces。非ces是您添加到script-src
指令和您网页上允许的内联脚本标签的随机字符串,如下例所示
use Phpcsp\Security\ContentSecurityPolicyHeaderBuilder; $policy = new ContentSecurityPolicyHeaderBuilder(); // Set the default-src directive to 'none' $policy->addSourceExpression(ContentSecurityPolicyHeaderBuilder::DIRECTIVE_DEFAULT_SRC, 'none'); $myScriptNonce = 'thisShouldBeRandom'; // Add the nonce to the script-src directive $policy->addNonce(ContentSecurityPolicyHeaderBuilder::DIRECTIVE_SCRIPT_SRC, $myScriptNonce); foreach ($policy->getHeaders(true) as $header) { header(sprintf('%s: %s', $header['name'], $header['value'])); }
将导致以下头
array (size=1)
0 =>
array (size=2)
'name' => string 'Content-Security-Policy' (length=23)
'value' => string 'default-src 'none'; script-src 'nonce-thisShouldBeRandom';' (length=58)
您的HTML应如下所示
<script>
// This would be blocked because it has no nonce
</script>
<script nonce="thisIsAWrongNonce">
// This would be blocked because the nonce is invalid
</script>
<script nonce="thisShouldBeRandom">
// This would work fine
</script>
非ces应针对每个请求是随机的,这样攻击者就无法预测非ces值。
哈希
如果您的应用程序需要内联脚本,您可以将源的SHA256、SHA384或SHA512哈希作为策略中script-src
指令的一部分来提供,以允许脚本运行。这样您就不需要启用unsafe-inline
。
违规报告
CSP为您提供接收CSP违规报告的选项。每次页面加载被您的CSP策略阻止的资源时,浏览器都会将一个JSON对象提交到您在策略中指定的URL。在以下示例中,这些报告将发送到https://example.com/csp/report.php
use Phpcsp\Security\ContentSecurityPolicyHeaderBuilder; $policy = new ContentSecurityPolicyHeaderBuilder(); // Set the script-src directive to 'none' $policy->addSourceExpression(ContentSecurityPolicyHeaderBuilder::DIRECTIVE_SCRIPT_SRC, 'https://example.com/scripts/'); // Set a report URL $policy->setReportUri('https://example.com/csp/report.php');
您还可以使用仅报告模式下的CSP。此模式适用于您在现有网站上实施CSP而不会破坏网站的情况。每次资源加载违反您的CSP策略时,浏览器都会发送违规报告,但实际上不会阻止资源。
// Set a report URL $policy->setReportUri('https://example.com/csp/report.php'); // Use report only mode $policy->enforcePolicy(false);
旧版头支持
此类还提供对一些被CSP取代的旧版头的支持。目前它支持X-XSS-Protection
和X-Frame-Options
头。
use Phpcsp\Security\ContentSecurityPolicyHeaderBuilder; $policy = new ContentSecurityPolicyHeaderBuilder(); // Enable the browsers xss blocking features $policy->setReflectedXssPolicy(ContentSecurityPolicyHeaderBuilder::REFLECTED_XSS_BLOCK); // Set the 'X-Frame-Options' header $policy->setFrameOptions(ContentSecurityPolicyHeaderBuilder::FRAME_OPTION_SAME_ORIGIN); // Get your CSP headers, including legacy headers $headers = $policy->getHeaders(true); foreach ($headers as $header) { header(sprintf('%s: %s', $header['name'], $header['value'])); }
这将导致以下头
array (size=3)
0 =>
array (size=2)
'name' => string 'Content-Security-Policy' (length=23)
'value' => string 'script-src 'none'; reflected-xss block; report-uri https://example.com/csp/report.php;' (length=86)
1 =>
array (size=2)
'name' => string 'X-XSS-Protection' (length=16)
'value' => string '1; mode=block' (length=13)
2 =>
array (size=2)
'name' => string 'X-Frame-Options' (length=15)
'value' => string 'SAMEORIGIN' (length=10)