なぜユーザーのパスワードを保存するのですか?


10

Webアプリケーションのユーザーパスワードを安全に保存する方法を尋ねる質問がときどきあります(RDBMSを使用して、私はFacebookやTwitterについて話していません)。通常の答えは、「パスワードをソルト化してから、TDESやSHA512などの強力なアルゴリズムでハッシュする」です。

私の質問は次のとおりです。RDBMSユーザーとして、ほとんどのエンジンには認証メカニズムが組み込まれているため、パスワードの保存にまったく問題がないのはなぜですか。

たとえば、一部のユーザーXが自分のWebアプリケーションでアカウントユーザーパスワードYを作成したい場合、次のクエリを間違って発行するとどうなりますか。

CREATE USER X WITH ENCRYPTED PASSWORD Y IN GROUP baseuser;

次に、私のアプリケーション内で、ユーザーは自分の資格情報を使用してデータベースへの接続を開くことができ、パスワード管理のすべてに煩わされる必要はありません。

この方法にはいくつかの利点があります。

  • 暗号化アルゴリズムを変更する必要があるとRDBMSが判断した場合、セキュリティ更新を適用するだけで、何もする必要はありません。
  • ユーザーの承認を管理するのは簡単です。ユーザーが管理者の役割に昇格された場合、ユーザーを対応するグループに追加するだけです。
  • SQLインジェクションは無意味になりました。データベース内の各ユーザーに許可したいものを正確に許可する権限を管理しているためです(たとえば、SOのようなフォーラムで、新しい投稿の追加、投稿への回答、コメントおよび自分の質問の編集/削除)。 / answers / comments);
  • ユーザーアカウント "匿名"は、アプリケーションへの認証されていない接続に使用できます。
  • 各ユーザーは、提供したデータの所有者です。

しかし、このトピックに関して私が見るほぼすべての質問について、これは物事を実行する方法ではないという一般的なコンセンサスがあるようです。私の質問は:なぜですか?

注:三点目は、によって許可されたポリシー PostgreSQLで、かつセキュリティポリシーのMicrosoft SQL Serverのインチ これらの概念は新しいものであることがわかりましたが、とにかく、ここにあるので、ここで説明する手法がユーザーアカウントを処理する標準的な方法にならないのはなぜですか。


2
コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
ポールホワイト9

ちなみに、通常の答えは間違っています。パスワードをソルト処理してから、bcryptやargon2などの低速アルゴリズムでハッシュする必要があります。
Tgr

回答:


27

多くのアプリケーションでは、個々のユーザーアカウントがデータベースに接続することを望んでいないためです。users / passwords / rights / permissionsはすべてアプリケーション層で処理され、単一の専用サービスアカウントがデータベースバックエンドへの接続に使用されます。

DBAとして、私はデータベースレベルで、中規模の一般向けWebアプリケーションの10,000人のアクティブユーザー、または突然人気のあるアプリの200万人以上のユーザーを管理する必要はありません。

実のところ、これはアプリケーション開発者とデータベース開発者/ DBAの間の哲学の違いです。

多くの/ほとんどのアプリケーション開発者は、アプリの機能やビジネスルールの主要な側面の責任をデータベースレイヤーに移したくないでしょう。代わりに、データベースを単にデータを格納および取得するためのツールと見なします。

場合によっては、これは近視眼的です。多くのRDBMSには、アプリ開発をより簡単にする素晴らしい機能があります(行レベルのセキュリティ、列インデックス、ファイルストリームストレージなど)。

ただし、これらの優れた機能の一部は新しいバージョンでのみ利用可能であり、組織が既存の環境をすぐにアップグレードできるとは限りません(2014年のこのグラフを参照)。

そして、他の場合では、それらをアプリケーション層で処理することが推奨されます(データベースプラットフォームの移植性だけでなく、率直に言って、主張は誇張されていると思います)。


2
ビジネスロジックがアプリケーションに含まれるかデータベースに含まれるかに、「聖戦」が存在します。すべてのビジネスロジック(特にセキュリティ)がデータベースにある(ストアドプロシージャ、ビューなどを使用して)アプリケーションを構築した場合、誰も直接接続して回避することができないため、データベースセキュリティメカニズムを利用する引数があるかもしれません。セキュリティ。カスタムテーブルでセキュリティメカニズム(つまり、ログイン/パスワード)を「再構築」することは避けるべきだと私は完全に同意します。Active Directory / O365のセキュリティが既にあるのに、なぜそうするのでしょう。
Nick.McDermaid 2017年

1
@ Nick.McDermaid私は、DBとアプリケーションの間でビジネスロジックを公平に混合して、将来の開発者が何が起こっているのかわからない手がかりを取り除く可能性を排除することを確認したいです。それを管理したいほど十分です。
Der Kommissar 2017年

WebサービスとTomcatアプリケーションサーバーをそこに
投入

8

分割線はその時点で少しふわふわになっていますが、データベースレベルのユーザーと権限はデータの一部ではなくスキーマの一部であると考えます。一般に、アプリケーションはスキーマを変更する場所がありません(ある、いつものように、このルールの例外)。

新しいユーザーが必要になり、古いユーザーが去るので、アプリケーションにスキーマオブジェクト(ログイン、ユーザー、権限)を管理するために必要な権限を与えたくありません。アプリケーションがハッキングされると、攻撃者はそれらの権限にアクセスできるからです。データベースをさらに開くことを容易にします。MS SQL Serverでは、完全に包含されたデータベースを使用していない限り、ログインはサーバーレベルのオブジェクトであるため、単一のアプリケーションデータベースを超えて権限を渡す必要があるため、データベースのリスクがさらに高くなります。

さらに、データベースレベルでアプリケーションごとのユーザーアカウントがある場合でも、認証されていない要求を処理するためにアプリケーションレベルのユーザーアカウントが必要です。つまり、アプリケーションのユーザーが認証に成功する前に、アプリケーションがデータベースからの情報を必要とする場合(おそらくウェルカム/ログイン画面にステータス情報を表示しますか?)。

また、データベースエンジン間の移植性が目標である場合(おそらく、アプリをmysqlとpostgresの両方で実行できるようにしたい場合)、アプリケーションは各エンジンのユーザー/ログイン管理機能を抽象化する必要があります。 -その努力をするなら、エンジンが提供する最も一般的な機能セットを受け入れる代わりに、自分でパスワードを実装して、希望する管理オプションを取得することもできます。


1
わかりましたので、「アプリケーションでスキーマを変更してはなりません」は、私が提案する手法に対する最初の良い点だと私は考えています。ただし、新しいユーザーを作成できる匿名アカウントは、最も基本的なアクセス権を持つ新しいユーザーを作成できる必要があります。管理者だけがユーザーを昇格したりユーザーを削除したりできます。これはアプリケーションで必要なことだと思います:-)一般的なデータは匿名ユーザーに表示されるため、この接続は認証が不要なコンテンツに使用できます。移植性も良い点ですが、ユーザーコマンドは今では標準に含まれていると思います(確かに数年前ではありませんでした)
Fabian Pijcke

ちなみに、この設定では、ハッカーが匿名ユーザーとしてデータベースにアクセスすると、必要な数のユーザーを作成できますが、これはセキュリティ上の問題ではなく、次のいずれかを使用してデータベースを膨らませることもできます。作成されたアカウントは、煩わしいものですが、セキュリティの問題はありません(そして、標準のインターフェイスを使用しても実行できますが、速度は
かなり

3
セキュリティの観点からは、データベースレベルのユーザーの方が優れていることに同意します。ただし、5000万の登録ユーザーがいるオンラインショップなどでは、基本的にそれを管理することは不可能です。それぞれがデータベースユーザーである必要があります。さらに、これは通常、接続プールを使用するWebアプリケーションではうまく機能しません。
a_horse_with_no_name

6

質問を言い直す

なぜユーザーのパスワードを保存するのですか?

最も簡単な答えは、あなたがそうしなければならないということです。パスワードは別の方法で保存します。ストレージを管理するには、データベースの組み込みシステムを使用するだけです。したがって、あなたの方法はあなたのデータベースと同じくらい良いです。それでも、他の方法よりは優れているかもしれませんが、ストレージを回避しているわけではありません。それは本当にストレージのコーディングを避けているだけです。

それもまた良くないかもしれません。データベースを危険にさらしてファイルのコピーを取得した場合、テーブルに直接アクセスできます。したがって、優れたパスワード管理システムを使用する意味はほとんどありません。誰かがパスワードまたはハッシュ化されたパスワードを含むシステムレベルのテーブルにアクセスできる場合は、ファイルに直接アクセスすることもできるためです。すでにデータを持っているのに、なぜパスワードをクラックする必要があるのですか?データを簡単に暗号化することもできません。各ユーザーはそれにアクセスできる必要があります。そのため、ユーザーレベルの暗号化はあまり機能しません。

しかし、あなたが本当に求めているように見えるのは

データベースに既に認証レベルがあるのに、なぜアプリケーションレベルの認証スキームを使用するのですか?

安全保障

より安全なバージョンを作成できる可能性を無視して、他の人はいくつかの理由を提案しています。私は概ね同意します。しかし、まだ誰も言及していない別のものがあります。データベースのセキュリティを危険にさらしています。

このシステムでは、アプリケーションのすべてのユーザーがデータベースユーザーとパスワードを持っています。もちろん、これは制限付きユーザーですが、データベースに接続できるユーザーです。行レベルのセキュリティを使用している場合でも、エンドユーザーがデータベース接続情報を知ることができるようにします。ユーザーがテーブルレベルのアクセスさえも取得できるエクスプロイトが存在する場合は、データベースを開いて攻撃しています。そして、いくつかのエクスプロイトがそれを超えて管理者アクセスになっています。

セキュリティタマネギのレイヤーでは、通常のシステムは次のとおりです。

  • 特定のマシンからの接続のみを許可するデータベース。
  • データベース、特定のユーザー/パスワードの組み合わせとしてのみ接続を許可します。
  • アプリケーションからの接続を許可するデータベース権限を持つサーバー。
  • アプリケーションはサーバー上で実行されます。
  • アプリケーションには、制限付きの権限を持つデータベース接続情報があります。
  • アプリケーションは、データベースの変更を許可する前にユーザーを認証します(新しいアカウントを作成する場合を除く)。

このシステムでは:

  • エンドユーザーは、データベースで機能するユーザーとパスワードの組み合わせを知っています。
  • サーバーを構成するか、または承認されたサーバーであるかのように見せかけるだけで十分です。

アプリケーションレベルのセキュリティ全体が失われました。そして、データベース層の一部を自発的に放棄しました。したがって、2つのエクスプロイトのみが必要です。

  1. 許可されたサーバーのなりすましまたは侵害。
  2. 制限付き特権アカウントのアクセスを増やします。

これら2つのことを実行できれば、データベースにアクセスできます。したがって、3つのレイヤーから2つのレイヤーに進みます。(通常のシステムの3番目の層は、データベースに接続するには有効なユーザーが必要であることです。)

あなたはこれらのアカウントの多くの管理を行うことになります。間違えたらどうしますか?ユーザーXを特定の行だけに制限する代わりに、重要なテーブルへのすべてのアクセスをユーザーに許可します。この種の作業は通常手動で行われ、その数は少ないため、監査は簡単です。しかし、システムでは、数千、数百万、または数十億ものユーザーアカウントを実行していて、それぞれが固有のアクセス権を持っている場合があります。

さらに言えば、データベースのシステムは数百万または数十億のユーザーに拡張できますか?もしそうなら、ルールの数はどうですか?各ユーザーがアクセスできるものとアクセスできないものについて100以上のルールを採用する場合、そのルールは10億のユーザーに拡大しますか?通常は小規模なシステムを採用し、それを大規模にします。それは必ずしもうまくいくとは限りません。成長するにつれて、システムの制限に気付く場合があります。


5

記述した内容は認証を処理しますが、承認(ユーザーがアクセスできるデータ)を処理したり、最も単純なユースケースでのみ処理します。

stackexechangeを使用して例を続行するには:削除された投稿をどのようにして高評価のユーザーにのみ表示しますか?したがって、アクセスルールの場合は、コードにロジックが必要です。ほとんどの開発者は、データベースルールとアプリケーションアクセスルールの間でアクセスロジックを共有する代わりに、それらすべてを同じ場所に置くことを好みます。

また、ユーザー情報を格納するためのテーブルも必要です。ユーザーはユーザー名+パスワードだけではありません。彼はメールや評判などを持っています。そのため、ユーザーテーブルにアクセスできる場合は、データベーステーブルと同期していることを確認する必要があるユーザーテーブルも必要です。

あなたのソリューションでは、パスワード列を省略できます。入力するのはそれほど難しくありません。パスワードを処理/ハッシュする方法に関する優れたライブラリとドキュメントがあります。

他のポイント:接続プールをどのように作成しますか?私はjdbc(java <-> db)のみを知っており、接続を取得するにはユーザー名+パスワードを指定する必要があります。

確立された方法よりも実装が難しい/複雑な他のいくつかの点を考えました:

  • パスワード回復の処理
  • 最初の実装から2年後、製品マネージャーは、oauthスキームのサポートを追加するか、2要素認証を許可するように求めます

のようなものCREATE POLICY deleted_posts_high_rep ON posts FOR SELECT TO baseuser USING ((SELECT rep FROM users WHERE name = current_user()) > 10000)が最初の質問に答えます。usersテーブルが必要なくなったと言ったことは一度もありません。dbuserテーブルとの同期を確実にすることは、少しトリッキーですが可能です。ここで説明する手法の主なポイントはセキュリティです。接続プールについては、OCamlを使用しており、接続のプールが必要になる理由がわかりません。現在、Cookie値を0-ary関数に関連付けて接続を返すハッシュマップを使用しています:-)
Fabian Pijcke

5
接続プールは、パフォーマンスを向上させるために実装されています。これらを使用すると、ユーザー要求ごとに接続を確立する必要がありません(そのため、TCPリンクの作成時のCPU / IO /待機時間+データベースとのすべての接続と認証交換を節約できます)。ポリシーの定義については、データベースは、すでに一度チェックした場合でも、データへのすべてのアクセスで常にアクセス権をチェックします。また、「アクセス拒否または禁止」は「OK、結果なし」と同じではありません。セキュリティ担当者がOKバージョンを好むかどうかはわかりません。
ティエリー

3
ファビアン、接続プーリングはあらゆる種類のスケールで基本的なものであり、実際にはデフォルトであり、使用しないとは考えていません。これがどれほど重要であるかを理解するためのいくつかのベンチマークは次のとおりです。接続プーリング(vladmihalcea.com/2014/04/17/the-anatomy-of-connection-poolingにより600倍のパフォーマンスの向上と4,000倍以上のパフォーマンスの向上接続プールprogress.com/tutorials/jdbc/…)。それは数桁の違いです、それは「持っているのに良い」ではありません、アプリはそれなしで停止するまで粉砕します。
Ivan McA

1
興味深い数字。実際、接続プールを使用しないアプリケーションを見たことがありません。しかし、私はそれらがそれほど高速化することを知りませんでした(そして期待していませんでした)。接続プールで得られるもう1つの側面はリソース制御です。これらのおかげで、一度に接続しようとするクライアントが大幅に増加するとアプリケーションが遅くなりますが、データベースにそれほど影響はありません(プールが適切に構成されている場合)。 。
ティエリー2017年

わかりました。接続プールの詳細情報を検索しましたが、Webサイトが1秒あたり100を超える接続を処理する必要があるので、これは非常に有効なポイントであることに同意します。PostgreSQLのすべての接続が約10MiBのRAMを消費するようです!それだけだとは思わなかった。
Fabian Pijcke 2017年

1

もう1つのポイント:多くの[1] Webアプリケーションでは、アプリ自体を使用してオンラインでユーザーアカウントを登録および作成できます。つまり、匿名ユーザー(想定する最低限の特権を持つ必要がある)は、ユーザーを作成して特権を付与する権限を持っている必要があります。

OK、付与できる権限を制限し、より高レベルのユーザーにより多くの付与オプションを与えることは可能かもしれません(ただし、私はそれを認識していません-単一の権限を「付与する」ことはあまりありません)。しかし、それでも、誰もがハッキングできるように、オンラインで付与特権を持つ何かを置くことを意味します。私がそうした場合、私のDBAは私を気に入らないと思います:)

いずれにせよ、この問題が存在することはわかっていますが、WebアプリがDBユーザーを管理することを許可しない場合は、特にデータの削除に対する防御の層があります。

また、これにより、プールまたは再利用されたDB接続が使用できなくなります。

[1]私が言うことのほとんどは、それを裏付ける数字ではない

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.