web-dev-qa-db-ja.com

機密データの転送/保存/暗号化システムの開発に関するアドバイスが必要

私はSO=にクローズし、これは特定のコードではなく一般的なアプリケーション設計に関するものであるため、ここに投稿するように言われました。

はじめに

私は現在、VisualFox Proデータベースからデータ(薬局レコード)を毎日抽出し、その一部をWordPressサイトにアップロードすることを含むプロジェクトに取り組んでいます。ここでは、薬局のクライアントが安全に表示します。ソフトウェアの一般的な方法論についてアドバイスをお願いします-コード化することはできますが、適切な方法で進んでいるかどうかを知る必要があります。両方のPCソフトウェア( C#/。NET 4.5)およびPHP WordPressプラグインです。WordPressにあることはそれほど重要ではありません。実際のコードは、多くは別々に実行されます)。

質問1:暗号化

私が使用する予定のサーバー側のデータを暗号化するための現在のプロセスは この記事 に基づいています。要約すると、サーバーに格納されている独自の公開鍵を使用して、個別の各ユーザーのデータを非対称に暗号化することを推奨しています。次に、このデータを復号化するための秘密鍵自体が、ユーザーのパスワードを使用して対称的に暗号化され、保存されます。この方法では、データベースが盗まれた場合でも、ユーザーのパスワードハッシュを破壊する必要があり、その場合でも、すべてのユーザーのデータに対してプロセスを繰り返す必要があります。

作者自身が指摘した唯一の弱点と私の質問の主要な点は、ユーザーがログインしている間、復号化されたキーがセッションストレージに保存されるという事実です。この記事が対処することを提案する方法は、ユーザーがログインする時間を制限することです。より良い解決策は、そのキーを短期間の安全なCookieに保存することです(もちろん、プロセス全体がHTTPS経由で行われます)。 。こうすることで、攻撃者がユーザーのコンピューターを制御してCookieを読み取ることができる場合、おそらくパスワードをキー入力してログインするだけでデータベースを盗む必要はありませんが、攻撃者がサーバーにアクセスしても、復号化することはできません。 HTTPSトラフィック(または可能ですか?わかりません。)

復号化されたキーを一時的に保存するために安全なCookieまたはセッションストレージを使用する必要がありますか?

質問2:ストレージ

私がまだ解決したい2番目のことは、データの格納方法です。これは、効率の問題です。すべてのユーザーは暗号化用の独自のキーを持っているため、すべてのユーザーのレコードは個別に保存する必要があります。レコードを表すオブジェクトの配列を含む暗号化されたJSONを含む、すべてのユーザーのデータの「ブロック」を保存する必要があるかどうか、または実際のデータ構造を持つテーブルにレコードを保存し、各データフィールドを暗号化する必要があるかどうかわからない別途キーで。

私はデータを1つのブロックとして保存することに傾倒しています-おそらく数千の個別のフィールドよりも、一度に1つの大きなデータブロックを復号化する方が効率的です。また、データを適切な構造で保存したとしても、データはすべてBLOBであるため、MySQLのWHERE、ORDERBYなどを使用することはできません。

ユーザーごとに大きなブロックとしてデータを保存する必要がありますか、または異なるフィールドに分けますか?

質問3:転送

私はDBFファイルからデータを抽出し、基本的に「差分」を作成します。これにより、前日のデータから現在の抽出データを比較し、変更されたユーザーのブロックのみをアップロードします(レコードをアップロードするだけではありません) 、おそらくユーザーのデータをブロックに格納することになるでしょう)。削除されたユーザー向けの「削除」手順も含まれています。これは、データベースに数十万のレコードがあり、合計で200MBを超え、サイズが毎日増加するためです。

私の現在の計画は、このすべてのデータをJSONファイルに書き込み、gzipしてサーバーにアップロードすることです。私の質問は、データのセキュリティを確保しながら、どうすればよいですか?当然のことながら、アップロードはHTTPS経由で行われ、許可されたアップロードのみを許可するAPIパスワードを設定していますが、私の主な関心事は、サーバーが危険にさらされた場合にデータを保護する方法です。攻撃者が処理中のサーバーからJSONファイルを取得することを望まない。アップロードする前に、サーバーにユーザーの公開鍵のリストを送信して、ソフトウェアで暗号化を実行させるというアイデアがありました。それがそのデータを保護する唯一の方法であるように私には思えます。おそらくAPIキーまたは特別なパスワードを使用してJSONファイル全体を暗号化することもできますが、サーバーで処理されているときに攻撃者が復号化されたファイルにアクセスできるだけなら、それは意味がありません。それは良い解決策ですか?

クライアント側でデータを個別に暗号化する必要がありますか、それとも安全にサーバーに転送してそこで暗号化する方法はありますか?

事前に回答をありがとうございました。以前にこのような問題に対処したことのある方からの連絡をお待ちしています。

マット

編集:私は1と2にかなり決まっています-@Moronsに感謝します。安全なCookieを使用して、データをブロックに保存します。私の主な質問は今、質問3です。それについていくつかの入力を得たいと思います。

6
Matt Jadczak

これが率直に言えばいいのではないかと思いますが、ここで行う作業は非常に難しく、正しく実行する可能性は非常に低くなっています。ほとんどの場合、セキュリティの欠陥は、基盤となるテクノロジーではなく、実装のミスが原因です。これまでに説明したようなシステムを安全にするには、適切なツールと方法論を使用し、すべてのEdgeケースに対応する必要があります。そうしないと、システム全体のセキュリティが侵害されます。

それは本当に役立つ答えではありませんが、そうですか?あなたが質問を構築しているようなシステムを構築しているとき、あなたが尋ねるべきである質問は、「これをどうやってやるのですか?」ではありません。代わりに、「自分に最も依存しない、これを行うにはどうすればよいですか?」その質問への答えは、可能な限り実証済みのシステムを使用し、最後の手段としてのみ独自のソリューションを導入することです。

暗号化に関する最初のポイントに答えるには、サーバーのメモリ内のキーを保護することについてあまり心配することは意味がありません。攻撃者がマシンにアクセスしてメモリからキーを読み取るのに十分な場合、完全に完全にハマっており、コード化したソリューションは何の役にも立たないでしょう。言い換えると、ほとんどの攻撃が発生する場所であるため、静止データとインターネット上を移動するデータを保護することを優先します。

データの保存に関する限り、非対称暗号をここに含める必要がある理由はわかりません。 PBKDF2 のようなものを使用して、ユーザーのパスワードから直接キーを取得し、データを暗号化して、暗号化されたblobをデータベースに格納します。フラットファイルでいっぱいのフォルダを管理するのは、たいていの場合面倒なので、フラットファイルよりもデータベースをお勧めします。データベースは、フラットファイルよりも速度やセキュリティの面で確かな利点を示さない場合がありますが、プールされた接続などの他の多くの機能を備えており、フラットファイルよりもはるかに簡単にデータをバックアップできます。 できるだけシンプルなシステムを使用して攻撃対象領域を最小限に抑え、可能な限り徹底的にテストされたオープンソースツールを使用します。使用する方法が見つかれば- [〜#〜] gpg [〜#〜] 暗号化と鍵導出の部分については、お勧めします。

転送に関しては、あなたは物事を間違った方法で考えていると思います。 クライアント側で暗号化を行わないこの記事 で説明されているように、ブラウザのJavaScriptは暗号化に適していません。サイトへのすべての接続にTLS/SSLを使用していることを確認している限り、暗号化されていないデータの送信について心配する必要はありません。クライアント側の暗号化が難しい理由の例として、MegaUploadの後継であるMEGAのセキュリティについてグーグルで調べてください。

最後に、私も含めて、インターネットから回答を得る人は誰も信用しません。解決策をとる前に、この種のことについて多くの調査を行います。また、 IT Security Stack Exchange でこの質問をすることをお勧めします。

-編集-

どういうわけか、私はシステムに3つの部分、クライアント(ブラウザー)、サーバー(データベース)、およびVisualFoxデータベースからデータをインポートするコネクターがあるという事実を完全に逃しました。秘密を共有する必要のある当事者が2つではなく本質的に3つあるため、実際にはシステム全体がより複雑になります。ユーザーのパスワードに基づいてデータを暗号化するのではなく、サーバーのパスワードに基づいてデータを暗号化することをお勧めします。このプロセスを説明する良い方法を考えているときに少し問題があります。代わりにワークフローの例を紹介します。

サーバー側

  1. 管理者がサーバーを起動します。
  2. 起動時に、サーバーコードはパスワードを要求します。
  3. サーバーはPBKDF2を使用して、メモリにのみ格納されているキーを取得します。
  4. サーバーは、更新されたデータについてX(日/時間/分)ごとにVirtualFox Proサーバーをポーリングするスレッドを生成します。
  5. サーバーはループに入り、ブラウザークライアントからの要求を待ちます。

データベースを更新しています

  1. メインサーバーの子スレッドは、Virtual Fox Proサーバーからのデータの更新を要求します。
  2. VirtualFox Proサーバーは、変更されたエントリを持つクライアントのデータを含むレポートをダンプします。
  3. VirtualFox Proサーバーはメインサーバー(ssh、sftpなど)への安全な接続を開き、圧縮されたデータを送信します。
  4. メインサーバーは、メモリに格納されているPBKDF2派生キーを1つずつ使用して、データベースに格納されているblobを復号化し、新しいデータで更新し、再暗号化して、データベースに再び格納します。このプロセスはすべてメモリ内で発生するはずです。

ブラウザクライアントが接続します

  1. メインサーバーがクライアントからhttpsリクエストを受信します。
  2. メインサーバーは、サードパーティの認証フレームワークを使用してクライアントの資格情報を確認します。このフレームワークはbcryptを使用してパスワードをハッシュし、ハッシュをファイルシステムにのみ保存する必要があります。
  3. 認証フレームワークがユーザーを明確に識別すると、メインサーバーはメモリ内のPBKDF2派生キーを使用してユーザーのblobを復号化し、データをユーザーに送信します。
  4. ユーザーの認証Cookieの有効期限が切れると、メインサーバーはPBKDF2派生キーを使用したデータの復号化を停止し、代わりにユーザーに再認証を求めます。

このモデルは、従来のWebサイトの動作(つまり、サードパーティのバグテスト済みフレームワークに依存できること)とより一致していますが、データはデータベースにアクセスする前にメモリ内で暗号化/復号化されます。理想的には、メインサーバー上の暗号化キーを管理するためにGPGまたは他のキーストアを使用することもできます。

8
TwentyMiles

正直なところ、暗号化されたブロックにデータを保存している場合、DBには何が必要ですか? (あなたが正しいと言っているのは、レコード全体を暗号化した場合、それを照会することはできないということです)

私はVFPでファイルをローカルに暗号化し、それを(ユーザーのパスワードを使用して)暗号化してアップロードします(ユーザーごとに1つのファイル)。私はDiffsを扱うことさえせず、毎日データセット全体をアップロードするだけです。 (データサイズが許す場合)

Word Pressへのアクセスと直接そのファイルの復号化があります。 (ファイルをコードブロックとして考える)

Cookieで何をしようとしているのか理解できません。ユーザーがログインしている間、Cookieをタイムアウトしますか?次に、ユーザーはログインしている間、データへのすべてのアクセスを失います。

2
Morons