跳到內容

NelmioSecurityBundle

編輯此頁面

NelmioSecurityBundle 為您的 Symfony 應用程式提供額外的安全性功能。

安裝

在您的 composer.json 中要求 nelmio/security-bundle 套件,並更新您的依賴項

1
$ composer require nelmio/security-bundle

此套件應由 Symfony Flex 自動啟用。如果您不使用 Flex,您需要手動啟用此套件,方法是在您專案的 config/bundles.php 檔案中加入以下程式碼行

1
2
3
4
5
6
7
8
<?php
// config/bundles.php

return [
    // ...
    Nelmio\SecurityBundle\NelmioSecurityBundle::class => ['all' => true],
    // ...
];

如果您的專案中沒有 config/bundles.php 檔案,則您可能正在使用較舊的 Symfony 版本。在這種情況下,您應該改為擁有 app/AppKernel.php 檔案。編輯該檔案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = [
            // ...

            new Nelmio\SecurityBundle\NelmioSecurityBundle(),
        ];

        // ...
    }

    // ...
}

功能

  • 內容安全策略:跨站腳本攻擊 (XSS) 可以在現代瀏覽器中使用策略來緩解,該策略指示瀏覽器永遠不要執行內聯腳本,或永遠不要從與頁面網域不同的網域載入內容。
  • 簽署 Cookie:指定要簽署的特定 Cookie,以便使用者無法修改它們。請注意,它們不會被加密,而只會被簽署。內容仍然對使用者可見。
  • 點擊劫持保護X-Frame-Options 標頭已新增至所有回應,以防止您的網站被放入框架/iframe 中。這可能會造成嚴重的安全隱患,正如 Facebook 和其他公司一次又一次地證明的那樣。您可以允許從網站本身或從任何地方以每個 URL 為基礎框架您的網站。
  • 外部重新導向偵測:根據使用者輸入將您的網站重新導向到任意 URL 可能會被利用,以混淆使用者點擊看似指向有效網站的連結,但實際上這些連結會將他們導向惡意內容。也可能藉此方式獲得 PageRank。
  • 強制 HTTPS/SSL 處理:這會強制所有請求都通過 SSL。它還會傳送 HSTS 標頭,以便支援它的現代瀏覽器可以讓使用者即使輸入不含 https 的 URL 也使用 HTTPS,從而避免在公共 Wi-Fi 上受到攻擊。
  • 彈性 HTTPS/SSL 處理:如果您不想強制所有使用者都使用 HTTPS,您至少應該對已登入的使用者使用安全的工作階段 Cookie 並強制 SSL。但是,當已登入的使用者存取非 HTTPS 資源時,他們會顯示為已登出。這不是一個很好的解決方案。這將使應用程式偵測已登入的使用者並將他們重新導向到安全 URL,而不會使工作階段 Cookie 不安全。
  • 停用內容類型嗅探:要求使用正確的 mime 類型載入腳本。這會停用某些瀏覽器具有的功能,這些瀏覽器使用內容嗅探來判斷回應是否為有效的腳本檔案。
  • (已棄用) XSS 保護:在相容的瀏覽器 (IE 8 及更新版本) 上啟用/停用 Microsoft XSS 保護。
  • Referrer PolicyReferrer-Policy 標頭已新增至所有回應,以控制從您的網站發出的請求以及瀏覽器從您的網站導航出去時新增的 Referer 標頭。

最高安全性設定

這是提供最高安全性保護的設定,但您應該繼續閱讀下一節以取得詳細的建議

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# config/packages/nelmio_security.yaml
nelmio_security:
    # signs/verifies all cookies
    signed_cookie:
        names: ['*']
    # prevents framing of the entire site
    clickjacking:
        paths:
            '^/.*': DENY
        hosts:
            - '^foo\.com$'
            - '\.example\.org$'

    # prevents redirections outside the website's domain
    external_redirects:
        abort: true
        log: true

    # prevents inline scripts, unsafe eval, external scripts/images/styles/frames, etc
    csp:
        hosts: []
        content_types: []
        enforce:
            level1_fallback: false
            browser_adaptive:
                enabled: false
            report-uri: '%router.request_context.base_url%/nelmio/csp/report'
            default-src:
                - 'none'
            script-src:
                - 'self'
            block-all-mixed-content: true # defaults to false, blocks HTTP content over HTTPS transport
            # upgrade-insecure-requests: true # defaults to false, upgrades HTTP requests to HTTPS transport

    # disables content type sniffing for script resources
    content_type:
        nosniff: true

    # Send a full URL in the ``Referer`` header when performing a same-origin request,
    # only send the origin of the document to secure destination (HTTPS->HTTPS),
    # and send no header to a less secure destination (HTTPS->HTTP).
    # If ``strict-origin-when-cross-origin`` is not supported, use ``no-referrer`` policy,
    # no referrer information is sent along with requests.
    referrer_policy:
        enabled: true
        policies:
            - 'no-referrer'
            - 'strict-origin-when-cross-origin'

    # forces HTTPS handling, don't combine with flexible mode
    # and make sure you have SSL working on your site before enabling this
#    forced_ssl:
#        hsts_max_age: 2592000 # 30 days
#        hsts_subdomains: true
#        redirect_status_code: 302 # default, switch to 301 for permanent redirects

    # flexible HTTPS handling, read the detailed config info
    # and make sure you have SSL working on your site before enabling this
#    flexible_ssl:
#        cookie_name: auth
#        unsecured_logout: false

內容安全策略

使用 CSP,您可以設定現代瀏覽器理解並將遵守的策略。該策略包含許多不同的指令;default-srcscript-srcobject-srcstyle-srcimg-srcmedia-srcframe-srcfont-srcconnect-srcbase-urichild-srcform-actionframe-ancestorsplugin-typesblock-all-mixed-contentupgrade-insecure-requestsreport-urimanifest-src

您可以為每個內容類型提供指令陣列,但 block-all-mixed-contentupgrade-insecure-requests 除外,它們僅接受布林值。空的內容類型將從 default-src 繼承,指定的內容類型永遠不會從 default-src 繼承。詳細資訊請參閱內容安全策略 1.0內容安全策略 2.0 規範。

每個指令都應該是網域、URI 或關鍵字。關鍵字 'self' 將允許來自與頁面相同來源的內容。如果您需要允許內聯腳本或 eval(),您可以使用 'unsafe-inline''unsafe-eval'

注意

透過使用 'unsafe-inline''unsafe-eval',您實際上是在停用 CSP 的 XSS 保護機制。

除了內容類型之外,該策略也接受 report-uri,它應該是一個 URI,瀏覽器可以在策略指令被違反時將 JSON payload POST 到該 URI。從 v3.5 開始,也可以包含 report-to 指令來設定報告端點 (請參閱 Reporting API),其目的是取代已棄用的 report-uri 指令。

可選的 content_types 金鑰可讓您僅在某些 HTTP 回應上根據其內容類型限制內容安全策略標頭。

最後,可選的 hosts 金鑰可讓您設定應在哪些主機名稱 (例如 foo.example.org) 上強制執行 CSP 規則。如果列表為空 (預設情況下為空),則所有主機名稱都將使用 CSP 規則。

如果 content_typeshosts 選項不符合您的需求,您也可以將實作 Symfony\Component\HttpFoundation\RequestMatcherInterface 的服務設定為 request_matcher。然後 content_typeshosts 選項將不再使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        enabled: true
        report_logger_service: logger
        request_matcher: null
        hosts: []
        content_types: []
        enforce:
            # see full description below
            level1_fallback: true
            # only send directives supported by the browser, defaults to false
            # this is a port of https://github.com/twitter/secureheaders/blob/83a564a235c8be1a8a3901373dbc769da32f6ed7/lib/secure_headers/headers/policy_management.rb#L97
            browser_adaptive:
                enabled: false
            report-uri: '%router.request_context.base_url%/nelmio/csp/report'
            default-src: [ 'self' ]
            frame-src: [ 'https://www.youtube.com' ]
            script-src:
                - 'self'
                - 'unsafe-inline'
            img-src:
                - 'self'
                - facebook.com
                - flickr.com
            block-all-mixed-content: true # defaults to false, blocks HTTP content over HTTPS transport
            # upgrade-insecure-requests: true # defaults to false, upgrades HTTP requests to HTTPS transport
        report:
            # see full description below
            level1_fallback: true
            # only send directives supported by the browser, defaults to false
            # this is a port of https://github.com/twitter/secureheaders/blob/83a564a235c8be1a8a3901373dbc769da32f6ed7/lib/secure_headers/headers/policy_management.rb#L97
            browser_adaptive:
                enabled: true
            report-uri: '%router.request_context.base_url%/nelmio/csp/report'
            script-src:
                - 'self'

上述設定將強制執行以下策略

  • 預設是允許來自與頁面相同來源
  • 框架僅來自安全的 YouTube 連線
  • JavaScript 來自相同來源以及來自內聯 <script> 標籤
  • 圖像來自相同來源、facebook.com 和 flickr.com

任何違反強制策略的行為都將發佈到 /nelmio/csp/report

此外,該設定僅報告但不強制執行 JavaScript 只能在來自同一伺服器時執行的策略。

此套件提供預設的報告實作,將違規記錄為預設記錄器的通知,若要啟用,請將以下內容新增至您的 routing.yml

1
2
3
4
5
# config/routing.yaml
nelmio_security:
    path:     /nelmio/csp/report
    defaults: { _controller: nelmio_security.csp_reporter_controller::indexAction }
    methods:  [POST]

(可選) 使用 report_logger_service 記錄到 'security' 頻道

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        report_logger_service: monolog.logger.security

(可選) 停用 compat_headers 以避免傳送 X-Content-Security-Policy (IE10、IE11、Firefox < 23)。這表示這些瀏覽器將不會收到任何 CSP 指令。

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        compat_headers: false

使用瀏覽器自適應指令

NelmioSecurityBundle 可以設定為僅傳送瀏覽器可以理解的指令。這減少了透過報告 URI 提供的雜訊。這是 Twitter SecureHeaders library 中所做工作的直接移植。

使用 enabled 金鑰啟用它

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        enforce:
            browser_adaptive:
                enabled: true

注意

這將解析使用者代理程式,並可能消耗一些 CPU 使用率。您可以指定快取解析器以避免消耗過多 CPU

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        enforce:
            browser_adaptive:
                enabled: true
                parser: my_own_parser

並根據 NelmioSecurityBundle 提供的快取解析器之一或您自己的快取解析器宣告服務 my_own_parser。例如,使用 PsrCacheUAFamilyParser

1
2
3
4
5
<service id="my_own_parser" class="Nelmio\SecurityBundle\UserAgent\UAFamilyParser\PsrCacheUAFamilyParser">
  <argument type="service" id="app.my_cache.pool"/>
  <argument type="service" id="nelmio_security.ua_parser.ua_php"/>
  <argument>604800</argument>
</service>

請查看 Nelmio\SecurityBundle\UserAgent\UAFamilyParser 以取得這些解析器。

用於處理內聯腳本的消息摘要

如果您想在 script-srcstyle-src 上停用 'unsafe-inline' (建議),Nelmio Security Bundle 開箱即用,具有消息摘要功能。Twig 原生支援此功能。

您可以在設定中設定用於消息摘要的演算法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        hash:
            algorithm: sha512 # default is sha256, available are sha256, sha384 and sha512
        enforce:
            # Provides compatibility with CSP level 1 (old / non-yet-compatible browsers) when using CSP level 2
            # features likes hash and nonce. It adds a 'unsafe-inline' source to a directive whenever a nonce or hash
            # is used.
            # From RFC: " If 'unsafe-inline' is not in the list of allowed style sources, or if at least one
            #             nonce-source or hash-source is present in the list of allowed style sources "
            # See https://www.w3.org/TR/CSP2/#directive-style-src and https://www.w3.org/TR/CSP2/#directive-script-src
            level1_fallback: true
            default-src: ['self']

在您的 Twig 範本中,使用 cspscriptcspstyle 標籤自動計算消息摘要並將其插入到您的標頭中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% cspscript %}
<script>
    window.api_key = '{{ api_key }}';
</script>
{% endcspscript %}

{# ... #}

{% cspstyle %}
<style>
    body {
        background-color: '{{ bgColor }}';
    }
</style>
{% endcspstyle %}

如果您未使用 Twig,則可以使用 ContentSecurityPolicyListener 的消息摘要,它將自動計算消息摘要並將其新增至回應 CSP 標頭

1
2
3
4
5
6
7
8
9
10
$listener->addScript("<script>
    window.api_key = '{{ api_key }}';
</script>");


$listener->addStyle("<style>
    body {
        background-color: '{{ bgColor }}';
    }
</style>");

用於處理內聯腳本的 Nonce

內容安全策略規範也提出了用於內聯的 nonce 實作。Nelmio Security Bundle 開箱即用,具有 nonce 功能。Twig 原生支援此功能。

在您的 Twig 範本中,使用 csp_nonce 函數存取目前請求的 nonce 並將其新增至回應 CSP 標頭。如果您未請求 nonce,則不會產生 nonce。

1
2
3
4
5
6
7
8
9
10
11
<script nonce="{{ csp_nonce('script') }}">
    window.api_key = '{{ api_key }}';
</script>

{# ... #}

<style nonce="{{ csp_nonce('style') }}">
    body {
        background-color: '{{ bgColor }}';
    }
</style>

如果您未使用 Twig,則可以使用 ContentSecurityPolicyListener 的 nonce 功能

1
2
3
4
// generates a nonce at first time, returns the same nonce once generated
$listener->getNonce('script');
// or
$listener->getNonce('style');

報告

使用 report-uri,您可以輕鬆地使用 ContentSecurityPolicyController 收集違規。以下是使用 routing.yml 的設定範例

1
2
3
4
5
# config/routes.yaml
csp_report:
    path: /csp/report
    methods: [POST]
    defaults: { _controller: nelmio_security.csp_reporter_controller::indexAction }

設定的這部分有助於過濾由此端點收集的雜訊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# config/packages/nelmio_security.yaml
nelmio_security:
    csp:
        report_endpoint:
            log_level: "notice" # Use the appropriate log_level
            log_formatter: ~    # Declare a service name that must implement Nelmio\SecurityBundle\ContentSecurityPolicy\Violation\Log\LogFormatterInterface
            log_channel: ~      # Declare the channel to use with the logger
            filters:
                # Filter false positive reports given a domain list
                domains: true
                # Filter false positive reports given a scheme list
                schemes: true
                # Filter false positive reports given known browser bugs
                browser_bugs: true
                # Filter false positive reports given known injected scripts
                injected_scripts: true
                # You can add you custom filter rules by implementing Nelmio\SecurityBundle\ContentSecurityPolicy\Violation\Filter\NoiseDetectorInterface
                # and tag the service with "nelmio_security.csp_report_filter"
            dismiss:
                # A list of key-values that should be dismissed
                # A key is either a domain or a regular expression
                # A value is a source or an array of source. The '*' wilcard is accepted
                '/^data:/': 'script-src'
                '/^https?:\/\/\d+\.\d+\.\d+\.\d+(:\d+)*/': '*'
                'maxcdn.bootstrapcdn.com': '*'
                'www.gstatic.com': ['media-src', 'img-src']

簽署 Cookie

理想情況下,您應該明確指定要簽署哪些 Cookie。原因很簡單。Cookie 會隨每個請求傳送。簽名通常比 Cookie 值本身長,因此簽署所有內容只會不必要地減慢您的應用程式速度並增加使用者的頻寬使用量。

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    signed_cookie:
        names: [test1, test2]

但是,為了簡單起見,並從高安全性開始並在稍後進行最佳化,您可以將 * 指定為 Cookie 名稱,以自動簽署所有 Cookie。

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    signed_cookie:
        names: ['*']

其他可選設定

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    signed_cookie:
        secret: this_is_very_secret # defaults to global %secret% parameter
        hash_algo: sha512 # defaults to sha256, see ``hash_algos()`` for available algorithms

升級雜湊演算法

隨著計算能力和安全性研究的進步,升級到更安全的雜湊演算法對於維護應用程式安全性至關重要。但是,僅僅變更 `hash_algo` 值可能會破壞現有的 Cookie。為了方便順利轉換,此套件提供了 `legacy_hash_algo` 選項。如果您的應用程式目前使用 `sha-256`,並且您希望升級到更安全的 `sha3-256` 演算法,請將 `legacy_hash_algo` 設定為 `sha256`,並將 `hash_algo` 設定為 `sha3-256`

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    signed_cookie:
        hash_algo: sha3-256
        legacy_hash_algo: sha256

注意

`legacy_hash_algo` 選項可能會使您的應用程式暴露於降級攻擊,並且僅應暫時用於向後相容性。

點擊劫持保護

大多數網站不使用框架,也不需要可框架化。這是一種常見的攻擊媒介,目前所有瀏覽器 (IE8+、Opera10.5+、Safari4+、Chrome4+ 和 Firefox3.7+) 都有解決方案。您的網站傳送的額外標頭會告知瀏覽器它無法在框架中顯示。瀏覽器會透過顯示簡短說明而不是內容,或顯示空白頁面來做出反應。

X-Frame-Options 標頭的有效值為 DENY (防止來自所有頁面的框架) 和 SAMEORIGIN (防止來自非同網域的所有頁面的框架)。此外,如果您想允許一些 URL,然後拒絕其他所有內容,則此套件還支援 ALLOW 選項,該選項會跳過為符合的 URL 建立標頭。

還有一個選項 (目前尚不完全支援),是使用 ALLOW-FROM uri,其中 uri 可以是任何原始 URL,從 example.orghttps://example.org:123/sub/path。如果您有多網域設定,這可讓您精確指定哪個網域可以嵌入您的網站。

預設設定 (拒絕所有內容)

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    clickjacking:
        paths:
            '^/.*': DENY
        content_types: []
        hosts: []

允許清單設定 (拒絕所有內容,但允許少數 URL)

1
2
3
4
5
6
7
8
9
10
# config/packages/nelmio_security.yaml
nelmio_security:
    clickjacking:
        paths:
            '^/iframes/': ALLOW
            '^/business/': 'ALLOW-FROM https://biz.example.org'
            '^/local/': SAMEORIGIN
            '^/.*': DENY
        content_types: []
        hosts: []

套用至特定主機

1
2
3
4
5
6
7
8
9
10
# config/packages/nelmio_security.yaml
nelmio_security:
    clickjacking:
        paths:
            '^/iframes/': ALLOW
            '^/.*': DENY
        content_types: []
        hosts:
            - '^foo\.com$'
            - '\.example\.org$'

您當然也可以只拒絕一些關鍵 URL,而讓其餘 URL 不受影響

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    clickjacking:
        paths:
            '^/message/write': DENY
        content_types: []
        hosts: []

可選的 content_types 金鑰可讓您僅在某些 HTTP 回應上根據其內容類型限制 X-Frame-Options 標頭。

外部重新導向偵測

此功能可協助您偵測並防止重新導向到外部網站。如果您不小心將查詢參數作為重新導向目標,則很容易意外發生這種情況。

您可以透過開啟記錄功能來記錄這些 (以警告級別記錄)

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        log: true

您可以中止 (它們會被 403 回應取代) 重新導向

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        abort: true

或者您可以覆寫它們,將重新導向的 Location 標頭替換為路由名稱或另一個 URL

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        # redirect to the 'home' route
        override: home
        # use this to redirect to another URL
        # override: /foo

如果您想要在覆寫頁面上顯示被封鎖的 URL,您可以指定 forward_as 參數,此參數定義哪個查詢參數將接收 URL。例如,使用以下配置,將重新導向到 http://example.org/ 的操作將被覆寫為 /external-redirect?redirUrl=http://example.org/

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        # redirect and forward the overridden URL
        override: /external-redirect
        forward_as: redirUrl

由於網站常常會有需要導向外部網站的正當理由,通常像是 OAuth 登入等等,您可以允許幾個網域名稱。它們的所有子網域也都會被允許,因此如果需要,您可以允許您自己網站的子網域。

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        abort: true
        allow_list:
            - twitter.com
            - facebook.com

如果您有一個可以重新導向到另一個主機的控制器,您也可以使用 `ExternalRedirectResponse` 來允許重新導向,而無需全域配置主機。傳遞給 `ExternalRedirectResponse` 的任何主機都會加到已全域配置的主機之外。

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    external_redirects:
        abort: true
        allow_list:
            - bar.com
1
2
3
4
5
6
7
8
9
10
use Nelmio\SecurityBundle\ExternalRedirect\ExternalRedirectResponse;

// Will be allowed even though "foo.com" is not allowed globally through the config.
return new ExternalRedirectResponse('https://foo.com', ['foo.com', 'auth-provider.test']);

// Will not be allowed.
return new ExternalRedirectResponse('https://not-allowed.com', ['foo.com', 'auth-provider.test']);

// Will be allowed because "bar.com" is allowed globally through the config.
return new ExternalRedirectResponse('https://bar.com', ['foo.com', 'auth-provider.test']);

強制 HTTPS/SSL 處理

預設情況下,此選項會強制您的整個網站始終使用 SSL。它會將所有透過 http:// URL 連線到網站的使用者重新導向到 https:// URL,並使用 302 回應。

此功能的基本配置如下

1
2
3
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl: ~

如果您開啟此選項,建議您也將您的 session cookie 設定為安全,以及您傳送的所有其他 cookie。您可以使用以下方式進行前者

1
2
3
4
# config/packages/framework.yaml
framework:
    session:
        cookie_secure: true

若要防止某些 URL 被強制重新導向到 SSL,您可以定義一個允許的正規表示式清單

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl:
        enabled: true
        allow_list:
            - ^/unsecure/

若要將強制重新導向限制為僅限某些主機名稱,您可以定義主機名稱清單作為正規表示式

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl:
        enabled: true
        hosts:
            - ^\.example\.org$

若要變更重新導向的方式,例如變更為永久重新導向,您可以設定

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl:
        enabled: true
        redirect_status_code: 301

然後,如果您想要更進一步,您可以啟用 HTTP 嚴格傳輸安全協議 (HSTS)。這基本上是傳送一個標頭來告知瀏覽器您的網站必須始終使用 SSL 存取。如果使用者輸入 http:// URL,瀏覽器會自動將其轉換為 https://,並且會在發出任何請求之前執行此操作,這可以防止中間人攻擊。

瀏覽器會快取該值,時間長度為指定的 hsts_max_age(以秒為單位),如果您開啟 hsts_subdomains 選項,則該行為也將應用於所有子網域。

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl:
        hsts_max_age: 2592000 # 30 days
        hsts_subdomains: true

您也可以透過啟用 hsts_preload 來告知瀏覽器將您的網站新增到已知的 HSTS 網站清單中。一旦您的網站出現在 Chrome 和 Firefox 預載清單中,那麼訪問您網站的新使用者將已經被重新導向到 HTTPS URL。

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    forced_ssl:
        hsts_max_age: 31536000 # 1 year
        hsts_preload: true

注意

目前 Chrome 要求 至少 1 年的值,Firefox 也要求hsts_subdomains 也必須啟用預載才能運作。

您可以將您的網站提交到 HSTS 預載清單,以加速加入過程。

一個小小的警告:雖然 HSTS 對於安全性很有幫助,但這意味著如果瀏覽器無法驗證您的 SSL 憑證是否有效,它將不允許使用者查詢您的網站。這只是意味著您應該小心並及時更新您的憑證。

提示

請查看 Can I use HSTS? 以取得有關其在瀏覽器中支援的完整資訊。

彈性 HTTPS/SSL 處理

安全地處理 SSL 的最佳方法是為您的整個網站啟用它。

然而,在某些情況下,這並不受歡迎,無論是出於快取或效能原因,或者僅僅是因為您網站的大多數訪客都是匿名的,並且從 SSL 增加的隱私和安全性中受益不多。

如果您不想全面啟用 SSL,您需要避免不安全網路(通常是開放 Wi-Fi)上的人們透過未加密的方式傳送會話 cookie 而導致其被盜用。實現此目的的方法是將您的會話 cookie 設定為安全 - 但現在還不要這樣做,請繼續閱讀到最後。

1
2
3
4
# config/packages/framework.yaml
framework:
    session:
        cookie_secure: true

如果您使用「記住我」功能,您也應該將其標記為安全

1
2
3
4
5
6
# config/packages/security.yaml
security:
    firewalls:
        somename:
            remember_me:
                secure: true

現在,如果您這樣做,您會遇到兩個問題。首先,不安全的頁面將無法再使用會話,這可能會很不方便。其次,如果已登入的使用者進入您網站的非 HTTPS 頁面,則會被視為匿名,因為他的瀏覽器不會傳送會話 cookie。為了修正這個問題,這個套件會設定一個新的不安全 cookie(flexible_ssl.cookie_name,預設為 auth),一旦使用者登入。這樣一來,如果任何頁面被已登入的使用者以不安全的方式存取,他將被重新導向到該頁面的安全版本,並且他的會話隨後對框架可見。

啟用 NelmioSecurityBundle 的 flexible_ssl 選項將確保已登入的使用者始終看到安全頁面,並且它將確保他們的會話 cookie 是安全的,但如果您需要使用它來儲存非關鍵資料(例如語言設定等等),匿名使用者仍然可以使用不安全的會話。「記住我」cookie 也將始終設為安全,即使您將設定保留為 false 也是如此。

1
2
3
4
5
# config/packages/nelmio_security.yaml
nelmio_security:
    flexible_ssl:
        cookie_name: auth
        unsecured_logout: false

您還必須在您的安全性配置中配置一件事:每個防火牆都應該新增我們的登出監聽器,以便在使用者登出時可以清除特殊的 auth cookie。您可以這樣做

1
2
3
4
5
6
7
8
# config/packages/security.yaml
security:
    firewalls:
        somename:
            # ...
            logout:
                handlers:
                    - nelmio_security.flexible_ssl_listener

在登出時,如果您希望使用者被重新導向到不安全的頁面,請將 unsecured_logout 設定為 true。

內容類型嗅探

停用腳本資源的內容類型嗅探。強制瀏覽器僅執行具有有效內容類型標頭的腳本檔案。這需要使用 來自 Microsoft 的非標準 nosniff 標頭

1
2
3
4
# config/packages/nelmio_security.yaml
nelmio_security:
    content_type:
        nosniff: true

XSS 保護 (已棄用)

注意

此功能是非標準且已棄用的。建議改用 CSP:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection

在相容的瀏覽器上啟用或停用 Microsoft XSS 保護。這需要使用 來自 Microsoft 的非標準 X-XSS-Protection 標頭

1
2
3
4
5
6
# config/packages/nelmio_security.yaml
nelmio_security:
    xss_protection:
        enabled: true
        mode_block: true
        report_uri: '%router.request_context.base_url%/nelmio/xss/report'

Referrer Policy

新增 Referrer-Policy 標頭以控制從您的網站發出的請求以及瀏覽器導航離開您的網站時新增的 Referer 標頭。

您可以指定多個 referrer policies。策略的順序很重要。瀏覽器只會選擇它們理解的最後一個策略。例如,舊版瀏覽器不理解 strict-origin-when-cross-origin 策略。網站可以指定 no-referrer 策略,然後是 strict-origin-when-cross-origin 策略:舊版瀏覽器會忽略未知的 strict-origin-when-cross-origin 值並使用 no-referrer,而新版瀏覽器將使用 strict-origin-when-cross-origin,因為它是最後一個被處理的策略。

以下是有效的 referrer policies

為了提高您網站的安全性,請使用 no-referrersame-originstrict-originstrict-origin-when-cross-origin

1
2
3
4
5
6
7
# config/packages/nelmio_security.yaml
nelmio_security:
    referrer_policy:
        enabled: true
        policies:
            - 'no-referrer'
            - 'strict-origin-when-cross-origin'
本作品,包括程式碼範例,均根據 Creative Commons BY-SA 3.0 授權條款授權。
目錄
    版本