In this article
JavaScriptのセキュリティ
JavaScriptの脆弱性とベストプラクティスを解説
ほぼすべてのプログラミング言語と同様に、JavaScriptにも潜在的なセキュリティ上のリスクがあります。JavaScriptの脆弱性を悪用されると、データの操作、セッションのリダイレクト、データの改ざんや窃取などが行われる可能性があります。JavaScriptは通常クライアントサイドのアプリケーションで使われるものと考えられていますが、JavaScriptのセキュリティ問題はサーバーサイド環境でも問題を引き起こすことがあります。
よくあるJavaScriptのセキュリティ脆弱性に対する最善の防御策は、それらを把握し、適切な対策を実施してリスクを低減することです。
2023年におけるJavaScriptのセキュリティ脆弱性
JavaScriptでよく見られる脆弱性には、クロスサイトスクリプティング(XSS)、悪意のあるコード、中間者攻撃、Webアプリケーションのソースコードに潜む脆弱性の悪用などがあります。開発中にコードをスキャンして脆弱性を検出し、開発者にセキュリティ教育を行うことで、こうした脆弱性を防止できます。
この記事では、よくあるJavaScriptの脆弱性と、一般的な最新のセキュリティ対策にテストツール(監査・コード解析ツール、JavaScriptの脆弱性スキャナーなど)を組み合わせて、それらを防ぐ方法をご紹介します。
JavaScriptセキュリティとは?
JavaScriptセキュリティとは、JavaScriptを使用するアプリケーションにおけるセキュリティ問題の調査、防止、保護、解決に関するものです。
JavaScriptは、Webアプリケーションの構築に欠かせない技術であり、サーバーサイド、デスクトップ、さらにはモバイルアプリケーションの開発でも広く使われています。しかし、その普及率の高さゆえに、さまざまな攻撃経路を通じて狙われる格好の標的にもなっています。JavaScriptは主にフロントエンドで使用されるため、まずはブラウザーにおけるJavaScriptのセキュリティ問題に注目するのがよいでしょう。
ソフトウェアベンダーもこうしたJavaScriptのセキュリティ問題を認識しており、JavaScriptセキュリティスキャンソフトウェアやさまざまなJavaScriptセキュリティテストツールを提供しています。これらのツールはアプリケーションの安全性を高め、JavaScriptのセキュリティリスクを大幅に低減します。JavaScriptコードチェッカーを試して、コードの脆弱性を見つけましょう。
よくあるJavaScriptの脆弱性とは?
よくあるJavaScriptの攻撃経路には、悪意のあるスクリプトの実行、ユーザーの既存のセッションデータやブラウザーのlocalStorageからのデータ窃取、ユーザーを意図しない操作に誘導すること、Webアプリケーションのソースコードにある脆弱性の悪用などがあります。
もちろん、このリストですべてを網羅しているわけではありません。ここでは、Webアプリケーションのフロントエンドに重点を置いています。
8つのJavaScriptセキュリティ脆弱性

1. ソースコードの脆弱性
ソースコードの脆弱性は、ほかのJavaScriptのセキュリティホール、場合によっては複数の脆弱性と組み合わさることがよくあります。残念ながら、このようなケースでは、JavaScriptの難読化だけで脆弱性を防いだり隠したりすることはできません。JavaScriptはコンパイル言語ではなくインタープリター言語であるため、この方法でアプリケーションコードを潜在的な攻撃者による解析から保護することは、ほぼ不可能です。それでも、難読化はリバースエンジニアリングを遅らせるため、有効な対策です。
ソースコードにセキュリティホールが生じるもう一つの原因は、公開パッケージやライブラリが広く使われていることです。JavaScriptエコシステムの主要なサービスであるNPMのレジストリには、100万を超えるパッケージが登録されています。豊富な選択肢は大きな利点ですが、その一方で、Webアプリケーションのプロジェクトにインストールされるパッケージに、膨大な数の潜在的な脆弱性が存在する可能性もあります。
さらに、開発者はごく簡単な作業にもパッケージをインストールすることが多く、その結果、プロジェクトの依存関係が増えていきます。これがセキュリティ問題や、その他の広範囲に及ぶ影響につながることもあります。
アプリケーションの依存関係にある潜在的な脆弱性をすべて監視して対処するには時間と手間がかかりますが、監査ツールを使えばプロセスを自動化し、迅速化できます。
ソースコードに起因するJavaScriptのセキュリティ問題を防ぐには、次のような多角的なアプローチが必要です。
開発者のベストプラクティスに対する理解を深める
アプリケーションコードを適切に監査し、潜在的な脆弱性を検出する
コードが想定どおりに動作するだけでなく、安全に実行されることを確認する単体テストを作成する
アプリケーションを動的にスキャンし、サードパーティのパッケージやライブラリにあるJavaScriptのセキュリティ問題を特定するツールを導入する
2. 意図しないスクリプトの実行
意図しないスクリプト実行攻撃の大半は、クロスサイトスクリプティング(XSS)に関係しています。JavaScriptに関連する特有の懸念は、Webページ上のDocument Object Model(DOM)との連携により、スクリプトを埋め込んでWeb上のクライアントコンピューターで実行できることです。XSS攻撃にはさまざまな種類がありますが、いずれも信頼できないスクリプトをユーザーのブラウザーに表示して実行させる点は共通しています。
最も基本的なXSS攻撃の例として、ユーザー同士がページ上でメッセージを閲覧できるフォーラムサイトでの攻撃があります。メッセージに含まれるHTMLやJavaScriptが適切にエンコードされていないと、悪意のあるユーザーがフォーラムにスクリプトを投稿できる可能性があります。
このようなスクリプトが投稿されると、エンドユーザーはアプリケーションを実行するだけで、意図せず攻撃に加担する被害者となります。悪意のあるコードは、Webページの一部であるかのように表示されます。
XSS攻撃を防ぐため、開発者はユーザー入力やサーバーからの出力を処理する際、文字列データのエスケープ、フィルタリング、検証を組み合わせたサニタイズを行う必要があります。
3. ユーザー入力のエスケープ/エンコード
XSS攻撃では、Webページの基盤となるHTML、JavaScript、CSSで使われる特定の特殊文字を含むデータが送信されます。ブラウザーがWebページをレンダリングする際にこれらの文字に遭遇すると、表示する値ではなく、Webページのコードの一部として認識します。そのため、攻撃者はテキストフィールドを抜け出し、ブラウザー側で実行される追加コードを挿入できます。
これを防ぐには、ブラウザーから送信されたデータをレスポンスで返すとき(その場で返す場合も、データベースから取得して返す場合も)、必ずこれらの特殊文字を対応するエスケープコードに置き換えます。
たとえば、HTMLエンティティの区切りに使われる < と > の文字は、< と > に置き換えることができます。これによりブラウザーは、これらの文字をHTMLエンティティとして解釈せず、文字として表示します。ブラウザーから送信されたデータをJavaScriptコンテキストで返す場合は、英数字以外の文字を、各文字の16進数ASCII値をNNとしてxNNでエスケープします。
4. 入力のフィルタリング
場合によっては、入力データから危険な文字を単純に削除する方法が適しています。ある程度の保護にはなりますが、データ操作に対する唯一の防御策として頼るべきではありません。攻撃者はさまざまな手法でフィルターを回避できます。
5. 入力の検証
可能な限り、ブラウザーから送信された入力が想定された文字のみを含んでいることを検証します。たとえば、電話番号のフィールドには数字と、必要に応じてハイフンや括弧のみを入力できるようにします。想定外の文字を含む入力は、直ちに拒否する必要があります。フィルターは、許可する文字を特定し、それ以外をすべて拒否するように設定します。
6. クライアントサイドの検証だけに頼る
ここまでに説明した方法はブラウザー上で有効ですが、攻撃者は特殊なツールを使ってサーバーに直接データを送信し、クライアントサイドの検証を回避することがあります。これにより、悪意のあるデータや未検証のデータがサーバーに入力される可能性があります。サーバーサイドで追加の検証を行わなければ、保存データが破損したり、誤ったデータに置き換えられたりするおそれがあります。
このような事態を防ぐためのベストプラクティスは、クライアントサイドとサーバーサイドの両方で検証を実施することです。この方法なら、不正なデータのリスクを低減しながら、エンドユーザーの操作性を高めるクライアント側の検証機能も提供できます。
サーバーサイドだけで検証すると、すべての検証に合格するまでオンラインフォームに何度も入力しなければならず、ユーザーにとって煩雑になる場合があります。JavaScriptによる検証で入力の問題をすぐにユーザーに知らせる一方、サーバー側の検証によって、想定されたデータだけがアプリケーションに取り込まれるようにします。
7. セッションデータの窃取
クライアントサイドのブラウザースクリプトは、Webアプリケーションからブラウザーに返されるすべてのコンテンツにアクセスできるため、非常に強力です。これには、ユーザーのセッションIDなどの機密データを含む可能性のあるCookieも含まれます。実際、XSS攻撃でよく使われる手口の一つは、ユーザーのセッションIDトークンを攻撃者に送信し、セッションを乗っ取れるようにすることです。
これを防ぐために、現在はほとんどのブラウザーがCookieのHttp-Only属性に対応しています。サーバーがブラウザーにCookieを設定する際にHttp-Only属性を指定すると、ブラウザーはDOMからCookieにアクセスできないようにします。これにより、クライアントサイドスクリプトを使った攻撃がCookieに保存された機密データへアクセスするのを防げます。
ブラウザーのローカルストレージやセッションストレージにあるデータも同様に窃取される可能性がありますが、DOMアクセスを通じて保護することはできません。そのため、Webアプリケーションのアーキテクチャ上の特定の機能で必要な場合を除き、トークンなどの機密情報をブラウザーのストレージに保存しないことが最善です。
8. ユーザーを意図しない操作に誘導する
クロスサイトリクエストフォージェリ(CSRF)攻撃は、ユーザーがそのサイトを開いていなくても、すでにログインしているWebサイトに対してブラウザーに悪意のあるリクエストを実行させようとします。標的サイトがCookieベースのセッションを使用している場合、そのサイトへのリクエストに認証Cookieが自動的に付加されることがあります。
攻撃者は独自のWebページを作成し、ユーザーがそのページを開いたときに、バックグラウンドでほかのサイトに悪意のあるリクエストを送信させることもできます。また、ソーシャルメディアやフォーラムなどのプラットフォームに悪意のあるリンクやコンテンツを投稿し、ユーザーのセッションCookieを使って、ブラウザーからほかのサイトへのリクエストを気付かれないように送信させることもあります。
この脆弱性を回避する一般的な方法は、Cookieに保存されない追加のトークンを導入し、クライアントとサーバー間の通信をトークン化することです。セッション確立時にWebサイト上の各フォーム用のトークンを生成し、ユーザーがサイトを利用している間、各リクエストと一緒に送信する必要があります。
JavaScriptのセキュリティ問題にどう対処する?
JavaScriptの脆弱性からアプリケーションやサーバーを保護するには、JavaScriptセキュリティのベストプラクティスを取り入れ、高度なスキャンツールを活用します。
Web開発の現場では、ソフトウェアエンジニアは新たに発生するJavaScriptのセキュリティリスクを常に把握する必要があります。アプリケーションの機能テストが重要なのはもちろんですが、JavaScriptセキュリティテストツールを定期的に使用することも、脆弱性を防ぐうえで重要です。さらに、シンプルで一般的なベストプラクティスに従うことで、アプリケーションの堅牢性を高められます。
次のJavaScriptセキュリティのベストプラクティスで、リスクを軽減できます。
**eval()**を避ける:渡された引数がJavaScriptの式であれば実行してしまうため、このコマンドをコードで使用しないでください。攻撃者が入力値を操作できた場合、任意のスクリプトを実行できることを意味します。代わりに、より安全な方法を選びましょう。
暗号化する:HTTPS/SSLを使用して、クライアントとサーバー間でやり取りするデータを暗号化します。
セキュアCookieを設定する:SSL/HTTPSが使用されるよう、Cookieを「secure」に設定します。これにより、アプリケーションのCookieはセキュアなWebページでのみ使用されます。
APIアクセスキーを設定する:エンドユーザーごとに個別のトークンを割り当てます。トークンが一致しない場合は、アクセスを拒否または取り消せます。
使用 安全なDOM操作メソッドを使用する:innerHTMLなどのメソッドは強力ですが、渡された値を制限したり、エスケープ/エンコードしたりしないため、潜在的な危険性があります。代わりにinnerTextのようなメソッドを使えば、危険性のあるコンテンツを自動的にエスケープできます。これは、DOMベースのXSS攻撃を防ぐうえで特に有効です。
JavaScriptのセキュリティ上の問題を特定することは、アプリケーション開発における脆弱性を防ぐための重要な第一歩です。オープンソースの脆弱性スキャナーで、今すぐコードをテストしましょう。