11

申し訳ありませんが、koa で秘密鍵がどのように機能するのかよくわかりません。koa には、次のように使用されるオブジェクトのkeysフィールドがあります。app

const app = new Koa();
app.keys = ['some secret', 'another secret', 'or more ...']; // it's an
                                                             // array right?

そして、koa-csrfミドルウェアを使用する場合、デフォルトでは、ビルトインcsrf.middlewareは によって提供されるキーを使用しませんapp.keys。デフォルトのミドルウェアを使用する場合、セッションに秘密鍵を設定する別のミドルウェアを作成する必要があります。

app.use(session()); // koa-generic-session
app.use(async (ctx, next) => {               // without this custom middleware
  ctx.session.secret = 'yet another secret'; // POST /protected-route
  await next();                              // will give 403
});                                          // missing secret
csrf(app);
app.use(csrf.middleware);

Flask を使用するときは、. によって設定された秘密鍵を 1 つだけ指定する必要がありstringますarray。なぜ複数の秘密鍵が必要なのですか? アプリケーション全体に 1 つだけを使用するだけでは十分ではありませんか?

4

1 に答える 1

12

ここで複数のことを尋ねているようです。

  1. app.keys = [...]鍵のローテーションのために、Koa に複数の鍵を提供できます。

    たとえば、毎月新しいキーを生成する場合は、古い Cookie をすべてすぐに無効にすることなく、そのキーで新しい Cookie に署名できます。代わりに、古い Cookie を自然に期限切れにすることをお勧めします。

    キーのローテーションが気にならない場合は、app.keys = ['mysecret']変更しないことをそのまま使用します。

  2. koa-csrfのミドルウェアは、設定したキーを実際に使用しますapp.keys=

    Koa はapp.keysCookies インスタンス ( https://github.com/pillarjs/cookies ) に渡し、ビルトインがキーthis.cookies.get()this.cookies.set()使用します (提供されている場合)。

    koa-sessionKoa のビルトインを使用しthis.cookies.{get,set}ます。

    koa-csrfを使用しkoa-sessionます。

しかし、それはすべて無関係です。

app.keys=403 応答は、シークレットを設定していないことを訴えているわけではありません。CSRF トークン (別名シークレット) を提供していないこと、さらには有効なトークンを提供していないことを訴えています。

手動設定の「修正」はthis.session.secret、koa-csrfがCSRFトークンを見つけるために探す値を手動で設定するだけです。CSRF システムのセキュリティ対策全体をバイパスしています。

CSRF トークン システムの要点は、保護されたエンドポイントにヒットした人が、たとえば、<form>あなたが制御するページからそのエンドポイントに投稿した から実際に発信されたことを確認することです。

これは、トークンを生成し、それを Cookie に保存し、トークンをフォームに添付して、送信時にフォーム トークンがセッション トークンと一致することを確認することによって行われます。

あなたが欠けているように見えるのは、あなたがしなければならないことです:

  1. CSRF トークンを生成する
  2. secretクライアントの Cookie に設定します
  3. CSRF トークンをクライアントに公開して、クライアントが保護されたエンドポイントに送信できるようにします。
  4. 保護されたエンドポイントで、クライアントが「シークレット」Cookie の CSRF トークンと一致する CSRF トークンを送信することを確認します。koa-csrf がそのトークンを見つけるためにチェックする場所は次のとおりです。

koa-csrf のthis.csrf呼び出しは #1 と #2 を実行します。#3を実装する必要があります。koa-csrfthis.assertCSRFは #4 を行います。

したがって、全体として、これはどのように見えるかです (未テスト):

var koa = require('koa')
var csrf = require('koa-csrf')
var session = require('koa-session')
var Router = require('koa-router');
var bodyParser = require('koa-bodyparser');

var app = koa()
app.keys = ['session secret']
app.use(session())
app.use(bodyParser())
csrf(app)
app.use(csrf.middleware)

var router = new Router();

router.get('/messages', function*() {
  this.render('new_message_form.html', {
    token: this.csrf   // this call also sets `this.session.secret` for you
  });
});

router.post('/messages', function*() {
  this.assertCSRF(this.request.body);

  // If we get this far, then the CSRF check passed
  yield database.insertMessage(this.body.message);
});

app.use(router.routes());
app.listen(3000, () => console.log('server listening on 3000'));

「new_message_form.html」は次のようになります。_csrfユーザーが送信すると、によって生成されたトークンがthis.csrf保護されたエンドポイントに送信されるように隠しフィールドを設定していることに注意してください。_csrfフィールドは、送信されたトークンを見つけるために koa-csrf がチェックする場所の 1 つです。

<form action="/messages" method="POST">
  <input type="hidden" name="_csrf" value="{{ token }}">
  <input type="message" name="message" placeholder="Write your message here...">
  <button type="submit">Save Message<button>
</form>
于 2016-02-13T01:26:44.273 に答える