web-dev-qa-db-ja.com

データベース内の2つのテーブル間の関係を難読化する方法は?

ここにある種の奇妙なユースケースがあり、どう対処すればよいかわかりません。
私は医療データを保存するプロジェクトに取り組んでいます。次の要件は別のチームによって対処されましたが、あまり文書化されていません。これが許容できる解決策であるか、見逃した可能性のある明らかな脆弱性があるか、そしてそれを行うより良い方法があるかどうかを理解しようとしています。

要件

データベースは患者に関する医療データを保存します。
患者の名前、姓、生年月日を照会できる必要があります。

一方、データベースダンプなどの形で誰かがデータに不正にアクセスする場合は、その人物が医療情報と確実なID(名前、姓、生年月日)を照合しないようにする必要があります。 。
SGBDの管理者権限を持つユーザーからデータを保護する必要はありません。

現在のシステム

患者エンティティは2つのテーブルに分かれています。最初のテーブルは名前、姓、生年月日を保持し、2番目のテーブルは他のエンティティとのすべての関係を含む実際の医療記録です。

関連付けは、医療記録に保存されているIDのハッシュを通じて行われます。

Identity                        Record
|id|name|surname|birthDate|     |id|hash|Some other fields...|

基本的に、IDとレコードの両方を取得するために、SQLクエリは次のようになります。

SELECT * FROM Identity i JOIN Record r
  ON r.hash = hash(i.id || i.name || i.surname || i.birthDate)

欠点

コメントで述べたように、コードを知っている人なら誰でも関連付けを計算できるため、これは実質的にセキュリティを提供しません。

単一の一方向ハッシュを使用しているため、IDから医療記録にナビゲートするには1つの操作しか必要ありませんが、その逆ではすべてのハッシュを計算する必要があります。

関連付けを単純に推測する確率は、レコード数に反比例しますが、その推測が正しいかどうかを確認する方法はありません。 (パスワードを推測するときとは異なり、パブリックログインフォームで確認できます。)

これまでに見つけたもの

名前、姓、生年月日のクエリが不要な場合は、これらのフィールドを暗号化するだけで済みます。
これらのフィールドを暗号化する場合、それらを照会する唯一の方法は、最初にすべてを復号化することです。
関連付けに確定的暗号化の代わりにハッシュを使用した理由がわかりません。または、医療記録のハッシュを患者のテーブルに入れて、レコードからテーブルにナビゲートするのに必要な操作は1つだけで済みます。
ハッシュにキーを付ける必要があります。そうしないと、コードを見た人が関連付けを計算できます。
キーは少なくともアプリケーションサーバーのどこかに保存されます。
キーはクエリでSGBDに渡されます。つまり、傍受またはログに記録される可能性があるため、保護は、たとえばテーブルのダンプを取得するユーザーに対しては機能しますが、DBに対する管理者権限を持つユーザーに対しては機能しません。
偽のデータを追加し、レコードの順序をランダム化すると、関連付けを推測することが難しくなります。

ご質問

まず第一に、これはまったく実行可能ですか?
言及しなかった明らかな欠陥はありますか?

ハッシュ(アルゴリズムのタイプ、ソルトなど)を処理する場合、いくつかの推奨事項がありますが、それらは通常、データ自体がデータベースに存在しないユースケースに適用されます。ここでそれらを実践する価値はありますか?

この問題に対するより一般的なアプローチはありますか?

医療データの取り扱いに関する参考資料はありますか?

1
vctls

患者の名前、姓、生年月日を照会できる必要があります。一方、誰かがデータに不正アクセスする可能性がある場合は、その個人がID(名前、姓、生年月日)と医療情報を照合しないようにする必要があります。

現在の形式でのハッシュは、この要件を満たす安全な方法ではありません。すでに述べたように、すべての患者に対してハッシュを作成するだけで完了です。

キー付きハッシュと暗号化について言及していますが、キーがどこかにある必要があり、それがHSMでない限り、データベースアクセスにはおそらくそのキーへのアクセスも含まれているため、それによってセキュリティがどのように向上するかはわかりません。

要件を解決する安全な方法は、患者データをまったく保存しないことです。すべての患者または部品をリストしたり、生年月日で患者をフィルタリングしたりする必要はないようです。ハッシュを超えるように選択した場合FirstName|LastName|DateOfBirth、データを永続化する必要なく、そのデータを簡単にクエリし、その患者のすべてのレコードを受け取ることができます。

患者データを保持する必要がある場合(確かに、医療データとは直接関係はありませんが)、患者データを個別に、つまり物理的に異なるデータベースに保持します。

1
Tobi Nary

Identity.idとRecord.idの両方があり、おそらく両方とも自動インクリメンタル主キーがあり、両方のテーブルがほぼ同時に挿入を取得しているため、多くの場合、両方のIDは実際には同じ値(または固定オフセット)になります。あなたはより安全にしようとする複雑な方法で物事をやっていますが、それは壊れています。

また、ハッシュで名前、姓、生年月日を使用する意味がわかりません。名前、姓、生年月日だけ それだけでは十分に一意ではありません 。したがって、IDの必要性。ただし、IDを考慮しているため、他のフィールドは必要ありません。hash(Identity.id)を使用するか、ハッシュの代わりにHMAC()またはIDの暗号化を使用できます。

それでも、挿入の順序だけに基づいて多くのレコードのペアを一致させるのはおそらく簡単でしょう。実際、「データベース全体を取得するユーザーがIDと一致するのを防ぐ必要がある」という全体的な概念には、おそらく欠陥があります。少なくとも、アプリケーションに格納されているキーで関係を保護している場合は、その部分を保護するための手順を実行し、それをデータベース自体と一緒に格納しないでください。

最後に、医療データから患者名に移動するにはすべてのハッシュを計算する必要があること、そしてそれは問題があることを述べていますが、おそらくアプリケーションが医療データから患者に移動することは意図されていませんが、すべての検索はルックアップから開始する必要があります患者さん。その場合、彼らはこれが問題ではないと考えていただろう。

1
Ángel