このトピックでは、クロスサイトスクリプティング攻撃などの一般的なWebアプリケーションの脆弱性や攻撃に対する、Angularの組み込みの保護について説明します。 認証や認可など、アプリケーションレベルのセキュリティは扱いません。
以下で説明する攻撃と対策の詳細については、Open Web Application Security Project (OWASP) ガイドを参照してください。
脆弱性の報告
Angularは、Google オープンソースソフトウェア脆弱性報酬プログラムの一部です。Angularの脆弱性については、https://bughunters.google.com で報告してください。
Googleがセキュリティ上の問題をどのように処理するかについては、Googleのセキュリティポリシーを参照してください。
ベストプラクティス
Angularアプリケーションを安全にするためのベストプラクティスをいくつか紹介します。
- Angularライブラリリリースを最新の状態に保つ - Angularライブラリは定期的に更新されており、これらの更新には、以前のバージョンで見つかったセキュリティ上の欠陥の修正が含まれている場合があります。Angularの変更ログで、セキュリティ関連の更新を確認してください。
- Angularのコピーを変更しない - Angularのプライベートなカスタマイズされたバージョンは、現在のバージョンから遅れがちであり、重要なセキュリティ修正や機能強化が含まれていない場合があります。代わりに、Angularの改善点をコミュニティと共有し、プルリクエストを作成してください。
- ドキュメントで"セキュリティリスク"とマークされているAngular APIを避ける - 詳細については、このページの安全な値を信頼するセクションを参照してください。
クロスサイトスクリプティング(XSS)の防止
クロスサイトスクリプティング(XSS)により、攻撃者はWebページに悪意のあるコードを挿入できます。 このようなコードは、ユーザーのログインデータやユーザーデータを盗んだり、ユーザーになりすましたりできます。 これは、Web上で最も一般的な攻撃の1つです。
XSS攻撃を阻止するには、悪意のあるコードがDocument Object Model(DOM)に入らないようにする必要があります。
攻撃者が<script>タグをDOMに挿入するように仕向けることができたら、攻撃者はWebサイトで任意のコードを実行できます。
攻撃は<script>タグに限定されません。DOMの多くの要素やプロパティはコードの実行を許可します。たとえば、<img alt="" onerror="...">や<a href="javascript:...">などです。
攻撃者が制御するデータがDOMに入ると、セキュリティの脆弱性が発生する可能性があります。
Angularのクロスサイトスクリプティングセキュリティモデル
Angularは、XSSのバグを体系的に阻止するために、すべての値をデフォルトで信頼されていないものとして扱います。 テンプレートバインディングや補間からDOMに値が挿入されると、Angularは信頼されていない値をサニタイズしてエスケープします。 値がAngularの外部で既にサニタイズされており、安全であるとみなされる場合は、値を信頼済みとしてマークすることでAngularに伝えます。
レンダリングに使用する値とは異なり、Angularテンプレートはデフォルトで信頼済みとみなされ、実行可能なコードとして扱われる必要があります。 ユーザー入力とテンプレート構文を連結してテンプレートを作成しないでください。 これを行うと、攻撃者はアプリケーションに任意のコードを注入できます。 これらの脆弱性を防ぐために、本番環境のデプロイでは常にデフォルトのAhead-Of-Time (AOT) テンプレートコンパイラを使用してください。
コンテンツセキュリティポリシーとTrusted Typesを使用することで、さらに保護を強化できます。 これらのWebプラットフォーム機能は、DOMレベルで動作するため、XSSの問題を防ぐための最も効果的な手段です。これにより、他の低レベルAPIを使用したバイパスはできません。 そのため、これらの機能を活用することを強くお勧めします。これを行うには、アプリケーションのコンテンツセキュリティポリシーを構成し、Trusted Typesの強制を有効にします。
サニタイズとセキュリティコンテキスト
_サニタイズ_とは、信頼されていない値を検査して、DOMに挿入しても安全な値に変換することです。 多くの場合、サニタイズは値をまったく変更しません。 サニタイズはコンテキストに依存します。 例えば、CSSでは無害な値も、URLでは危険な可能性があります。
Angularは、次のセキュリティコンテキストを定義しています。
| セキュリティコンテキスト | 詳細 |
|---|---|
| HTML | HTMLとして値を解釈する場合に使用します。たとえば、innerHtmlにバインディングする場合。 |
| Style | styleプロパティにCSSをバインディングする場合に使用します。 |
| URL | <a href>などのURLプロパティに使用します。 |
| Resource URL | <script src>などのコードとして読み込まれて実行されるURL。たとえば、 |
Angularは、信頼されていない値をHTMLとURLに対してサニタイズします。リソースURLのサニタイズは、リソースURLに任意のコードが含まれているため、不可能です。 開発モードでは、Angularはサニタイズ中に値を変更する必要がある場合、コンソールに警告を表示します。
サニタイズの例
次のテンプレートは、htmlSnippetの値をバインディングします。1つは要素の内容に補間して、もう1つは要素のinnerHTMLプロパティにバインディングします。
inner-html-binding.component.html
<h3>Binding innerHTML</h3>
<p>Bound value:</p>
<p class="e2e-inner-html-interpolated">{{ htmlSnippet }}</p>
<p>Result of binding to innerHTML:</p>
<p class="e2e-inner-html-bound" [innerHTML]="htmlSnippet"></p>
補間されたコンテンツは常にエスケープされます。HTMLは解釈されず、ブラウザは要素のテキストコンテンツに角括弧を表示します。
HTMLを解釈するには、innerHTMLなどのHTMLプロパティにバインディングします。
攻撃者が制御する可能性のある値をinnerHTMLにバインディングすると、通常はXSSの脆弱性が発生します。
たとえば、次のようにJavaScriptを実行できます。
inner-html-binding.component.ts (class)
export class InnerHtmlBindingComponent {
// For example, a user/attacker-controlled value from a URL.
htmlSnippet = 'Template <script>alert("0wned")</script> <b>Syntax</b>';
}
Angularは、値を安全ではないと認識し、自動的にサニタイズします。これにより、script要素は削除されますが、<b>要素などの安全なコンテンツは保持されます。
DOM APIの直接使用と明示的なサニタイズ呼び出し
信頼済みタイプを強制しない限り、組み込みのブラウザDOM APIは、セキュリティの脆弱性から自動的に保護しません。
たとえば、document、ElementRefを通じてアクセスできるノード、および多くのサードパーティAPIには、安全ではないメソッドが含まれています。
同様に、DOMを操作する他のライブラリと対話する場合、Angularの補間と同じような自動サニタイズは行われない可能性があります。
可能な限り、DOMと直接対話するのを避け、代わりにAngularテンプレートを使用してください。
避けられない場合、組み込みのAngularサニタイズ関数を使用してください。
DomSanitizer.sanitizeメソッドと適切なSecurityContextを使用して、信頼されていない値をサニタイズします。
その関数は、以下で説明するように、bypassSecurityTrust 関数を使用して信頼済みとしてマークされた値も受け取り、サニタイズしません。
安全な値を信頼する
アプリケーションは、実行可能なコードを含めたり、特定のURLから<iframe>を表示したり、危険な可能性のあるURLを作成したりすることが必要な場合があります。
これらの状況で自動サニタイズを回避するには、値を検査して作成方法を確認し、安全であることを確認したことをAngularに伝えます。
注意してください。
悪意のある可能性のある値を信頼すると、アプリケーションにセキュリティの脆弱性が発生します。
疑問がある場合は、専門のセキュリティレビュアーに相談してください。
値を信頼済みとしてマークするには、DomSanitizerを注入し、次のいずれかのメソッドを呼び出します。
bypassSecurityTrustHtmlbypassSecurityTrustScriptbypassSecurityTrustStylebypassSecurityTrustUrlbypassSecurityTrustResourceUrl
覚えておいてください。値が安全かどうかはコンテキストに依存します。そのため、値の使用方法に適したコンテキストを選択してください。
次のテンプレートは、javascript:alert(...)呼び出しへのURLをhrefにバインディングする必要があるとします。
bypass-security.component.html (URL)
<h4>An untrusted URL:</h4>
<p><a class="e2e-dangerous-url" [href]="dangerousUrl">Click me</a></p>
<h4>A trusted URL:</h4>
<p><a class="e2e-trusted-url" [href]="trustedUrl">Click me</a></p>
通常、Angularは自動的にURLをサニタイズし、危険なコードを無効にし、開発モードではこの操作をコンソールにログ出力します。
これを回避するには、bypassSecurityTrustUrl呼び出しを使用して、URL値を信頼済みURLとしてマークします。
bypass-security.component.ts (trust-url)
private sanitizer = inject(DomSanitizer);
constructor() {
// javascript: URLs are dangerous if attacker controlled.
// Angular sanitizes them in data binding, but you can
// explicitly tell Angular to trust this value:
this.dangerousUrl = 'javascript:alert("Hi there")';
this.trustedUrl = this.sanitizer.bypassSecurityTrustUrl(this.dangerousUrl);
ユーザー入力を信頼済みの値に変換する必要がある場合は、コンポーネントメソッドを使用してください。
次のテンプレートでは、ユーザーはYouTubeビデオIDを入力し、対応するビデオを<iframe>に読み込むことができます。
<iframe src>属性はリソースURLセキュリティコンテキストです。なぜなら、信頼されていないソースは、たとえば、うっかりしたユーザーが実行する可能性のあるファイルダウンロードを密かに送り込むことができるからです。
これを防ぐために、コンポーネントのメソッドを呼び出して信頼済みビデオURLを作成すると、Angularは<iframe src>へのバインディングを許可します。
bypass-security.component.html (iframe)
<h4>Resource URL:</h4>
<p>Showing: {{ dangerousVideoUrl }}</p>
<p>Trusted:</p>
<iframe
class="e2e-iframe-trusted-src"
width="640"
height="390"
[src]="videoUrl"
title="trusted video url"
></iframe>
<p>Untrusted:</p>
<iframe
class="e2e-iframe-untrusted-src"
width="640"
height="390"
[src]="dangerousVideoUrl"
title="unTrusted video url"
></iframe>
bypass-security.component.ts (trust-video-url)
updateVideoUrl(id: string) {
// Appending an ID to a YouTube URL is safe.
// Always make sure to construct SafeValue objects as
// close as possible to the input data so
// that it's easier to check if the value is safe.
this.dangerousVideoUrl = 'https://www.youtube.com/embed/' + id;
this.videoUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.dangerousVideoUrl);
}
コンテンツセキュリティポリシー
コンテンツセキュリティポリシー(CSP)は、XSSを防ぐための防御の深化技術です。
CSPを有効にするには、Webサーバーを構成して、適切なContent-Security-Policy HTTPヘッダーを返すようにします。
コンテンツセキュリティポリシーについては、Google Developers WebサイトのWeb Fundamentalsガイドで詳しく説明されています。
まったく新しいAngularアプリケーションに必要な最小限のポリシーは次のとおりです。
default-src 'self'; style-src 'self' 'nonce-randomNonceGoesHere'; script-src 'self' 'nonce-randomNonceGoesHere';
Angularアプリケーションを提供する際、サーバーは各リクエストのHTTPヘッダーに、ランダムに生成されたnonceを含める必要があります。
このnonceをAngularに提供する必要があります。Angularは、<style>要素をレンダリングするためにnonceを使用します。
Angularのnonceは、次のいずれかの方法で設定できます。
- ワークスペース構成で
autoCspオプションをtrueに設定します。 - ルートアプリケーション要素に
ngCspNonce属性を設定します。index.htmlを作成するときに、ヘッダーとindex.htmlの両方にnonceを追加できるサーバー側のテンプレートがある場合は、この方法を使用します。 CSP_NONCE注入トークンを使用してnonceを提供します。実行時にnonceにアクセスでき、index.htmlをキャッシュする必要がある場合は、この方法を使用します。
import {bootstrapApplication, CSP_NONCE} from '@angular/core';
import {AppComponent} from './app/app.component';
bootstrapApplication(AppComponent, {
providers: [
{
provide: CSP_NONCE,
useValue: globalThis.myRandomNonceValue,
},
],
});
一意のnonce
提供するnonceは、リクエストごとに一意であること、予測したり推測したりできないことを常に確認してください。 攻撃者が将来のnonceを予測できる場合、CSPによって提供される保護を回避できます。
Generating a nonce at the origin server is generally discouraged when using a CDN, as responses are frequently cached. If the server generates a nonce and the CDN caches that HTML response, every subsequent visitor receives the same "unique" value, allowing an attacker to discover the static value and bypass CSP protections.
To maintain the "one-time-use" integrity of a nonce, it should ideally be generated at the Edge layer (e.g., CDN) just before the content is delivered to the user.
NOTE: アプリケーションのクリティカルCSSをインライン化したい場合、CSP_NONCEトークンは使用できません。autoCspオプションを使用するか、ルートアプリケーション要素にngCspNonce属性を設定してください。
プロジェクトでnonceを生成できない場合は、style-srcセクションに'unsafe-inline'を追加することで、インラインスタイルを許可できます。
| セクション | 詳細 |
|---|---|
default-src 'self'; |
ページが同じオリジンから必要なすべてのリソースを読み込むことを許可します。 |
style-src 'self' 'nonce-randomNonceGoesHere'; |
ページが同じオリジンからグローバルスタイル('self')を読み込むことを許可し、Angularによってnonce-randomNonceGoesHereで挿入されたスタイルを読み込むことを許可します。 |
script-src 'self' 'nonce-randomNonceGoesHere'; |
ページが同じオリジンからJavaScript('self')を読み込むことを許可し、Angular CLIによってnonce-randomNonceGoesHereで挿入されたスクリプトを読み込むことを許可します。これは、重要なCSSのインライン化を使用する場合にのみ必要です。 |
Angular自体が正常に機能するには、これらの設定のみが必要です。 プロジェクトが成長するにつれて、アプリケーション固有の追加機能に合わせて、CSP設定を拡張する必要がある場合があります。
Trusted Typesの強制
Trusted Typesを使用して、アプリケーションをクロスサイトスクリプティング攻撃から保護することをお勧めします。 Trusted Typesは、より安全なコーディング慣行を強制することで、クロスサイトスクリプティング攻撃を防ぐために役立つWebプラットフォーム機能です。 Trusted Typesは、アプリケーションコードの監査を簡素化するためにも役立ちます。
Trusted Types
Trusted Typesは、アプリケーションのターゲットとするすべてのブラウザでまだ利用できない場合があります。 Trusted Types対応のアプリケーションがTrusted Typesをサポートしていないブラウザで実行される場合、アプリケーションの機能は維持されます。アプリケーションは、AngularのDomSanitizerによってXSSから保護されます。 最新のブラウザサポートについては、caniuse.com/trusted-typesを参照してください。
アプリケーションでTrusted Typesを強制するには、アプリケーションのWebサーバーを構成して、次のAngularポリシーのいずれかでHTTPヘッダーを出力する必要があります。
| ポリシー | 詳細 |
|---|---|
angular |
このポリシーは、Angular内部のセキュリティレビュー済みコードで使用され、Trusted Typesが強制されたときにAngularが機能するために必要です。Angularによってサニタイズされた、インラインテンプレート値またはコンテンツは、このポリシーによって安全なものとして扱われます。 |
angular#bundler |
このポリシーは、Angular CLIバンドラーが、遅延チャンクファイルを生成する場合に使用されます。 |
angular#unsafe-bypass |
このポリシーは、AngularのDomSanitizerでセキュリティをバイパスするメソッド(bypassSecurityTrustHtmlなど)を使用するアプリケーションで使用されます。これらのメソッドを使用するアプリケーションは、このポリシーを有効にする必要があります。 |
angular#unsafe-jit |
このポリシーは、Just-In-Time (JIT) コンパイラで使用されます。アプリケーションがJITコンパイラと直接対話するか、プラットフォームブラウザダイナミックを使用してJITモードで実行されている場合は、このポリシーを有効にする必要があります。 |
angular#unsafe-upgrade |
このポリシーは@angular/upgradeパッケージで使用されます。アプリケーションが AngularJS ハイブリッドの場合、このポリシーを有効にする必要があります。 |
Trusted TypesのHTTPヘッダーは、次の場所で構成する必要があります。
- 本番環境のサービスインフラストラクチャ
- Angular CLI(
ng serve)、ローカル開発とエンドツーエンドテストのためにangular.jsonファイルのheadersプロパティを使用 - Karma(
ng test)、ユニットテストのためにkarma.config.jsファイルのcustomHeadersプロパティを使用
Trusted TypesとAngular用に構成されたヘッダーの例を以下に示します。
Content-Security-Policy: trusted-types angular; require-trusted-types-for 'script';
Trusted TypesとAngularアプリケーション用に構成されたヘッダーの例で、AngularのDomSanitizerでセキュリティをバイパスするメソッドをいずれか使用しています。
Content-Security-Policy: trusted-types angular angular#unsafe-bypass; require-trusted-types-for
+'script';
Trusted TypesとJITを使用するAngularアプリケーション用に構成されたヘッダーの例を以下に示します。
Content-Security-Policy: trusted-types angular angular#unsafe-jit; require-trusted-types-for
+'script';
遅延読み込みモジュールを使用するAngularアプリケーション用に構成されたヘッダーの例を以下に示します。
Content-Security-Policy: trusted-types angular angular#bundler; require-trusted-types-for 'script';
コミュニティの貢献
Trusted Type構成のトラブルシューティングについて詳しくは、次のリソースが役立つ場合があります。
AOTテンプレートコンパイラを使用する
AOTテンプレートコンパイラは、テンプレートインジェクションと呼ばれる一連の脆弱性を防ぎ、アプリケーションのパフォーマンスを大幅に向上させます。 AOTテンプレートコンパイラは、Angular CLIアプリケーションで使用されるデフォルトのコンパイラであり、本番環境のすべてのデプロイで使用する必要があります。
AOTコンパイラ以外の選択肢としては、JITコンパイラがあります。JITコンパイラは、実行時にブラウザでテンプレートを実行可能なテンプレートコードにコンパイルします。 Angularはテンプレートコードを信頼するため、テンプレートを動的に生成してコンパイルすると、特にユーザーデータを含むテンプレートの場合、Angularの組み込みの保護を回避することになります。これは、セキュリティ上のアンチパターンです。 フォームを安全な方法で動的に構築する方法については、動的フォームガイドを参照してください。
サーバー側のXSS保護
サーバーで構築されたHTMLは、インジェクション攻撃に対して脆弱です。 Angularアプリケーションにテンプレートコードを注入することは、アプリケーションに実行可能なコードを注入することと同じです。 攻撃者は、アプリケーションを完全に制御できます。 これを防ぐために、値を自動的にエスケープしてサーバー上のXSSの脆弱性を防ぐ、テンプレート言語を使用してください。 サーバー側でテンプレート言語を使用してAngularテンプレートを作成しないでください。これには、テンプレートインジェクションの脆弱性を導入するリスクが伴います。
HTTPレベルの脆弱性
Angularには、クロスサイトリクエストフォージェリ(CSRFまたはXSRF)とクロスサイトスクリプトインクルージョン(XSSI)という、2つの一般的なHTTP脆弱性を防ぐために役立つ組み込みのサポートがあります。 これらはどちらも、主にサーバー側で軽減する必要がありますが、Angularはクライアント側の統合を容易にするためのヘルパーを提供します。
クロスサイトリクエストフォージェリ
クロスサイトリクエストフォージェリ(CSRFまたはXSRF)では、攻撃者は悪意のあるコードを含む別のWebページ(evil.comなど)にユーザーを誘導します。このWebページは、アプリケーションのWebサーバー(example-bank.comなど)に秘密裏に悪意のあるリクエストを送信します。
ユーザーがexample-bank.comのアプリケーションにログインしているとします。
ユーザーはメールを開き、evil.comへのリンクをクリックします。このリンクは新しいタブで開きます。
evil.comページは、すぐにexample-bank.comに悪意のあるリクエストを送信します。
おそらく、ユーザーのアカウントから攻撃者のアカウントに資金を転送するリクエストです。
ブラウザは、認証Cookieを含むexample-bank.comのCookieを、このリクエストとともに自動的に送信します。
example-bank.comサーバーにXSRF保護がない場合、サーバーはアプリケーションからの正当なリクエストとevil.comからの偽造リクエストを区別できません。
これを防ぐためにアプリケーションは、ユーザーリクエストが別のサイトではなく実際のアプリケーションから発信されたものであることを確認する必要があります。 サーバーとクライアントは、この攻撃を阻止するために協力する必要があります。
一般的なXSRF対策では、アプリケーションサーバーは、ランダムに作成された認証トークンをCookieで送信します。 クライアントコードはCookieを読み取り、そのトークンを使用して、すべての後続のリクエストにカスタムリクエストヘッダーを追加します。 サーバーは、受信したCookie値とリクエストヘッダー値を比較し、値が欠落している場合や一致しない場合はリクエストを拒否します。
この方法は、すべてのブラウザが_同一オリジンポリシー_を実装しているため、有効です。
Cookieが設定されているWebサイトのコードのみが、そのサイトのCookieを読み取り、そのサイトへのリクエストにカスタムヘッダーを設定できます。
つまり、アプリケーションのみが、このCookieトークンを読み取り、カスタムヘッダーを設定できます。
evil.comの悪意のあるコードはできません。
HttpClientのXSRF/CSRFセキュリティ
HttpClientは、XSRF攻撃を防ぐために使用される一般的なメカニズムをサポートしています。HTTPリクエストを実行すると、インターセプターはCookieからトークン(デフォルトではXSRF-TOKEN)を読み取り、HTTPヘッダー(X-XSRF-TOKEN)として設定します。ドメイン上で実行されているコードのみがCookieを読み取ることができるため、バックエンドは、HTTPリクエストが攻撃者ではなく、クライアントアプリケーションから発信されたものであると確信できます。
デフォルトでは、インターセプターは、相対URLへのすべての変更リクエスト(POSTなど)でこのヘッダーを送信しますが、GET/HEADリクエストや絶対URLを持つリクエストでは送信しません。
GETリクエストを保護しないのはなぜ?
CSRF保護は、バックエンドのステートを変更する可能性のあるリクエストにのみ必要です。CSRF攻撃は、本来、ドメイン境界を跨いで行われるため、Webの同一オリジンポリシーにより、攻撃側のページが認証されたGETリクエストの結果を取得することはできません。
これを活用するには、サーバーは、ページの読み込み時または最初のGETリクエスト時に、XSRF-TOKENというJavaScriptで読み取り可能なセッションCookieにトークンを設定する必要があります。後続のリクエストでは、サーバーは、CookieがX-XSRF-TOKEN HTTPヘッダーと一致することを確認し、ドメイン上で実行されているコードのみがリクエストを送信できたことを確認できます。トークンはユーザーごとに一意である必要があり、サーバーで検証できる必要があります。これにより、クライアントが独自のトークンを作成することを防ぎます。トークンを、サイトの認証Cookieのダイジェストにソルトを付加した値に設定すると、セキュリティが向上します。
複数のAngularアプリケーションが同じドメインまたはサブドメインを共有する環境で競合を防ぐため、各アプリケーションに一意のCookie名を割り当てます。
HttpClientは、XSRF保護スキームのクライアント側のみをサポート
バックエンドサービスは、ページのCookieを設定し、すべての対象リクエストでヘッダーが存在することを確認するように構成する必要があります。そうしないと、Angularのデフォルトの保護は無効になります。
カスタムCookie/ヘッダー名の構成
バックエンドサービスでXSRFトークンCookieやヘッダーに異なる名前を使用している場合は、withXsrfConfigurationを使用してデフォルト値をオーバーライドします。
次の例のように、provideHttpClient呼び出しに追加します。
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(
withXsrfConfiguration({
cookieName: 'CUSTOM_XSRF_TOKEN',
headerName: 'X-Custom-Xsrf-Header',
}),
),
],
};
XSRF保護の無効化
組み込みのXSRF保護メカニズムがアプリケーションで機能しない場合は、withNoXsrfProtection機能を使用して無効にできます。
export const appConfig: ApplicationConfig = {
providers: [provideHttpClient(withNoXsrfProtection())],
};
Open Web Application Security Project(OWASP)のCSRFについては、クロスサイトリクエストフォージェリ(CSRF)とクロスサイトリクエストフォージェリ(CSRF)防止チートシートを参照してください。 スタンフォード大学の論文クロスサイトリクエストフォージェリに対する堅牢な防御は、詳細な情報源です。
また、Dave SmithのAngularConnect 2016でのXSRFに関する講演も参照してください。
クロスサイトスクリプトインクルージョン(XSSI)
クロスサイトスクリプトインクルージョンは、JSONの脆弱性としても知られており、攻撃者のWebサイトがJSON APIからデータを読み取ることを許可する可能性があります。
この攻撃は、古いブラウザで、組み込みのJavaScriptオブジェクトコンストラクターをオーバーライドし、<script>タグを使用してAPI URLを含めることで機能します。
この攻撃は、返されたJSONがJavaScriptとして実行可能である場合にのみ成功します。
サーバーは、すべてのJSONレスポンスの先頭に、よく知られている文字列")]}',\n"を使用して実行不能にすることで、攻撃を防ぐことができます。
AngularのHttpClientライブラリは、この規則を認識し、さらに解析する前に、すべてのレスポンスから文字列")]}',\n"を自動的に削除します。
詳細については、Google Webセキュリティブログの投稿のXSSIセクションを参照してください。
Preventing Server-Side Request Forgery (SSRF)
Angular includes strict validation for Host, X-Forwarded-Host, X-Forwarded-Proto, X-Forwarded-Prefix and X-Forwarded-Port headers in the request handling pipeline to prevent header-based Server-Side Request Forgery (SSRF).
The validation rules are:
HostandX-Forwarded-Hostheaders are validated against a strict allowlist and cannot contain path separators.X-Forwarded-Portheader must be numeric.X-Forwarded-Protoheader must behttporhttps.X-Forwarded-Prefixheader must start with/and contain only alphanumeric characters, hyphens, and underscores, separated by single slashes.- By default, all
X-Forwarded-*headers are treated as untrusted and are removed from the request. To retain them, they must be explicitly allowed by configuringtrustProxyHeaders.
Invalid headers trigger an error log, and unallowed proxy headers are removed from the request. Requests with unrecognized hostnames will result in a 400 Bad Request is issued.
NOTE: Most cloud providers and CDN providers perform automatic validation of these headers before a request ever reaches the application origin. This inherent filtering significantly reduces the practical attack surface.
Configuring allowed hosts
To allow specific hostnames, you need to add them to the allowlist. This is critical for ensuring your application works correctly and securely when deployed. The patterns support wildcards for flexible hostname matching.
You can configure the allowedHosts option in your angular.json:
{
// ...
"projects": {
"your-project-name": {
// ...
"architect": {
"build": {
"builder": "@angular/build:application",
"options": {
"security": {
"allowedHosts": [
"example.com",
"*.example.com" // allows all subdomains of example.com
]
}
// ... other options
}
}
}
}
}
}
You can also configure allowedHosts when initializing the application engine:
const appEngine = new AngularAppEngine({
allowedHosts: ['example.com', '*.trusted-example.com'],
});
const nodeAppEngine = new AngularNodeAppEngine({
allowedHosts: ['example.com', '*.trusted-example.com'],
});
For the Node.js variant AngularNodeAppEngine, you can also provide NG_ALLOWED_HOSTS (comma-separated list) environment variable for authorizing hosts.
export NG_ALLOWED_HOSTS="example.com,*.trusted-example.com"
IMPORTANT: You can use * as a value in allowedHosts to allow all hostnames, though this is generally discouraged and presents a security risk. Accepting any host header can expose your application to host header injection and Server-Side Request Forgery (SSRF) attacks. This configuration should only be used when validation for Host and X-Forwarded-Host headers is performed in another layer, such as a load balancer or reverse proxy. For better security, we recommend using an explicit list of allowed hosts whenever possible. See GHSA-x288-3778-4hhx for more details.
Configuring trusted proxy headers
By default, Angular ignores all X-Forwarded-* headers. If your application is behind a trusted reverse proxy (like a load balancer) that sets these headers, you can configure Angular to trust them.
You can configure trustProxyHeaders when initializing the application engine:
const appEngine = new AngularAppEngine({
trustProxyHeaders: ['x-forwarded-host', 'x-forwarded-proto'], // Trust specific headers
});
const nodeAppEngine = new AngularNodeAppEngine({
trustProxyHeaders: true, // Trust all X-Forwarded-* headers
});
IMPORTANT: Only enable trustProxyHeaders if your application is behind a trusted proxy that strictly validates or overrides these headers. Otherwise, attackers can spoof these headers to cause Server-Side Request Forgery (SSRF) attacks.
Angularアプリケーションの監査
Angularアプリケーションは、通常のWebアプリケーションと同じセキュリティ原則に従う必要があり、同様に監査する必要があります。 セキュリティレビューで監査する必要があるAngular固有のAPI(bypassSecurityTrustメソッドなど)は、ドキュメントでセキュリティに敏感なものとしてマークされています。