ソフトウェア・インテグリティ

 

Java開発者向けのSpring Securityベストプラクティス・トップ10

Spring Securityを利用することで、セキュアなSpringアプリケーションを構築できます。最初にSpring Securityのベストプラクティス・トップ10をご紹介します。

Spring Securityのベストプラクティス | シノプシス

この記事をご覧の方は、Springとその基本的なメカニズムにすでに精通していることでしょう。2002年に登場して以来、Springは、あらゆる種類のWebアプリケーションをJavaで構築するための主要なフレームワークとなっています。

通常、Webアプリケーションは、企業と社内外のユーザーを結ぶ最大のインターフェイスです。開発段階でアプリケーションにセキュリティ上の見落としがあると、ハッカーにとって絶好の標的になる可能性があります。脆弱なアプリケーションが悪用されることで、顧客や会社の機密データが漏えいし、金銭的な損失が発生したり、企業の評判が恒久的なダメージを受ける可能性があります。Springでは、こうした落とし穴を回避するのに役立つさまざまなセキュリティ技術が導入されています。以下では、アプリケーションのセキュリティを保つために従うべき「10のSpring Securityのベストプラクティス」をご紹介します。

シノプシスのコース・カタログをすべて見る

1. テスト済み・実証済みのセキュリティ・ライブラリを使用する

以下のヒントの多くにつながる基本的なポイントです。退屈に聞こえるかもしれませんが、アプリケーションのセキュリティを確保するということは、攻撃者が侵入する可能性のあるすべての抜け穴をふさぐことです。このような作業には、特定のプロジェクトの独自開発に追加することを意図した機能よりも、テストおよび実証済みのセキュリティ・ライブラリで対応する方がはるかに適しています。

Springアプリケーションに対応するテスト済み・実証済みのライブラリがSpring Securityです。Spring Securityは認証処理を簡素化し、CSRFなどのエクスプロイトに対する一連の保護を設定します。また、他の多くの脅威から保護するための適切な構成を設定する際にも役立ちます。

Spring Securityの追加は、いくつかの依存関係を追加するだけという簡単なものですが、最大限の価値を引き出すためには多少の追加作業が必要です。これについては次のヒントで説明します。

2. HTTPセキュリティ・ヘッダーを設定する

HTTPセキュリティ・ヘッダーは、アプリケーションに対する悪意のあるアクティビティを防ぐために有効です。このヘッダーは、サーバーから返されるHTTP応答に挿入する必要があり、クライアント・コードがブラウザで実行できる動作の境界や、トランスポート・セキュリティ、リファラー(参照元)の表示、HTMLフレームに関連するポリシーなど、ブラウザの動作の一部を定義します。

Spring Securityでは、一部のヘッダーは初期時に最も安全なオプションに設定されていますが、他のヘッダーは、アプリケーションに最適な組み合わせと必要なセキュリティ・レベルに合わせて微調整する必要があります。セキュリティ構成を定義する場合、HttpSecurity.headers()メソッドを使用してヘッダーを設定できます。

3. データとコマンドを分離する

Webアプリケーションは、アプリケーションに提供するデータにハッカーが悪意のあるコマンドを挿入する、サーバー側のインジェクション攻撃を受ける可能性があります。この攻撃は、ユーザーによって提供された信頼できないデータを使用してアプリケーションで実行コマンド(SQLクエリなど)を作成するなどの方法で可能になります。この場合、ハッカーは、構築されたコマンドを破壊して悪意のある行為を実行するための適切な文字の順番を見つけるだけで目的を果たせます。

Springには、データとコマンドの混在を避けるために役立つさまざまな方法があります。データベースアクセスには、Spring Data JPAを使用するのが効果的です。アプリケーションからのほとんどのデータベースアクセスを抽象化することで、不正使用される可能性がある手書きのSQLクエリを使用するリスクが軽減されます。

場合によっては、このようなデータ抽象化を利用できず、実際のSQLクエリを使用せざるを得ないことがあります。その場合はクエリのパラメータ化が最善の方法です。

4. 表示テキストをサニタイズする

Webアプリケーションがクロスサイト・スクリプティング(XSS)攻撃を受ける可能性もあります。この種の攻撃では、ハッカーは、他のユーザーがアプリケーションで表示するコンテンツに悪意のあるJavaScriptを挿入し、被害者の権限を利用して悪意のあるコードを実行できるようにします。セキュリティ・ヘッダーで悪意のあるコードの実行可能範囲を制限することは可能ですが、ユーザーが提供するコンテンツにJavaScriptコードを含めることができないようにすることが最善の防御策です。

サニタイズ(無害化)には複数の方法があります。

  • MVC(Model-View-Controller)アプリケーションでは、一部のテンプレート・エンジンでHTMLサニタイズをネイティブ機能として提供しています。一例としてThymeleafが挙げられます。利用可能な機能を確認し、適切に使用してください。
  • その他の場合は表示データを明示的にエンコードまたはサニタイズする必要がありますが、その際、独自に実装を試みようとせず、実証済みのエンコーディングまたはサニタイズ・ライブラリを使用することをお勧めします。OWASP Java EncoderOWASP Java HTML Sanitizerなどの便利なライブラリがあります。
  • WebアプリケーションがAPIベースの場合はクライアント側もセキュリティで保護することをお忘れなく。これについてはここでは説明を省きますが、APIのセキュリティに劣らず重要なことです。

5. CORS(オリジン間リソース共有)ポリシーを慎重に定義する

同一生成元ポリシー(SOP)は、悪意がある可能性のあるスクリプトを分離するために、あるオリジンからのデータが別のオリジンからのスクリプトによって読み取られたり実行されることを防ぎ、HTTPメソッドまたはヘッダーを使用する場合に、別のオリジンに対して一部の要求が実行されることを防ぎます。たとえば、あるオリジンからサイトを閲覧している場合、ブラウザは別のオリジンへのリクエストに対する応答に含まれているコードを実行しません。また、標準ヘッダーを使用した単純なGET、HEAD、POSTリクエスト以外の場合、スクリプトは別のオリジンへのリクエストを実行できません。「オリジン」とは、プロトコル、ホスト名、ポートの組み合わせです。

厳格なSOPは大規模なWebアプリケーションに対して制限が厳しすぎる場合があることから、そういうときのためにCORS(オリジン間リソース共有)が存在します。CORSを使用することで、サーバーはSOPの制限を緩和し、特定の呼び出し元のオリジンと呼び出し先のエンドポイントに対してオリジン間のリクエスト/応答の読み取りおよび実行を許可できます。CORSルールはサーバーによって定義されますが、準拠する責任はブラウザにあることを覚えておいてください。

Springを使用すると、CORSポリシーを簡単に定義できます。これらの定義はWebMvcConfigurerクラスで一元的に設定するか、@Controllerまたは@RequestMappingの@CrossOrigin注釈を使用して設定することができます。

一般的なアドバイスとして、SOPとCORSの仕組みを確実に理解してください。ユーザーとデータを保護するにはブラウザと組み合わせる必要があります。CORSは細かい粒度での設定が可能です。必要なエンドポイントとオリジンのみを許可するように注意してください。

6. 認証の強化

多くのWebアプリケーションでは、現在のユーザーがアクセス許可を与えるリソースを決定する必要があります。各ユーザーが何を実行できるかを認可のルールとして定義します。その重要な要素は、認証対象のユーザーにかんする知識(ナレッジ)です。認証のセキュリティに問題があるとアプリケーション全体が危険にさらされる可能性があるため、最大限のセキュリティを確保することが重要です。

Spring Securityは認証を簡素化し、セキュリティ強化を支援します。デフォルトでは、フォーム形式のログインページが表示され、ユーザーが提供したユーザー名とパスワードを、アプリケーション・ユーザー・データベースと照合し、セッション中のユーザー認証を追跡します。この動作は、WebSecurityConfigurerAdapterクラスを拡張することで構成可能であり、ユーザーの認証方法やその他の要素(ログイン状態を保存する「Remember Me」機能の有無など)を定義できます。

パスワードの保存も考慮すべき重要事項です。ユーザーのパスワードのハッシュをアプリケーション・データベースに保存する場合、悪意のあるアクターがそのデータベースにアクセスしてパスワードに対するオフラインのブルートフォース(総当たり)攻撃を実行する可能性があることを前提とする必要があります。その1つの対策として、簡単にはブルートフォース攻撃を完了できないような複雑な一方向性パスワード・エンコード・アルゴリズムを設定する方法があります。現時点では、コスト係数13のbcryptを使用することが推奨されます。Springでは、passwordEncoder()インターフェイスの実装を定義することでこれを行うことができます。

7. 認証の委任

以前のSpring Securityのベストプラクティスでは、独自の認証を管理することが困難である理由をいくつか説明しました。パスワードポリシー、列挙攻撃からの保護、多要素認証(MFA)機能など、基本的なメカニズム以上の高度な方式を装備しようとすると、処理はさらに複雑化します。

解決策としては、OpenID Connect(OIDC)を利用して、パブリック ID プロバイダー(GoogleやGitHubなど)またはプライベート ID プロバイダーにユーザー認証を委任する方法が推奨されます。Springバージョン5.1からは、OIDCベースの認証を統合するための組み込みのサポートを提供しています。アプリケーションでプロバイダーの構成設定を指定し、oauth2Loginメソッドを呼び出して該当ログインを要求するようにアプリケーションを設定する必要があります。

8. 堅牢な認可モデルを理解して実装する

堅牢な認可方式を用いることで、アプリケーションは現在使用中のユーザーが誰であるかを常に認識します。アプリケーション内のリソースにアクセスする権限がユーザーにあるかどうかを確認するためには、適切な認可方式が必要です。

Springには、ロールベースアクセス制御(RBAC)、他のメソッドを実装するために使用できる、属性ベースアクセス制御(ABAC)などのカスタマイズ可能な認可システムがあります。ユーザーにはロールと権限を割り当てることができます。認可は、アプリケーション全体、特定のエンドポイント、および個々の操作に対して付与できます。アクセス許可をチェックする独自のカスタムメソッドを実装することもできます。

アプリケーションに必要な認可モデルを理解し、アプリケーションのすべてのレベル(アプリケーション、エンドポイント、操作)で認可チェックを行って、徹底的な防御を実施することが重要です。

9. 機密情報を隠蔽する

あらゆるアプリケーションは、データベース資格情報や暗号鍵などの機密データをはじめ、攻撃者にアプリケーションを偽装される可能性のある機密情報を処理する必要があります。これらの機密情報が構成ファイルに含まれている場合、不正なユーザーがさまざまな方法(たとえば、開発チームが誤って公開リポジトリに発行したファイルまたは悪意のある内部関係者が公開したファイルに対するディレクトリ・トラバーサル攻撃)でアクセスする可能性があります。

HashiCorpのVaultなどの専用の機密情報管理システムを使用することで、チームはSpringのセキュリティのベストプラクティスに確実に従うことができます。アプリケーション・シークレットはコンテナに格納され、権限があるクライアントにのみ提供されます。機密情報が誤って漏えいするリスクがはるかに小さくなります。

Spring Vaultを利用すれば、Springはこのようなコンテナともシームレスに統合します。このライブラリを使用すれば、開発者にとってシークレット管理が非常に簡単になります。

10. 基本を網羅する

前述のヒントではWeb開発で一般的なセキュリティの要素について説明しましたが、それ以外のセキュリティのすべての要素も同様に検討する必要があります。他のアプリケーションと同様に、ライブラリのバージョンを常に最新状態に維持し、依存関係として使用されるライブラリが脆弱性のリスクをもたらさないことを確実にすることが重要です。また、悪用の事例を特定し、セキュリティ・テストを実施し、コードレビューを行うことも重要です。ツールの使用は確かに有益ですが、アプリケーションのセキュリティ・リスクを軽減するには、適切なアプリケーション・セキュリティ・プロセスが重要なのです。

はじめてみる

Spring Securityはセキュリティを強化するための強力な手段ですが、適切に使用することが重要です。この投稿では、Springアプリケーションのセキュリティを強化する方法のほんの概要を説明しました。もう一つのヒントとして、アプリケーションの安全性と回避すべき落とし穴について時間をかけてチームを教育することも推奨されます。シノプシスのeラーニング教材では、Springアプリケーションを含むアプリケーション・セキュリティのさまざまな要素について、これらのトピックを掘り下げています。

アプリケーション・セキュリティのベストプラクティス | シノプシス

 

この著者によるその他の情報