JavaScriptの脆弱性からWebアプリケーションを保護する
Emily Parker
Product Engineer · Leapcell

JavaScriptの脆弱性からWebアプリケーションを保護する
はじめに
今日の相互接続されたデジタルランドスケープにおいて、Webアプリケーションはオンラインバンキングからソーシャルメディアまで、無数のサービスのバックボーンとなっています。前例のない利便性と機能性を提供する一方で、この広範な依存関係は、悪意のある攻撃者にとって格好の標的にもなります。これらの攻撃の大部分は、Webアプリケーションがユーザー提供データを処理・相互作用する方法、特にJavaScript環境内で発生する脆弱性を利用しています。これらの一般的なセキュリティ上の欠陥を理解し、軽減することは、単なる良い習慣に留まらず、ユーザーのプライバシーを保護し、データの整合性を維持し、デジタルインフラストラクチャの信頼性を確保するために絶対に必要なことです。本稿では、JavaScriptに関連する3つの非常に一般的なWebアプリケーションの脆弱性、すなわちクロスサイトスクリプティング(XSS)、クロスサイトリクエストフォージェリ(CSRF)、およびプロトタイプ汚染に焦点を当て、それらのメカニズム、実用的な例による危険性、そして効果的な防御戦略の概要を説明します。
主要なWebアプリケーションの脆弱性の理解と防御
各脆弱性の詳細に入る前に、これらの攻撃がどのように機能するか、そしてどのように防御するかを支えるいくつかの主要な概念を明確にしましょう。
コア用語:
- クライアントサイドスクリプティング: サーバーサイドコードとは対照的に、ユーザーのWebブラウザで直接実行されるコード(最も一般的にはJavaScript)を指します。これにより、動的でインタラクティブなWeb体験が可能になりますが、潜在的な攻撃ベクトルも導入されます。
- HTMLエスケープ/サニタイゼーション: 文字列内の特殊文字(
<
、>
、&
、"
、'
、/
)をHTMLエンティティ等価物(例:<
が<
になる)に変換するプロセスです。これにより、ブラウザがユーザー提供データ_を_実行可能なHTMLやJavaScriptとして解釈するのを防ぎます。サニタイゼーションは、HTML内の潜在的に有害なスクリプトや属性を削除または無効化することで、さらに一歩進みます。 - オリジン: URLのスキーム(プロトコル)、ホスト(ドメイン)、およびポートによって定義されます。同一オリジンポリシー(SOP)は、あるオリジンからロードされたドキュメントやスクリプトが、別のオリジンからのリソースとどのように相互作用できるかを制限する重要なセキュリティメカニズムです。
- HTTP Cookie: Webサーバーによってユーザーのコンピュータに保存される小さなデータ片です。これらは、セッション管理、パーソナライゼーション、およびトラッキングによく使用されます。
- HTTPヘッダー: HTTPリクエストおよびレスポンスと共に送信される情報の行であり、通信に関するメタデータを提供します。
- DOM (Document Object Model): HTMLおよびXMLドキュメントのプログラミングインターフェイスです。ページ構造をオブジェクトのツリーとして表現し、JavaScriptが要素、コンテンツ、スタイルにアクセスして操作できるようにします。
それでは、脆弱性を探ってみましょう。
クロスサイトスクリプティング (XSS)
XSS攻撃は、攻撃者が他のユーザーが見るWebページに悪意のあるクライアントサイドスクリプトを注入したときに発生します。被害者のブラウザがこのスクリプトを実行すると、セッションハイジャック、ウェブサイトの改ざん、悪意のあるサイトへのリダイレクト、または機密データの盗難につながる可能性があります。
XSSには主に3つのタイプがあります。
-
Stored XSS(持続的XSS): 悪意のあるスクリプトは、ターゲットサーバー(例: データベース、コメントセクション、フォーラム投稿)に永続的に保存されます。被害者が汚染されたページをリクエストすると、サーバーは保存されたスクリプトを取得し、ブラウザに送信します。その後、ブラウザがそれを実行します。
例シナリオ: 悪意のあるユーザーがブログにコメントを投稿します。
<script>alert('You have been hacked! Session ID: ' + document.cookie);</script>
ブログアプリケーションがこのコメントを直接保存し、適切なエスケープなしで表示した場合、そのコメントを表示するすべてのユーザーが
alert
スクリプトを実行し、セッションクッキーが露出する可能性があります。 -
Reflected XSS(非持続的XSS): 悪意のあるスクリプトはWebサーバーで反射(リフレクト)され、通常はエラーメッセージ、検索結果、またはユーザーがリクエストの一部として送信した入力の一部または全部を含む他の応答に含まれます。スクリプトは永続的に保存されません。
例シナリオ: 脆弱な検索ページが検索クエリを応答に直接表示します:
http://example.com/search?query=<script>alert('Reflected XSS!');</script>
ユーザーがこの特別に細工されたリンクをクリックすると、ブラウザは注入されたスクリプトを実行します。 -
DOMベースXSS: 脆弱性はクライアントサイドコード自体にあり、スクリプトがユーザー提供データを使用してDOMを安全でない方法で変更します。サーバーサイドは、悪意のあるペイロードの作成や保存には一切関与しません。
例シナリオ: クライアントサイドJavaScriptスニペットがURLパラメータを取得し、それをHTMLに直接挿入します。
// Vulnerable code const param = new URLSearchParams(window.location.search).get('name'); document.getElementById('welcomeMessage').innerHTML = 'Welcome, ' + param; // Attack URL: http://example.com/?name=<img src=x onerror=alert('DOM%20XSS!')>
ここでは、
onerror
属性を持つ<img>
タグが、src=x
がロードに失敗した場合にJavaScriptを実行でき、DOMベースXSSを示しています。
XSSのための防御戦略:
-
出力エンコーディング/エスケープ: 最も重要な防御策です。ユーザー提供データをHTMLにレンダリングする前に、常に特殊文字をエスケープしてください。これにより、ブラウザはデータを実行可能なコードではなくコンテンツとして解釈するようになります。
// Example: Server-side (Node.js with Express and a template engine like EJS) // In a template: <%= userInput %> (EJS automatically escapes by default) // Manual escaping for JavaScript context (e.g., injecting into a <script> block) function escapeHtml(str) { return str.replace(/[&<>