舞台裏

Qiita が表でこっちが裏。こっそりやっていく。

Strict-Transport-Security を試した

HTTP Strict-Transport-Security の動作について実際に動かして試した。

HTTPS 通信の検証については、 Payara (GlassFish) を使っていればデフォルトで 8181 ポートにアクセスすれば HTTPS で通信できるので、それを利用(証明書の作成とかインポートとか面倒な作業が不要なので動作確認に便利)。

最初、 http 始まりでブックマークしてる URL とかも気を利かせて https にしてくれるのかなぁと思っていたが、そうではなかった。 あくまで、プロトコルを省略してアクセスしようとした場合の、デフォルトのプロトコルが HTTP から HTTPS になるって話だった。

ちなみにはてなブログは HTTP 通信なのでこのヘッダーはついていない。

X-Frame-Options の変更を試した

デフォルトだとレスポンスヘッダーに

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

がついていることを確認。

この中でも特に X-Frame-Options の動きを確認。

Tomcat の webapps に test フォルダを追加、↓のような index.html ファイルを追加して http://localhost:8080/test/ にアクセス。

<html>
  <head>
  </head>
  <body>
    <iframe src="http://localhost:8080/namespace/" style="width: 500px; height: 500px;"></iframe>
  </body>
</html>

f:id:opengl-8080:20170414232339j:plain

こんなエラーが出て、 <iframe> からは参照できないようになっている。

これを、ポリシーに SAMEORIGIN を設定したらどうなるか見る。

namespace

    <sec:http>
        ...
        <sec:headers>
            <sec:frame-options policy="DENY" />
        </sec:headers>
    </sec:http>

Java Configuration

        http.authorizeRequests()
                ...
                .and()
                .headers().frameOptions().sameOrigin();

f:id:opengl-8080:20170414232709j:plain

オリジンが同じなので <iframe> 上で見れるようになった。

20.2.3 DelegatingRequestMatcherHeaderWriter

20.2.3 DelegatingRequestMatcherHeaderWriter

At times you may want to only write a header for certain requests.

ときどき、あなたは一定のリクエストでだけヘッダーを書きたいと思うことでしょう。

For example, perhaps you want to only protect your log in page from being framed.

例えば、あなたはフレーム化されたログインページだけを守りたいと思うとします。

You could use the DelegatingRequestMatcherHeaderWriter to do so.

あなたは DelegatingRequestMatcherHeaderWriter を使うことでそれができます。

When using the XML namespace configuration, this can be done with the following:

XML namespace configuration を使っている場合は、次のようにすることで実現できます。

<http>
    <!-- ... -->

    <headers>
        <frame-options disabled="true"/>
        <header ref="headerWriter"/>
    </headers>
</http>

<beans:bean id="headerWriter"
    class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
    <beans:constructor-arg>
        <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"
            c:pattern="/login"/>
    </beans:constructor-arg>
    <beans:constructor-arg>
        <beans:bean
            class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"/>
    </beans:constructor-arg>
</beans:bean>

We could also prevent framing of content to the log in page using java configuration:

私たちは、 Java Configuration を使ってログインページのコンテンツをフレーム化することを防ぐこともできます。

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    RequestMatcher matcher = new AntPathRequestMatcher("/login");
    DelegatingRequestMatcherHeaderWriter headerWriter =
        new DelegatingRequestMatcherHeaderWriter(matcher,new XFrameOptionsHeaderWriter());
    http
    // ...
    .headers()
        .frameOptions().disabled()
        .addHeaderWriter(headerWriter);
}
}

20.2.2 Headers Writer

20.2.2 Headers Writer

When the namespace or Java configuration does not support the headers you want, you can create a custom HeadersWriter instance or even provide a custom implementation of the HeadersWriter.

namespace か Java Configuration がサポートしていないヘッダーが必要となった場合は、カスタムの HeaderWriter インスタンスを生成するか、カスタムの実装を提供することができます。

Let’s take a look at an example of using an custom instance of XFrameOptionsHeaderWriter.

XFrameOptionsHeaderWriter のカスタムインスタンスを使用する例を見てみましょう。

Perhaps you want to allow framing of content for the same origin.

おそらく、あなたは同じオリジンでのコンテンツのフレームかを許可したいと思うでしょう。

This is easily supported by setting the policy attribute to “SAMEORIGIN”, but let’s take a look at a more explicit example using the ref attribute.

これは、 “SAMEORIGIN” をポリシーの属性にセットすることで簡単にサポートされています。 しかし、 ref 属性を使用したより明示的な例を見てください。

<http>
    <!-- ... -->

    <headers>
        <header ref="frameOptionsWriter"/>
    </headers>
</http>
<!-- Requires the c-namespace.
See http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-c-namespace
-->
<beans:bean id="frameOptionsWriter"
    class="org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter"
    c:frameOptionsMode="SAMEORIGIN"/>

We could also restrict framing of content to the same origin with Java configuration:

私たちは、 Java Configuration で同じオリジンでコンテンツをフレーム化することを制限することもできます。

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    // ...
    .headers()
        .addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN));
}
}

20.2 Custom Headers, 20.2.1 Static Headers

20.2 Custom Headers

Spring Security has mechanisms to make it convenient to add the more common security headers to your application.

Spring Security はより共通のセキュリティヘッダーをアプリケーションに追加することを便利にするメカニズムを持ちます。

However, it also provides hooks to enable adding custom headers.

しかしながら、それはカスタムヘッダーを追加できるフックを提供することでもあります。

20.2.1 Static Headers

There may be times you wish to inject custom security headers into your application that are not supported out of the box.

ときどき、あなたはサポートされていないカスタムのセキュリティヘッダーをアプリケーションに追加したいと思うでしょう。

For example, given the following custom security header:

例えば、以下のカスタムのセキュリティヘッダーを提供します。

X-Custom-Security-Header: header-value

When using the XML namespace, these headers can be added to the response using the <header> element as shown below:

XML namespace を使っている場合は、レスポンスにヘッダーを追加するには <header> 要素を次のように使用します。

<http>
    <!-- ... -->

    <headers>
        <header name="X-Custom-Security-Header" value="header-value"/>
    </headers>
</http>

Similarly, the headers could be added to the response using Java Configuration as shown in the following:

同様に、 Java Configuration でレスポンスにヘッダーを追加する場合は次のようにします。

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    // ...
    .headers()
        .addHeaderWriter(new StaticHeadersWriter("X-Custom-Security-Header","header-value"));
}
}

20.1.8 Referrer Policy

20.1.8 Referrer Policy

Referrer Policy is a mechanism that web applications can leverage to manage the referrer field, which contains the last page the user was on.

Referer ポリシーは Web アプリケーションがユーザーが最後にアクセスしていたページを含んだ referer フィールドを管理するようできるメカニズムです。

Spring Security’s approach is to use Referrer Policy header, which provides different policies:

Spring Security のアプローチは、異なるポリシーを提供する Referer Policy ヘッダーを使うというものです。

Referrer-Policy: same-origin

The Referrer-Policy response header instructs the browser to let the destination knows the source where the user was previously.

レスポンスヘッダの Referer-Policy はユーザが以前いた場所を知らせるようブラウザに指示します。

Configuring Referrer Policy

Spring Security doesn’t add Referrer Policy header by default.

Spring Security はデフォルトでは Referer Policy ヘッダーを追加しません。

You can enable the Referrer-Policy header using XML configuration with the <referrer-policy> element as shown below:

あなたは、 XML 設定では <referer-policy> タグを次のように使用することで Referer-Policy ヘッダーを有効にできます。

<http>
    <!-- ... -->

    <headers>
        <referrer-policy policy="same-origin" />
    </headers>
</http>

Similarly, you can enable the Referrer Policy header using Java configuration as shown below:

同様に、あなたは Java Configuration で次のようにして Referer-Policy を有効にできます。

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    // ...
    .headers()
        .referrerPolicy(ReferrerPolicy.SAME_ORIGIN);
}
}

20.1.7 Content Security Policy (CSP)

20.1.7 Content Security Policy (CSP)

Content Security Policy (CSP) is a mechanism that web applications can leverage to mitigate content injection vulnerabilities, such as cross-site scripting (XSS).

Content Security Policy は、 Web アプリケーションがコンテンツインジェクション脆弱性を緩和するのに利用できるようにするメカニズムです。 例えば、 XSS などがそうです。

CSP is a declarative policy that provides a facility for web application authors to declare and ultimately inform the client (user-agent) about the sources from which the web application expects to load resources.

CSPは、Webアプリケーション作成者が宣言し、最終的にWebアプリケーションがリソースを読み込むソースについてクライアント(ユーザーエージェント)に通知するための機能を提供する宣言型ポリシーです。

Content Security Policy is not intended to solve all content injection vulnerabilities.

CSP は全てのコンテンツインジェクション脆弱性を解決することを意図していません。

Instead, CSP can be leveraged to help reduce the harm caused by content injection attacks.

代わりに、 CSP はコンテンツインジェクション攻撃を原因とする問題を減らすのに活用できます。

As a first line of defense, web application authors should validate their input and encode their output.

最初の防衛ラインとして、 Web アプリケーションの制作者は彼らの入力を検証し、出力をエンコードすべきです。

A web application may employ the use of CSP by including one of the following HTTP headers in the response:

Webアプリケーションは、レスポンスに次のHTTPヘッダーのいずれかを含めることで、CSPを使用することができます。

  • Content-Security-Policy
  • Content-Security-Policy-Report-Only

Each of these headers are used as a mechanism to deliver a security policy to the client.

これらのヘッダーは、クライアントにセキュリティポリシーを提供するためのメカニズムとして使用されます。

A security policy contains a set of security policy directives (for example, script-src and object-src), each responsible for declaring the restrictions for a particular resource representation.

セキュリティポリシーは、特定のリソース表現についての制限を宣言したセキュリティポリシーディレクティブのセット(例えば script-srcobject-src)を含んでいます。

For example, a web application can declare that it expects to load scripts from specific, trusted sources, by including the following header in the response:

例えば、 Web アプリケーションは、次のレスポンスヘッダを含めることで、アプリケーションが特定の信頼された場所からスクリプトを読み込むことを期待していることを宣言できます。

Content-Security-Policy: script-src https://trustedscripts.example.com

An attempt to load a script from another source other than what is declared in the script-src directive will be blocked by the user-agent.

script-src ディレクティブで宣言された場所とは異なる場所からスクリプトをロードしようとすると、ユーザエージェント(※ブラウザとか)によってブロックされます。

Additionally, if the report-uri directive is declared in the security policy, then the violation will be reported by the user-agent to the declared URL.

さらに、もし report-uri ディレクティブがセキュリティポリシーに宣言されていた場合、違反行為はユーザエージェントによって宣言された URL に報告されます。

For example, if a web application violates the declared security policy, the following response header will instruct the user-agent to send violation reports to the URL specified in the policy’s report-uri directive.

例えば、もし Web アプリケーションが宣言されたセキュリティポリシーに違反した場合、以下のレスポンスヘッダーはユーザーエージェントに違反のレポートをポリシーの report-uri ディレクティブで指定された URL に対して送信するよう指示します。

Content-Security-Policy: script-src https://trustedscripts.example.com; report-uri /csp-report-endpoint/

Violation reports are standard JSON structures that can be captured either by the web application’s own API or by a publicly hosted CSP violation reporting service, such as, REPORT-URI.

違反のレポートは Web アプリケーション自身の API か、 CSP 違反レポートサービス(例えば REPORT-URI)によってホストされたポリシーのいずれかでキャプチャー可能な標準的な JSON の構造をしています。

The Content-Security-Policy-Report-Only header provides the capability for web application authors and administrators to monitor security policies, rather than enforce them.

Content-Security-Policy-Report-Only ヘッダーは Web アプリケーションの作者と管理者に代わってセキュリティポリシーを監視する能力を提供します。

This header is typically used when experimenting and/or developing security policies for a site.

このヘッダーは通常、サイトのセキュリティポリシーを検証したり開発しているときに使用します。

When a policy is deemed effective, it can be enforced by using the Content-Security-Policy header field instead.

ポリシーが有効とみなされると、代わりに Content-Security-Policy ヘッダーフィールドが使用されるようになります。

Given the following response header, the policy declares that scripts may be loaded from one of two possible sources.

以下のレスポンスヘッダーを与えて、ポリシーがスクリプトは2つの有効なソースのうち1つからロードされるということを宣言しています。

Content-Security-Policy-Report-Only: script-src 'self' https://trustedscripts.example.com; report-uri /csp-report-endpoint/

If the site violates this policy, by attempting to load a script from evil.com, the user-agent will send a violation report to the declared URL specified by the report-uri directive, but still allow the violating resource to load nevertheless.

evil.com からロードしようとしたためにサイトがこのポリシーに違反した場合、ユーザーエージェントは違反レポートを report-uri ディレクティブで宣言された URL に送信します。 しかし、それでもまだ違反したリソースをロードすることは許可されています。

Configuring Content Security Policy

It’s important to note that Spring Security does not add Content Security Policy by default.

Spring Security は Content Security Policy をデフォルトでは追加しないという点に注意してください。

The web application author must declare the security policy(s) to enforce and/or monitor for the protected resources.

Web アプリケーションの作者は、リソースの保護について実行するのかもしくは監視するのかについてセキュリティポリシーを宣言しなければなりません。

For example, given the following security policy:

例えば、次のセキュリティポリシーを与えるとした場合、

script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/

You can enable the CSP header using XML configuration with the <content-security-policy> element as shown below:

あなたは xml 設定を使った場合は <content-security-policy> 要素を以下に見るように使うことで CSP ヘッダーを有効にできます。

<http>
    <!-- ... -->

    <headers>
        <content-security-policy
            policy-directives="script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/" />
    </headers>
</http>

To enable the CSP ‘report-only’ header, configure the element as follows:

CSP の report-only ヘッダーを有効にするには、要素を次のように設定します。

<http>
    <!-- ... -->

    <headers>
        <content-security-policy
            policy-directives="script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/"
            report-only="true" />
    </headers>
</http>

Similarly, you can enable the CSP header using Java configuration as shown below:

同様に、あなたは Java Configuration を次のように使うことで CSP ヘッダーを有効にできます。

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    // ...
    .headers()
        .contentSecurityPolicy("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/");
}
}

To enable the CSP ‘report-only’ header, provide the following Java configuration:

CSP の report-only ヘッダーを有効にするには、 Java Configuration では次のように提供します。

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    // ...
    .headers()
        .contentSecurityPolicy("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
        .reportOnly();
}
}

Additional Resources

Applying Content Security Policy to a web application is often a non-trivial undertaking.

Web アプリケーションに Content Security Policy を適用することは、しばしば重要ではないことがあります。

The following resources may provide further assistance in developing effective security policies for your site.

以下のリソースは効果的なセキュリティポリシーをサイトに組み込むときの助けを提供します。

An Introduction to Content Security Policy

CSP Guide - Mozilla Developer Network

W3C Candidate Recommendation