web-dev-qa-db-ja.com

deviseのtoken_authenticatableは安全ですか?

Rails API を使用して簡単なAPIを構築しています。ここで正しい軌道に乗っていることを確認したいと思います。私はdeviseを使用してログインを処理しており、Deviseのtoken_authenticatableオプション。リクエストごとに送信する必要があるAPIキーを生成します。

私はAPIをバックボーン/マリオネットフロントエンドとペアにしていますが、通常、セッションをどのように処理すべきか疑問に思っています。私の最初の考えは、APIキーをローカルストレージまたはCookieに保存し、ページの読み込み時に取得することでしたが、APIキーを保存する方法がセキュリティの観点から気になりました。ローカルストレージ/ Cookieを調べるか、通過するリクエストを盗聴してAPIキーを取得し、それを使用してそのユーザーを無期限に偽装するのは簡単ではないでしょうか?私は現在、ログインごとにAPIキーをリセットしていますが、それでも頻繁に思えます-任意のデバイスにログインするたびに、それはあなたが他のすべてのものからログアウトされることを意味し、これは一種の痛みです。このリセットをドロップできれば、ユーザビリティの観点から改善されると思います。

私はここで完全に間違っているかもしれません(そして私がそうであることを願っています)、この方法の認証が確実に安全であるかどうか、そしてそうでない場合は良い代替案は誰でも説明できますか?全体として、頻繁に再認証を強制することなく、ユーザーをAPIアクセスに安全に「サインイン」させておく方法を探しています。

76
Jeff Escalante

_token_authenticatable_は、タイミング攻撃に対して脆弱です。これについては、 このブログ投稿 で詳しく説明されています。これらの攻撃が_token_authenticatable_がDevise 3.1から削除された理由です。詳細については、 plataformatecブログ投稿 を参照してください。

最も安全なトークン認証メカニズムを使用するには、トークンは次のようにします。

  1. HTTPS経由で送信する必要があります。

  2. 暗号強度のランダムでなければなりません。

  3. 安全に比較する必要があります。

  4. データベースに直接保存しないでください。トークンのハッシュのみをそこに保存できます。 (トークン=パスワードを覚えておいてください。パスワードをプレーンテキストでデータベースに保存しませんか?)

  5. 何らかの論理に従って期限切れになるはずです。

使いやすさを優先してこれらの点のいくつかを放棄すると、あなたはそれが可能な限り安全ではないメカニズムになってしまいます。それはそれと同じくらい簡単です。ただし、最初の3つの要件を満たし、データベースへのアクセスを制限する場合は、十分に安全である必要があります。

私の答えを拡大して説明します:

  1. HTTPSを使用します。スニファーを扱うため、これは間違いなく最も重要なポイントです。

    HTTPSを使用しない場合、多くの問題が発生する可能性があります。例えば:

    • ユーザーの資格情報(ユーザー名/メール/パスワード)を安全に送信するには、ダイジェスト認証を使用する必要がありますが、 ソルトハッシュはブルートフォースになりかねないので、最近ではカットされません

    • Rails 3では、CookieはBase64エンコードによってのみシュラウドされているため、かなり簡単に明らかにすることができます。 Decoding Rails Session Cookies 詳細については。

      Rails 4なので、Cookieストアは暗号化されているため、データはデジタルで検証され、攻撃者には読み取れません。_secret_key_base_が漏洩しない限り、Cookieは安全です。

  2. 次を使用してトークンを生成します。

    これが必要な理由の説明については、 sysrandom のREADMEおよびブログ投稿 How to Generate Secureさまざまなプログラミング言語の乱数

  3. ユーザーのID、メール、またはその他の属性を使用してユーザーレコードを検索します。次に、そのユーザーのトークンをリクエストのトークンと比較します _Devise.secure_compare(user.auth_token, params[:auth_token]_ 。 Rails 4.2.1+を使用している場合は、 _ActiveSupport::SecurityUtils.secure_compare_ も使用できます。

    notは、Rails FinderのようなUser.find_by(auth_token: params[:auth_token])のようなユーザーレコードを見つけます。これは脆弱です。タイミング攻撃!

  4. ユーザーごとに複数のアプリケーション/セッションを同時に使用する場合、次の2つのオプションがあります。

    • 暗号化されていないトークンをデータベースに保存して、デバイス間で共有できるようにします。これは悪い習慣ですが、UXの名前でそれができると思います(そして、DBアクセスで従業員を信頼している場合)。

    • 現在のセッションを許可するのと同じ数の暗号化されたトークンをユーザーごとに保存します。したがって、2つの異なるデバイスで2つのセッションを許可する場合は、データベースに2つの異なるトークンハッシュを保持します。このオプションを実装するのは少し簡単ではありませんが、間違いなく安全です。また、トークンを取り消すことにより、特定のデバイスで現在アクティブなセッションを終了するオプションをユーザーに提供できるという利点もあります( GitHub およびFacebookと同様)。

  5. トークンの有効期限が切れる何らかのメカニズムが必要です。このメカニズムを実装するときは、UXとセキュリティのトレードオフを考慮してください。

    Googleが6か月間使用されなかった場合、トークンの有効期限が切れます

    Facebookがトークンを2か月間使用しなかった場合は期限切れになります

    FacebookのSDKを使用するネイティブモバイルアプリは、約60日間有効な長寿命のアクセストークンを取得します。これらのトークンは、アプリを使用している人がFacebookのサーバーにリクエストを行うと、1日に1回更新されます。要求が行われなかった場合、トークンは約60日後に期限切れになり、ユーザーは新しいトークンを取得するためにログインフローを再度実行する必要があります。

  6. 暗号化されたCookieストアを使用するには、Rails 4にアップグレードします。できない場合は、提案された here のように、Cookieストアを自分で暗号化します。まったく問題はありません。暗号化されたCookieストアに認証トークンを保存する。

また、非常事態計画、たとえば、トークンのサブセットまたはデータベース内のすべてのトークンをリセットするレーキタスクを用意する必要があります。

始めるために、 this Gist (Deviseの著者の1人による)Deviseでトークン認証を実装する方法を確認できます。最後に、 APIの保護に関するRailscast が役立つはずです。

185
Ashitaka

プロジェクトのREADMEによると、devise_token_auth gemは、このStackOverflowの投稿に触発されました。 https://github.com/lynndylanhurley/devise_token_auth

10
Eliot Sykes

APIでRails4を使用してみることができます。これにより、セキュリティが強化され、devise 3.1.0rc

トークンの場合、セッションストアでは、 http://Ruby.railstutorial.org/chapters/sign-in-sign-out および http://blog.bigbinary.com/ 2013/03/19/cookies-on-Rails.html より不安定に。

最後に、これらの種類の暗号化と復号化を実行する必要があります " 保存された暗号化データを復号化できません "セキュリティを強化します。

3
Gaurav Sharma