SpringBootセキュリティ 10 のベストプラクティス

JavaフレームワークのSpring Boot。

Spring Bootを使用していて、セキュリティに関してどこから手をつけてよいかわからないとお悩みであれば、ぜひご一読ください。

今回は、こちらのブログ翻訳の内容をお届けいいたします。

https://snyk.io/blog/spring-boot-security-best-practices/

#SpringBootセキュリティ 10 のベストプラクティス
Simon Maple, Matt Raible
サイモン・メープル、マット・レイブル
2018年8月16日

<img src="https://res.cloudinary.com/snyk/image/upload/v1534422834/blog/Spring_Boot_Security_Cheat_Sheet.png">

[チートシートのダウンロード](https://res.cloudinary.com/snyk/image/upload/v1534422834/blog/Spring_Boot_Security_Cheat_Sheet.pdf)

このチートシートでは、デベロッパとメンテナがSpringBootのセキュリティを向上させる方法に関するベストプラクティスを提案しています。

Spring Bootは、Springアプリケーションの開発を劇的に簡素化するため、Javaエコシステムで最も使用されているフレームワークのひとつです。そのためSpringBootアプリケーションの全体的なセキュリティ体制を改善をお勧めします。

この記事は元々、[Okta](https://www.okta.com/)のJava チャンピオンでありデベロッパアドボケイトでもある[Matt Raible](https://twitter.com/mraible)と一緒に書いたものがもとになっています。私達は、二人ともセキュリティ業界の企業で働いており、Javaが大好きで、デベロッパがより安全なアプリケーションを作る手助けをしたいと考えています。Spring Bootセキュリティに関する見栄えのするチートシート以上のものを作ることができたと思います。
 
早速ですが、Spring Bootセキュリティのベストプラクティスのリストを確認してみましょう。なお、オリジナルの詳細記事は[Oktaブログ](https://developer.okta.com/blog/2018/07/30/10-ways-to-secure-spring-boot)にあります。
 
##Spring Bootセキュリティとは何ですか？

[Spring Bootのセキュリティ](https://snyk.io/blog/spring-boot-security-best-practices/)と一口にいっても、さまざまな要素があります。一般的には、SpringBootセキュリティスターターの依存関係を含め、Spring BootウェブアプリケーションにSpring Securityフレームワークを追加することを意味します。Spring Securityは認証およびアクセス制御フレームワークであり、SpringBootアプリケーションに簡単に組み込むことができます。一方、Spring Bootのセキュリティは、SpringSecurityフレームワークを含むだけではありません。このチートシートでは、Spring Bootのセキュリティに関する幅広いトピックと、SpringBootで作成されたアプリケーションを保護する方法に焦点を当てています。 
 
#SpringBootセキュリティのベストプラクティス
次にあげる厳選されたリストは、SpringBootアプリケーションでの認証と承認のためのSpringSecurityの導入だけではありません。ここでは、より広範なSpring Bootセキュリティ戦略に戦略に焦点を当て、以下のトピックをカバーしています。

1. 本番環境でHTTPSを使用する
2. 依存関係をテストし、Spring Bootの脆弱性を見つける 
3. CSRF保護を有効にする
4. Spring BootXSS保護にコンテンツ・セキュリティ・ポリシーを使用する
5. 認証にOpenIDConnectを使用する
6. パスワードのハッシュ化
7. 最新のリリースを使用
8. シークレットを安全に保管する
9. アプリのペネトレーションテスト
10. セキュリティチームにコードレビューを依頼する





#1.本番環境でHTTPSを使用する
TLS / SSL証明書は以前は高価であり、HTTPSは遅いと見なされていました。マシンの速度が格段に向上してパフォーマンスの問題が解決され、[Let'sEncrypt](https://letsencrypt.org/)は無料のTLS証明書を提供しています。これらの2つの開発が状況を一変し、TLSが主流になりました。

Spring BootアプリでHTTPSを強制するには`WebSecurityConfigurerAdapter`を拡張しセキュアな接続を要求します。

```
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

 @Override
 protected void configure(HttpSecurity http) throws Exception {
   http.requiresChannel().requiresSecure();
 }
}
```

クラウドプロバイダーはTLS証明書を大幅に簡素化することができます。[Amazon Certificate Manager](https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1)は、Let's Encryptとまったく同じですが、AWSのすべての製品／サービスにデフォルトで組み込まれています。100%無料のSSL証明書をプロビジョニングし、自動更新などを文字通りゼロの労力/設定で行うことができます。Herokuにも[自動証明書管理-Automated Certificate Managment」（https://devcenter.heroku.com/articles/automated-certificate-management）があります。

#2.依存関係をテストし、SpringBootの脆弱性を見つける 
アプリケーションが使用する直接依存関係の数がわからない可能性があります。また、アプリケーションが使用する推移的な依存関係の数がわからない可能性が非常に高くなります。依存関係はアプリケーション全体の大部分を占めており、Spring Bootのセキュリティ脆弱性を含んでいる可能性があるにもかかわらず、このようなことはよくあります。オープンソースの依存関係が再利用されると、悪意のあるハッカーにより多くの犠牲者をだせるため、攻撃者はますますオープンソースの依存関係を標的にします。アプリケーションの依存関係ツリー全体に既知の脆弱性がないことを確認することが重要です。
Snykは、アプリケーションビルドアーティファクトをテストし、SpringBootのセキュリティの脆弱性がわかっている依存関係にフラグを立てます。また、アプリケーションで使用しているパッケージに存在する脆弱性のリストをダッシュボードとして提供します。
<img src="https://res.cloudinary.com/snyk/image/upload/v1534422726/blog/snyk-vulnerabilities.png"> 
 

さらに、ソースコードリポジトリへのプルリクエストを介して、セキュリティ問題を修正するためのアップグレードバージョンやパッチを提案してくれます。また、Snykはリポジトリに寄せられたプルリクエストが、新たなSpring Bootのセキュリティ脆弱性をもたらさないかどうか、Webhookを介して自動的にテストすることで、あなたの環境を保護します。
SnykはCLIだけでなくWeb UIでも利用可能なので、CI環境に簡単に統合することができ、設定したしきい値を超える重大な脆弱性が存在する場合にビルドを中断するように設定することができます。
 
[SpringBootの脆弱性を無料で見つけて修正する](https://app.snyk.io/login?cta=sign-up&sect=body&page=10-spring-boot-security-best-practices)

 
#3.CSRF保護を有効にする
[クロスサイトリクエストフォージェリ](https://snyk.io/learn/cross-site-scripting/)とは、ユーザーが現在ログインしているアプリケーションの中で、望ましくないアクションを強制実行させる攻撃のことです。
Spring Securityは、デフォルトでオンになっている[優れたCSRFサポート](https://docs.spring.io/spring-security/reference/)を備えています。Spring MVCの`<form:form>`タグまたはThymeleafと`@EnableWebSecurity`を使用している場合、CSRFトークンは非表示の入力フィールドとして自動的に追加されます。Spring Bootセキュリティ戦略のこの部分を作成するには、SpringSecurityスターターを依存関係として追加する必要があります
AngularやReactなどのJavaScriptフレームワークを使用している場合は、JavaScriptがCookieを読み取れるように`CookieCsrfTokenRepository`を設定する必要があります。

``` 
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
       http
           .csrf()
               .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
   }
}
```

リクエストがHTTPS経由で発生すると、SpringSecurityは自動的にXSRF-TOKENCookieに`secure`フラグを追加します。SpringSecurityはCSRFCookieにSameSite=strictフラグを使用しませんが、SpringSessionまたはWebFluxセッション処理を使用する場合には使用します。
Spring Securityは、リクエストがHTTPSで行われると、`XSRF-TOKEN`クッキーに自動的にsecureフラグを追加します。Spring SecurityはCSRFクッキーに`SameSite=strict`フラグを使いませんが、Spring SessionやWebFluxのセッション処理では使います。

#4. Spring BootXSS保護にコンテンツセキュリティポリシーを使用する
[コンテンツセキュリティポリシー（CSP）](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)は、[XSS](https://owasp.org/www-community/attacks/xss/)（クロスサイトスクリプティング）およびデータインジェクション攻撃を軽減するのに役立つ追加のセキュリティレイヤーです。これを有効にするには、`Content-Security-Policy`ヘッダーを返すようにアプリを構成する必要があります。`<meta http-equiv="Content-Security-Policy">`HTMLページでタグを使用することもできます。

Spring Securityは、デフォルトでいくつかの[セキュリティヘッダー](https://docs.spring.io/spring-security/reference/)を提供します。Spring SecurityはデフォルトではCSPを追加しません。以下の設定で、Spring Bootアプリで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/");
   }
}
```
 
#5.認証にOpenIDConnectを使用する
OpenID Connect（OIDC）は、ユーザー情報を提供するOAuth2.0拡張機能です。アクセストークンに加えてIDトークンが追加され、さらに情報を取得できる`/userinfo`エンドポイントも追加されています。また、エンドポイント検出機能と動的クライアント登録も追加されます。

下の図は、OIDCによる認証の仕組みを示しています。
 <img src="https://res.cloudinary.com/snyk/image/upload/v1534422701/blog/oidc-for-authentication.png">

#6.パスワードのハッシュ化
パスワードをプレーンテキストで保存することは、アプリのセキュリティにとって最悪の行為のひとつです。幸い、Spring Securityでは、デフォルトでプレーンテキストのを許可していません。また、対称暗号化、キー生成、およびパスワードハッシュ（別名、パスワードエンコーディング）に使用できる[暗号化モジュール](https://docs.spring.io/spring-security/reference/)も付属しています。

`PasswordEncoder` は、Spring Securityのパスワードハッシュのメインインターフェイスで、以下のようになっています。
 
``` 
public interface PasswordEncoder {
   String encode(String rawPassword);
   boolean matches(String rawPassword, String encodedPassword);
}
```
Spring Securityはいくつかの機能実装を提供しており、最も人気のあるものは`BCryptPasswordEncoder`と`Pbkdf2PasswordEncoder`です。
 
7.最新のリリースを使用する
アプリケーションの依存関係を定期的にアップグレードする理由はいろいろあります。セキュリティは、アップグレードの動機となる最も重要な理由の一つです。[start.spring.io](https://start.spring.io/)スターターページでは、可能な限り依存関係だけでなく、Springパッケージの最新バージョンを使用しています。

ライブラリの作成者は、リリース間の下位互換性と動作の変更に対する感度が異なるため、インフラストラクチャのアップグレードは、依存関係のアップグレードよりも混乱が少ない傾向があります。とはいえ、構成にセキュリティの脆弱性を見つけた場合は、アップグレード、パッチ、または無視の3つのオプションがあります。
アップグレードは、アプリケーションの全体的な状態の観点から最も安全ですが、多くの場合、アップグレードが常にオプションであるとは限りません。このような場合には、パッチによってパッケージから脆弱性を取り除くことができます。パッチは、Snykのようなセキュリティの専門家から入手することができます。もちろん、脆弱性を無視することは選択肢の一つですが、良い方法ではありません。脆弱性を知っていながら、それが直接悪用されるとは思っていないかもしれません。現時点で、あなたのアプリケーション・フローの中にはないかもしれませんが、ある時点で、開発者が脆弱なパスを使用するコードを追加するかもしれないことを考慮する必要があります。
 
#8.秘密を安全に保管する
Spring Bootのセキュリティ戦略の一環として、データについても考慮する必要があります。パスワードやアクセストークンなどの機密情報は、慎重に取り扱う必要があります。これらをその辺に放置したり、プレーンテキストで渡すことも、ローカルストレージに保持しているなど予測されてはいけません。何度も、（GitHub）の[歴史が証明している](https://github.com/search?q=removed+password&type=Commits)ように、デベロッパは自分の秘密をどのように保存するかについて十分に慎重に考えていません。

アプリケーションが使用する可能性のあるサービスの保存、アクセスの提供、さらにはクレデンシャルの生成に使用できるシークレットをVaultに保存することをお勧めします。[HushiCorp社のVault](https://www.vaultproject.io/)は、秘密を簡単に保存できるだけでなく、多くの追加サービスを提供しています。LDAPなどの一般的な認証メカニズムと統合してトークンを取得することもできます。
[Spring Vault](https://spring.io/projects/spring-vault)はHashiCorp社のVaultを抽象化したもので、Springアノテーションベースのアクセスをクライアントに提供し、インフラで迷うことなく秘密のアクセス、保存、失効を可能にします。次のコードスニペットは、アノテーションを使ってSpring Vaultからパスワードを抽出するのがいかに簡単かを示しています。

``` 
@Value("${password}")
String password;
```

#9.アプリのペンテスト実行
[OWASP ZAP](https://owasp.org/www-project-zap/)セキュリテイツールは
ライブアプリケーションに対して侵入テストを行うプロキシです。これは、[GitHub](https://github.com/zaproxy/zaproxy)でホストされている人気のある（4kスター以上の）無料のオープンソースプロジェクトです。
OWASP ZAPが脆弱性を見つけるために使用する2つのアプローチは、SpiderとActive Scanです。SpiderツールはURLのseedから始まり、アクセスして各レスポンスを解析し、ハイパーリンクを特定してリストに追加します。次に、これらの新しく見つかったURLにアクセスし、再帰的に続行し、WebアプリケーションのURLのマップを作成します。Active Scanツールは、潜在的な脆弱性のリストに対して、選択したターゲットを自動的にテストします。このツールは、Webアプリケーションのどこに脆弱性があるかのレポートや、その脆弱性に関する詳細を提供します。
 
 
#10.セキュリティチームにコードレビューを依頼する
コードレビューは、パフォーマンスの高いソフトウェア開発チームにとって不可欠です。Oktaでは、すべてのプロダクションコードと公式のオープンソースプロジェクトで、専門のセキュリティチームによる分析を受けることが義務付けられています。会社にセキュリティの専門家がいない場合もありますが、もしあなたが機密データを扱っているのであれば、そうすべきかもしれません。
[Spring Boot Securityのチートシートをダウンロード](https://res.cloudinary.com/snyk/image/upload/v1534422834/blog/Spring_Boot_Security_Cheat_Sheet.pdf)してどこかに貼っておけば、アプリケーションでSpringBootを使用しているデベロッパが従うべきベストプラクティスのいくつかを思い出すことができるでしょう。
 
#よくある質問 FAQ
##Spring Bootにセキュリティを追加するにはどうすればよいですか？
ときに春のセキュリティの追加あなたの春ブートアプリケーションにセキュリティスターター依存関係を追加することから始まります。
Spring BootアプリケーションにSpring Securityを追加するには、まず[security starterの依存関係を追加](https://snyk.io/blog/spring-boot-security-best-practices/)します。
 
<dependency>
    <groupId> org.springframework.boot </ groupId>
    <artifactId> spring-boot-starter-security </ artifactId>
</ dependency>

デフォルトでは、スターターの依存関係が含まれている場合、認証が有効になります。認証情報を設定するには、プロパティ`spring.security.user.name`と`spring.security.user.password`を設定します。
 
##SpringBootでSpringSecurityを無効にするにはどうすればよいですか？
デフォルトでは、spring-boot-starter-securityパッケージが含まれていると、[Spring Security](https://snyk.io/blog/spring-boot-security-best-practices/)が有効になります。これを無効にするには、`application.properties`ファイルで`Spring Security`を除外することでかんたんに無効にできます。
`spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration`
 

######最後まで、読んでいただき、ありがとうございました！

---
Contents provided by:
Jesse Casman, Fumiko Doi, Content Strategists for Snyk, Japan, and Randell Degges, Community Manager for Snyk Global