2

セキュリティと認証、およびその他のほとんどのクライアント/サーバー通信に関しては、私は少し初心者です。私がやろうとしていることは単純であり、可能であれば、仕事をするためにサードパーティのフレームワークやクラスを持ち込む必要はありません。(私はPythonでGoogle App Engineを使用しています)

ユーザーは、モバイルアプリケーション(iOS)を介してサービスに1回ログインします。ログインすると、ユーザーはメッセージ、友達、ステータスなどを取得するために多くのリクエストを行います。そのため、アプリがサーバーと通信するたびに、ユーザーのメールアドレスとパスワードを送信して認証するのではなく、セッションID。これまでのところ、それはシステムについての私の理解にすぎませんでした。

私は非常に単純なアプローチを考え出しました。それはうまくいくように思えますが、経験が浅いので、おそらく多くのことを見ていません。これを行うと何が問題になりますか?

  1. デバイスでは、ユーザーが電子メール/パスワードを入力すると、資格情報がサーバーに送信されて検証され、認証されると乱数が生成されます。この乱数は、session_numberという名前のUserモデルにIntegerPropertyとして格納されます。

  2. session_numberはユーザーのデバイスに送信され、保存されます。これで、ユーザーがリクエストのためにサーバーに接続するたびに、session_numberユーザーの整数ID番号がサーバーに送信されます。そのuserIdのUserエンティティを取得し、user.session_number==incoming_session_numberの値を比較します。それらが一致する場合、それ以外の場合はエラーです。

  3. ユーザーがログアウトすると、データストアからsession_numberをクリアします。

ここでの他の唯一の質問は、ユーザーが複数のデバイスからログインしているときにこれをどのように処理するかということです。各デバイスは独自のsession_numberを保存する必要がありますか?

4

2 に答える 2

4

ホイールの再発明についての私のコメントは別として。この理論で私が目にする主な問題は、それが完全にリプレイ攻撃を受けやすいということです。

たとえば、ID99とセッションID/ Cookieが「MONKEY-1」のユーザーがいる場合、ユーザーがリクエストを送信する場合は、何らかの方法で「from、99、MONKEY-1」で署名する必要があります。それがそのようなものだったとしましょう:

{ FROM: 99, TO: SERVER, COMMAND: GET-NEW-MAIL, SESSION: MONKEY-1 }

MONKEY-1が秘密なら、それは素晴らしいことです。(どのフォーマットでも、ラインノイズの4KiBバイナリチャンクである可能性があります。)

しかし、今では、そのパケットが通り過ぎるのを見た盗聴者がいます…彼女は今、自分のパケットを送信しています。おそらく彼女は賢く、実際のユーザー99が使用していた送信元IPアドレスを偽装しました。盗聴者があなたの応答を聞くことができなくても、彼女はあなたにパケットを送信できる可能性があります。おそらく、次のようになります。

 { FROM: 99, TO: SERVER, COMMAND: DELETE-ALL-MAIL, SESSION: MONKEY-1 }

この種のことを防ぐ方法はたくさんありますが、効果はさまざまです。接続をSSLでラップすると、これを非常に困難にすることができます(ただし、決して不可能ではありません)。これは、多くのWebサイトが利用しているソリューションです。より良い方法は、ハッシュまたは公開鍵/秘密鍵暗号を使用して、侵入者が秘密データを取得できない方法で署名するために双方向通信を使用することです。たとえば、次のような交換があるとします。

{ FROM: SERVER, TO: ??, COMMAND: PLEASE-LOGIN, NONCE: PIGEON }

{ FROM: BILL, TO: SERVER, COMMAND: LOGIN, AUTH: hash ( hash ( password ) . "PIGEON" ) }

…ここでhash()、たとえば、SHA-256の合計を表し、. "PIGEON"連結を指します。

{ FROM: SERVER, TO: BILL, COMMAND: LOGIN-OK, SESSION: hash ( password ) ^ "MONKEY-1" }

…ここで^、ビット単位の排他的論理和のような操作を指します-または、おそらく。その後、ビルは次のようなリクエストを送信します。

 { FROM: BILL, TO: SERVER, COMMAND: GET-NEW-MAIL, NONCE: "ARMADILLO", 
   AUTH: hash ( "GET-NEW-MAIL" . #\Newline . "ARMADILLO" . #\Newline . "MONKEY-1" ) }

さて、MONKEY-1が平地を旅したことは一度もありません。また、各リクエストで指定されたAUTHキーは、使用される動詞またはコマンド、およびリクエストごとに異なるナンスに関連付けられており、サーバーはその整合性を簡単に確認できますが、盗聴者は同じメッセージを再度再生したり、変更したりすることはできません。動詞と何か違うことをします。

パスワードの問題を説明するには:

私はデータベーステーブルを持っています、そしてそれは含まれています

User: BILL, Password: hash(DOLPHIN)

有線で、私が受け取る場合

{ FROM: BILL, PASSWORD: hash(DOLPHIN), COMMAND: GET-ALL-MAIL }

…その場合、盗聴者がパスワードがDOLPHINであることを知る可能性は低いですが、気にする必要はありません。

 { FROM: BILL, PASSWORD: hash(DOLPHIN), COMMAND: DELETE-ALL-MAIL }

パスワードの塩漬けについておっしゃっていますが…どうしますか?

 User: BILL, PASSWORD: hash( SALT . DOLPHIN )

hash ( SALT . DOLPHIN )SALTとDOLPHINを別々に保管しない限り、からに移動する簡単な方法はありません hash (DOLPHIN)。したがって、ユーザーがあなたに送信hash ( SALT . DOLPHIN )するか(クライアント側に静的SALTを配置する)、またはプレーンテキストのパスワードを再度保存する必要があります。

回避策は、次のようなことを行うことです。

 Database: ( BILL => hash ( SALT . DOLPHIN ) )

 Server sends: ( NONCE )

 Client sends: ( BILL => hash ( NONCE . hash ( SALT . DOLPHIN ) ) )
于 2012-08-30T18:57:11.760 に答える
4

この種のセキュリティモデルの重要な側面の1つは、パスワードを保存する方法(つまり、パスワードを保存しない方法)です。不適切に行われると多くの危険があるため、見た目ほど単純ではありません。

この記事では、基本をカバーし、何を調べるべきかについての概要を説明します。ハッシュ、レインボーテーブル、ソルティング、および低速ハッシュ関数について説明します。

App Engineを使用しているので、Pythonの暗号化ライブラリについて調べたいと思うでしょう。hashlibとは標準ライブラリの一部である2つですが、残念ながらPythonの標準ライブラリにはまたはのようなhmac低速ハッシュ関数の実装がありません。bcryptpbkdf2

したがって、passlibパスワードハッシュに使用することをお勧めします。私はそれを自分でプロジェクトに使用しています(進行中の作業)。具体的には、使用することにしました。ここでコードを確認sha512_cryptできます(批判は大歓迎です)。

どうやら、スタンフォードによって構築されたPBKDF2のJavaScript実装もあります。

于 2012-08-30T19:02:47.593 に答える