入力と出力

完了

今日のアプリケーションで最もよく見られるセキュリティ上の弱点は、外部ソースから受信したデータ、特にユーザー入力を正しく処理できないことです。 どのような入力であれ、必ず詳細に調べて、使用する前に必ず妥当であることを検証するようにしてください。 攻撃の可能性があるユーザー入力の分析を怠ると、データの損失や露出、特権の昇格、さらには他のユーザーのコンピューター上で悪意のあるコードが実行されてしまうことにさえなり得ます。

このような状況の悲劇は、このシナリオが簡単に解決できる問題である点です。 このユニットでは、受信時、画面への表示時、または保存時のデータの処理方法を取り上げます。

なぜ入力を検証する必要があるのか

Web サイトでアカウントを作成できるようにするインターフェイスを構築しているときのことを考えてみてください。 プロファイル データには、サイトにアクセスするユーザーの全員に表示される名前、メールアドレス、ニックネームが含まれます。 新しいユーザーがプロファイルを作成し、SQL コマンドを含むニックネームを入力したら、どうでしょう。 たとえば、悪意のあるユーザーが次のような内容を入力したら、どうなるでしょうか。

Eve'); DROP TABLE Users;--

この値が知らない間にデータベースに挿入されると、絶対に実行したくないコマンドを実行するように SQL ステートメントが改変される可能性があります。 これは、"SQL インジェクション" 攻撃と呼ばれる、数多くの悪用の 1 つで、正しくユーザー入力を処理しなかったときに発生する可能性があります。 この状況を解決するためには、何をすればよいのでしょうか。 このユニットでは、(上述の悪用を解決する) 入力を検証するタイミングと出力のエンコード方法、パラメーター化クエリを作成する方法を学びます。 アプリケーションに入力される悪意のある入力に対する防御手法は大きく 3 つあります。

いつ入力を検証すればよいのか

答えは常にです。 アプリケーションに対するあらゆる入力を検証する必要があります。 これには、URL のパラメーター、ユーザーからの入力、データベースからのデータ、API からのデータ、その他のユーザーが操作できる可能性があるクリアな形式で渡されるあらゆるものが含まれます。 "ブロックリスト" (不正な入力だけを探す) は、潜在的に危険な入力を完全に網羅することが不可能なため、この代わりに、常に "許可リスト" 方式を使用してください。これは "既知の問題がない" 入力だけを受け付けることを意味します。 この防御策が回避できないよう、この作業はクライアント側ではなく、サーバー側で行ってください (両方で行ってもよい)。 すべてのデータを信頼できないものとみなしてください。そうすることで、Web アプリでよくある脆弱性の多くから身を守ることができます。

ASP.NET を使用している場合、そのフレームワークには、クライアントとサーバーの双方で入力を検証するための優れたサポートが用意されています。

別の Web フレームワークを使用している場合は、OWASP の「入力検証チート シート」 に入力を検証するための素晴らしいテクニックがいくつか用意されています。

常にパラメーター化クエリを利用する

SQL データベースは、通常、データを格納するために使用されます。たとえば、アプリケーションでユーザー プロファイル情報をデータベースに格納することができます。 コードに生のユーザーによる入力を使ったインライン SQL やその他のデータベース クエリを作成して、直接データベースに送信しないでください。既に説明したように、これは災難を招く行為です。

たとえば、次のようなインライン SQL のコードを作成してはいけません

string userName = Request.QueryString["username"]; // receive input from the user BEWARE!
...
string query = "SELECT *  FROM  [dbo].[users] WHERE userName = '" + userName + "'";

ここでは、テキスト文字列を連結して、クエリを作成しています。ユーザーから入力を受け取り、ユーザーを検索する動的な SQL クエリを生成します。 ここでも、悪意のあるユーザーがこれを行っていることに気付いた場合、あるいは脆弱性があるかどうかを見るためにいくつかの入力を試しただけでも、重大な障害が生じる場合があります。 代わりに、次などの、パラメーター化 SQL ステートメントやストアド プロシージャを利用します。

-- Lookup a user
CREATE PROCEDURE sp_findUser
(
@UserName varchar(50)
)

SELECT *  FROM  [dbo].[users] WHERE userName = @UserName

このメソッドでは、コードからそのプロシージャを安全に呼び出し、SQL ステートメントの一部として扱われることを心配せずに userName の文字列を渡すことができます。

必ず出力をエンコードする

ビジュアルに、またはドキュメントのいずれかに出力を行う場合、必ずエンコードして、エスケープされる必要があります。 これにより、サニタイズの過程で何かが欠落した場合、またはコードが悪意を持って使用されるおそれがあるものを誤って生成した場合に、ユーザーを保護できます。 この設計の原則では、すべてが出力 として表示されるため、何かが誤って実行されることがなくなります。これは "クロスサイト スクリプティング" (XSS) と呼ばれるもう 1 つの一般的な攻撃手法です。

XSS の防止は一般的なアプリケーションの要件であるため、このセキュリティ手法はお客様に代わって ASP.NET が作業を実行するもう 1 つの領域です。 既定では、すべての出力が既にエンコードされています。 別の Web フレームワークを使用している場合は、OWASP の「クロスサイト スクリプティング (XSS) 防止のチート シート」 で Web サイトでの出力エンコードに関するオプションを確認できます。

まとめ

入力のサニタイズと検証は、入力が確実に有効であり、安全に使用、保存できるようにするための必須要件です。 最新の Web フレームワークのほとんどには、この作業の一部を自動化する機能が組み込まれています。 お好みのフレームワークで提供されている機能については、そのドキュメントを確認してください。 これが一番よく起こる場所は Web アプリケーションですが、他の種類のアプリケーションも同様に脆弱であることを念頭に置いておいてください。 ご使用の新しいアプリケーションがデスクトップ アプリであるからといって、ご自分が安全であるとは考えないでください。 アプリを使用してデータが破壊されたり、会社の評判が落とされたりすることのないよう、いつでもユーザーによる入力を適切に処理する必要があります。

知識を確認

1.

検証の必要があるデータ ソースは次のどれでしょうか?

2.

パラメーター化クエリ (SQL ではストアド プロシージャ) は、次の理由から、データベースと通信する方法として安全です。

3.

エンコードしてから出力する必要があるデータは次のどれですか?