Skip to main content

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

著者

Natalia Venditto

Cheat Sheet assetts Angalar

2020年8月10日

0 分で読めます

以前、AngularJSのセキュリティ基礎チートシートをご紹介しました。今回は、最新のAngularにおけるセキュリティのベストプラクティスを詳しく見ていきます。Angularセキュリティベストプラクティスのチートシートはこちらからダウンロードできます。

Angularのセキュリティベストプラクティス6選

  1. 「Angularらしい」方法でXSSを防ぐ

  2. innerHTMLは慎重に使う

  3. ユーザー入力を連結してテンプレートを生成しない

  4. HTML要素の操作にネイティブDOM APIを使わない

  5. サーバーサイドテンプレートでテンプレートエンジンを使わない

  6. Angularプロジェクトをスキャンして、セキュリティ脆弱性を引き起こすコンポーネントを見つける

1. 「Angularらしい」方法でXSSを防ぐ

Angularのセキュリティベストプラクティス #1:補間({{  }})を使って、危険な可能性のある文字を安全にエンコードし、テンプレート式内の信頼できないHTMLまたはCSS式をエスケープします。 

AngularはReactやVue.jsと同様に、ブラウザーで文字列補間を処理する際、デフォルトで安全性を確保する設計になっています。デフォルトでは、すべてのデータを安全でない、信頼できないものとして扱います。そのため、これらをはじめとする最新のビューライブラリでは、HTMLコンテキスト内のテキストに対して、デフォルトで出力エンコードを行うことがベストプラクティスとなっています。

以前のブログ記事AngularJSのセキュリティベストプラクティスで詳しく説明したように、組み込みの波括弧による文字列補間を使う「Angularらしい」方法に従うことを強くおすすめします。悪意のあるユーザー入力をエスケープすることで、Webアプリケーションを危険にさらしたり、クロスサイトスクリプティング(XSS)の脆弱性につながったりするリスクを防げます。

2. innerHTMLは慎重に使う

Angularのセキュリティベストプラクティス #2:コンポーネントにHTMLを動的に追加する必要がある場合は、その生成を [innerHTML]にバインドします。これにより、データはコンテキスト内でHTMLとして解釈され、サニタイズされます。安全でないタグがすべて取り除かれるため、悪意のあるクロスサイトスクリプティングコードの実行を防げます。なお、 サニタイズ と エンコードは同じではありません。

サニタイズと出力エンコードの違いとは?

出力エンコードでは、文字列がテキスト表現に置き換えられ、特定のHTMLタグに対応付けられることがあります。たとえば、scriptのような入力が解析されると、Angularは特殊な山括弧をエンコードして、そのテキストを表示できます。これは、セキュリティのベストプラクティスを実装する多くのライブラリやフレームワークで標準的に使われる方法です。そのために、HTMLエンティティエンコードと呼ばれる変換を行い、次のテキストをDOMに書き込みます:script。その後、ブラウザーがコンテキストを解釈し、scriptタグを出力します。

出力エンコードとは異なり、サニタイズやフィルタリングでは、安全でない文字を積極的に検出して取り除いてからDOMに書き込みます。

出力エンコードとサニタイズを適切に行うには、コンテキストが重要な判断要素となります。コンテキストによって、適切な処理方法が変わるためです。

セキュリティコンテキストについて詳しく知るには、Angularのドキュメントを参照してください。そこでは次のように説明されています。

Angularでは、次のセキュリティコンテキストが定義されています。

* HTML:innerHtmlへのバインドなど、値をHTMLとして解釈する場合に使用します。* Style:CSSをstyleプロパティにバインドする場合に使用します。* URL:などのURLプロパティに使用します。* リソースURL:コードとして読み込まれ実行されるURLです。たとえば、ではこのコンテキストが使われます。

URLは特別な扱いとなり、フィルタリングされない点に注意してください。

3. ユーザー入力を連結してテンプレートを生成しない

Angularのセキュリティベストプラクティス #3:ユーザーが入力した可能性のある値を文字列としてテンプレートに連結しないでください。

Angularアプリケーションで文字列補間や推奨されているコンポーネント構成を適切に使わず、テンプレートを連結する必要が生じるケースは、あったとしてもごくわずかです。コードベースでこのような悪い慣行を見つけた場合は、入力値を可能な限りサニタイズするか、リファクタリングしてください。

次の例のようなコードに注意し、使用を避けてください。

headlineとbodyのバインディング、およびユーザー入力の可能性がある変数を含む、Angular HeroJobAdComponentのテンプレートを表示したコードエディター。

Angularのセキュリティベストプラクティス:ユーザー入力を連結してテンプレートを生成しない

20行目の一般的でない文字列からテンプレートへの連結に特に注意してください。potentialUserInputの値は、出所が不明または信頼できない悪意のある式である可能性があります。これは避けるべき悪い慣行の一例です。

以下は、Angularのプレイグラウンドで試せる、ユーザー入力をテンプレートに連結すると安全に処理されないことを示す、より詳しい例です。

コードエディターとブラウザーのプレビューに、HTMLを挿入したAngularの求人広告と、コンソールに繰り返し表示されるCookieのログを表示

Angularセキュリティの実践例:ユーザー入力を連結してテンプレートを生成しない

この点について、Angularセキュリティガイドでは次のように推奨しています。

「ユーザー入力とテンプレートを連結してテンプレートのソースコードを生成しないでください。こうした脆弱性を防ぐには、オフラインテンプレートコンパイラー(テンプレートインジェクションとも呼ばれます)を使用してください。」

- Angularセキュリティガイド

Angularでは、Ahead of Time(AOT)コンパイラーを使用してテンプレートをオフラインでコンパイルすることを推奨しています。これにより、さまざまなテンプレートインジェクションの脆弱性を完全に回避できます。

ng build --aot
ng serve --aot

Angularの最新バージョン(v9以降)では、Ivyでコンパイルする場合、Ahead of Timeコンパイルがデフォルトで有効になっており、テンプレートインジェクションを防ぎます。

{
  "projects": {
    "my-existing-project": {
      "architect": {
        "build": {
          "options": {
            ...
            "aot": true,
          }
        }
      }
    }
  }
}

4. HTML要素の操作にネイティブDOM APIを使わない

Angularのセキュリティベストプラクティス #4:ページ上のHTML要素の操作にネイティブDOM APIを使わないでください。

DOMを直接操作するのではなく、Angularのテンプレート機能や独自のAPIを使ってDOMを操作してください。一般的な指針として、次の方法は避けましょう。

  •  node.appendChild();

  • ページの操作にdocumentオブジェクトのメソッドを使う

  • jQuery APIを使う

Angularには、避けるよう推奨しているものと同種のDOM直接操作を可能にするネイティブAPIもあります。たとえば、ElementRef APIです。ElementRefを使って直接DOMノードにアクセスし、操作を行うと、セキュリティ上の問題が生じる可能性があります。

このような操作や、Angular API以外を使った操作は、セキュリティ脆弱性につながる可能性があります。

5. サーバーサイドテンプレートでテンプレートエンジンを使わない

Angularのセキュリティベストプラクティス #5:Angularのサーバーサイドレンダリングアプリケーションでテンプレートの作成やデータの追加に、サードパーティ製のテンプレートエンジンを使わないでください。

Node.jsでWebアプリケーションを構築したことがあれば、EJS、Pug、Handlebarsなどのテンプレートエンジンや、その代替ツールを使ったことがあるでしょう。これらはビュー層のサーバーサイドレンダリングテンプレートを管理するために使われ、パーシャルやレイアウトの合成など、ビューを動的に生成するためのさまざまな機能を備えています。

しかし、Angularのサーバーサイドレンダリングアプリケーションでこうしたテンプレートエンジンを使うと、テンプレートに悪意のあるコードが挿入される可能性があります。注入されるデータはAngular APIの範囲外にあるためサニタイズできず、テンプレート文字列を連結する場合と同じリスクが生じます。

6. Angularプロジェクトをスキャンして、セキュリティ脆弱性を引き起こすコンポーネントを見つける

Angularプロジェクトのオープンソース依存関係とAngularコンポーネントを常にスキャンし、セキュリティ脆弱性を確認しましょう。SnykのプラットフォームまたはCLIを無料で使って、セキュリティ脆弱性を 検出、修正し、継続的に監視できます。

Angularやそのエコシステムに含まれるモジュールやコンポーネントなど、サードパーティライブラリを使う際は、次の点に注意しましょう。Angularコアライブラリに影響するセキュリティ脆弱性と、プロジェクトにインポートして使用しているサードパーティ製Angularモジュールのセキュリティ脆弱性です。

既知の脆弱性があるコンポーネントの使用は、OWASP Top 10で記載されているWebセキュリティリスクです。注意が必要です。実際、下の図は既知のセキュリティ脆弱性があるAngularモジュールの一覧です。たとえば、npm installやnpm auditの実行時に検出されるものです。JavaScriptフレームワークセキュリティレポートから引用したこの図が示すように、年間何百万回もダウンロードされているにもかかわらず、現時点でセキュリティ修正がないものもあります。

AngularとReactの間接依存関係、脆弱性、深刻度、年間ダウンロード数、および各問題を修正できるかどうかを比較した表。
Angularのセキュリティ - 間接依存関係のリスク

Angular Webアプリケーションを保護する

npm auditを使っているなら、それは素晴らしい第一歩です。すでに適切な対応ができています。

ただし、npmのaudit機能を使っていても、対処すべきセキュリティ上の懸念は残っています。

  • 現時点でプロジェクト内のすべてのセキュリティ脆弱性を解消できたとしても、Angularモジュールに新たな脆弱性が見つかったらどうなるでしょうか。VercelやNetlifyなどにデプロイしたAngularアプリケーションへの影響に気づけるでしょうか。

  • もう1つの懸念は、npm auditが公式なCVEがある既知の脆弱性のみを追跡することです。一方、[SnykはAngular関連モジュールの23件以上のセキュリティ脆弱性を追跡しています](https://snyk.io/blog/angular-vs-react-security-bakeoff-2019/)が、npm auditではこれらが報告されません。

Snykなら、こうした2つの懸念を解消できます。しかも無料です ;-)

利用を始めるには?

無料のSnykアカウントを作成し、GitHubまたはBitbucketのフロントエンドプロジェクトを接続しましょう。Snykが自動的に問題を検出し、修正用のプルリクエストを作成します。

Capture the Flagを始めよう

オンデマンドのバーチャル入門ワークショップを見て、Capture the Flagの課題の解き方を学びましょう。

Angularのセキュリティ問題をすぐに見つけるには、Snyk CLIを使う方法もあります。

npm install -g snyk
snyk test
Angular 1.2.32で重大度の高いXSS脆弱性が見つかったことを示し、アップグレードを推奨するSnyk CLIのターミナル出力。
Snyk CLIは、既知のCVE脆弱性だけにとどまりません。これらを報告しないnpm auditとは異なり、

出典:AngularとReact:セキュリティ対決 2019

Snykは、修正済みバージョンにアップグレードするための、具体的な修復アドバイスを提供します。

Angular向けのセキュリティスキャナーをお探しなら、Snykをぜひお試しください。オープンソース依存関係を追跡し、脆弱性の通知を受け取り、発見された脆弱性を修正できます。

あわせて読みたい記事:

Angularは安全ですか?

新しいAngularフレームワーク(Angular 2以降)は、デフォルトで安全なフレームワークと見なされており、既知のセキュリティ脆弱性はありません。一方、前身のAngularJSには、2020年6月時点で25件を超える公開済みのセキュリティ脆弱性があります。Angularのセキュリティベストプラクティスに従い、Angular、Reactなどのプロジェクトで使われるnpmモジュールのエコシステムのセキュリティを詳しく解説した、SnykのJavaScriptフレームワークセキュリティレポートもご覧ください。

Angularアプリケーションを安全にするには?

Angularアプリケーションを安全にするための基本的なガイドラインを紹介します。

1. 開発者として「Angularらしい」方法とベストプラクティスに従い、XSSからアプリケーションを保護しましょう。たとえば、innerHTMLを使わない、ユーザー入力を連結してテンプレートを生成しない、HTML要素の操作にネイティブDOM APIを使わない、といった対策です。

2. Angularプロジェクトをスキャンし、セキュリティ脆弱性を引き起こすコンポーネントを見つけましょう。Angular独自のセキュリティ対策に従っていても、他のモジュールの開発者が従っているとは限りません。深刻な問題にさらされる可能性があります。スキャンだけでなく、潜在的な新たな問題の修正と監視も行いましょう。Snykなら簡単に実現できます。プロジェクトに簡単に接続できる無料ツールです。詳しくはAngularのセキュリティベストプラクティスをご覧ください。

AngularとReactでは、どちらがより安全ですか?

Angularプロジェクト(Angular 2以降)には、現在公表されているセキュリティ脆弱性はありません。Reactには影響を及ぼすセキュリティ脆弱性が2件ありますが、いずれも2017年のもので、すでにそれより新しいバージョンをお使いでしょう。Angularの前身であるAngularJSには、25件を超えるセキュリティ脆弱性があります。まだ開発や保守を続けている場合は、無料で利用できる開発者ファーストのセキュリティツール、Snykなどでプロジェクトを必ずスキャンしてください。このテーマについては、AngularとReactのエコシステムのセキュリティ状況を調査したJavaScriptフレームワークのセキュリティレポートをご覧ください。

Angularでは入力値がサニタイズされますか?

Angularではデフォルトで、XSSにつながる可能性のある危険なテキストがすべて出力時にエンコードされます。安全な補間に二重中括弧({{}})を使うなど、Angularが推奨する安全なコーディングを実践していることが前提です。ただし、AngularのinnerHTMLバインディングを使用した場合も、Angularは危険なコンテンツをサニタイズして保護しようとします。それでも、ユーザー入力を追加する方法としては、最後の手段にとどめるべきです。

CTFを始めよう

オンデマンドのバーチャル入門ワークショップを視聴して、CTFの課題の解き方を学びましょう。

続きを読む

Blog

フロンティアモデルは脆弱性を発見した。攻撃者だけがエクスプロイトチェーンを見つけた。

静的解析で欠陥は見つかりましたが、ライブ攻撃テストで侵害につながる連鎖を実証できたのは唯一でした。Evo COS、Claude Security、Claude Code Securityを比較します。

feature insights context
Blog

自律型攻撃はすでに始まっている。防御もそのスピードに追いつかなければならない。

自律型攻撃者によって、防御に使える時間は短くなっています。継続的な検出、修復、検証、予防で、セキュリティチームが攻撃に歩調を合わせる方法をご紹介します。

Blog

AIコーディングエージェントが不適切なアクセス制御を繰り返し実装する理由

AIコーディングエージェントは、コンパイルが通りレビューも通過する一方で、あるテナントのデータを別のテナントに公開してしまう認可ロジックを生成することがあります。不適切なアクセス制御が検出しにくい理由と、その防止策をご紹介します。