web-dev-qa-db-ja.com

これは有効な安全なCookieスキームですか?

情報の機密性が高いCookieのスキームがあります。クライアントから隠される情報は、Cookieの有効期限です。私はこの計画で私が自分自身をどのような不安にさらしているのか疑問に思っています。

以下で、_|_は連結を示し、_(text)k_はキーkを使用して暗号化されたテキストであることに注意してください。

cookie = creation_time | (expiration_time)k | HMAC(creation_time|expiration_time|server_key , k) where k = HMAC(creation_time, server_key)

キー検証の手順は次のとおりです。

  1. Creation_timeが有効なタイムスタンプであることを確認してください
  2. 作成k = HMAC(creation_time、server_key)
  3. kを使用して(expiration_time)kを復号化します。
  4. _(expiration_time - creation_time <= T)_ && _current_time < expiration_time_を確認します。ここで、TはCookieに対して許可されたサーバーTTL)です。
  5. hMAC(creation_time | expire_time | server_key、k)を計算し、Cookie値と比較します。それらが同じである場合、Cookieは有効です。

このCookieの要点は、Cookieがユーザーによって一度に受信され、時間T以内にajaxを介してpingが返されるようにすることです。

3
lluisrojass

この構造にはいくつか問題があります。

使用している暗号化アルゴリズムを定義していません。 CBCなどのパディング付きのブロック暗号モードを使用する場合、サーバーはプレーンテキストに対して信頼性レコードを検証する前に暗号化されたexpiration_time値を復号化する必要があるため、パディングOracle攻撃に対して設計が脆弱になる可能性があります。可能な限り、暗号文に対して信頼性チェックを適用する必要があります。

また、フィールド間で区切り文字がどのように機能するかも明確ではありません。デコードプロセスでの混乱を避けるために、個々のフィールドを個別に生成する方法を定義する必要があります。

重要ではありませんが、暗号化/復号化と信頼性(HMAC)の両方に単一の共有キーを使用することも悪い習慣です。これらの独立したキーを持つことを常に目指す必要があります。

全体として、これは非常に複雑な設計です。

より簡単な方法は、PHPの場合のように、有効期限をセッション変数として保存することです。

session_start();
$_SESSION['expiry'] = time() + 60 * 60 * 24; // now +24 hours

そして、各リクエストで:

session_start();
if (!isset($_SESSION['expiry']) || !is_int($_SESSION['expiry']))
{
    // expiry time has been unset or corrupted somewhere, log and fail
}
if ($_SESSION['expiry'] < time())
{
    // session expired, do whatever you need to do about this
}

これにより、複雑な暗号化スキームとトークンへのクライアント側のアクセスが節約されます。

1
Polynomial