DjangoにおけるCSRFクロスステーション要求偽造攻撃防止手順の詳細

3925 ワード

CSRF概念:
CSRFはサイト間で偽造を要求する(Cross-Site Request Forgery).
攻撃者はあなたの身分を盗んで、あなたの名義で悪意のある要求を送って、サーバーにとってこの要求は完全に合法的ですが、攻撃者が望んでいる操作を完成しました.例えば、あなたの名義でメールを送ったり、メッセージを送ったり、アカウントを盗んだり、システム管理者を追加したり、商品を購入したり、仮想通貨を振り替えたりします.
CSRF攻撃の原理と過程:
1、ユーザーCはブラウザを開き、信頼できるサイトAにアクセスし、ユーザー名とパスワードを入力してサイトAにログインすることを要求する.
2、ユーザー情報が検証に合格した後、ウェブサイトAはCookie情報を生成してブラウザに戻る.この時、ユーザーがウェブサイトAにログインすることに成功し、正常にウェブサイトAに要求を送ることができる.
3、ユーザーがウェブサイトAを脱退する前に、同じブラウザでTABページを開いてウェブサイトBにアクセスする.
4、ウェブサイトBはユーザーの要求を受信した後、いくつかの攻撃的なコードを返し、第三者サイトAへのアクセスを要求する要求を出す.
5、ブラウザは、これらの攻撃コードを受信した後、ウェブサイトBの要求に応じて、ユーザが知らないうちにCookie情報を携帯し、ウェブサイトAに要求する.サイトAは、その要求がBによって発起されたことを知らないため、ユーザCのCookie情報に基づいてCの権限でその要求を処理し、サイトBからの悪意のあるコードが実行される.
CSRF攻撃例:
被害者のボブは銀行に預金を持っていて、銀行のウェブサイトに要求を送った.http://bank.example/withdraw?account=bob&amount=1000000&for=bob2Bobに1000000の預金をbob 2の口座に振り込むことができます.通常、要求がウェブサイトに送信されると、サーバは、要求が合法的なセッションから来たかどうかを検証し、セッションのユーザーBobが正常にログインしたことを検証します.
 
ハッカーのMallory自身もこの銀行に口座を持っていて、彼は上記のURLがお金を振り替えることができることを知っています.Malloryは自分で銀行に要求を送ることができます.http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory.しかし、この要求はBobではなくMalloryから来ており、セキュリティ認証に合格できないため、この要求は機能しません.
 
この時、MalloryはCSRFの攻撃方式を使いたいと思って、彼はまず自分で1つのウェブサイトをして、ウェブサイトの中で以下のコードを入れます:src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory」と、広告などを通じてBobを誘って彼のサイトにアクセスした.Bobがこのサイトにアクセスすると、上記urlはBobのブラウザから銀行に送信され、このリクエストはBobブラウザのクッキーとともに銀行サーバに送信されます.多くの場合、Bobの認証情報を要求したため、この要求は失敗します.しかし、Bobがちょうど彼の銀行にアクセスしてから間もなく、彼のブラウザと銀行のウェブサイトの間のセッションが期限切れになっていない場合、ブラウザのクッキーにはBobの認証情報が含まれています.この時、悲劇が発生し、このurlの要求に応答し、BobのアカウントからMalloryのアカウントにお金を移すが、Bobは当時知らなかった.その後、Bobは口座のお金が少なくなったことを発見し、銀行に行ってログを調べても、本人からの合法的な要求が資金を移転したことに気づくしかなく、攻撃された痕跡はない.Malloryはお金を手に入れて逍遥することができます.
DjangoでCSRFを防ぐにはどうすればいいですか?
Djangoは専用のミドルウェア(CsrfMiddleware)を使用してCSRF防護を行う.具体的な原理は以下の通りである.
1.現在処理されている要求を修正し、すべてのPOSTフォームに非表示のフォームフィールドを追加します.名前はcsrfmiddlewaretokenで、値は現在のセッションIDに鍵のハッシュ値を追加します.セッションIDが設定されていない場合、ミドルウェアは応答結果を変更しないため、セッションを使用していないリクエストではパフォーマンス損失は無視できます.
2.セッションクッキーセットを含むすべての着信POST要求について、csrfmiddlewaretokenが存在するかどうか、および正しいかどうかを確認する.そうでない場合、ユーザは403 HTTPエラーを受信する.403エラーページの内容は、ドメイン間要求偽装が検出されたことである.リクエストを終了します.
この手順では、サイトからのフォームのみがデータPOSTを戻すことができます. 
また、セッションクッキーを使用しないPOST要求は保護されないが、悪意のあるウェブサイトが任意の方法でこのような要求を製造することができるため、保護される必要はない.HTML以外の要求の変換を避けるために、ミドルウェアは応答結果を編集する前にContent-Typeヘッダをチェックします.text/htmlまたはアプリケーション/xml+xhtmlとマークされているページだけが変更されます.
DjangoはCSRFの具体的な操作を防ぎます:
1、'django.middleware.csrf.CsrfViewMiddleware'Djangoのsettingsに追加する.pyファイルのMIDDLEWARE_CLASSESリスト(デフォルトでは追加されています)です.このミドルウェアはSessionMiddlewareの後に実行する必要があります.そのため、リストにCsrfMiddlewareがSessionMiddlewareの前に表示される必要があります.(応答ミドルウェアは後から前へ実行されるため).同時に、応答が圧縮または解凍される前に応答結果を処理しなければならないため、CsrfMiddlewareはGZipMiddlewareの後に実行しなければならない.
MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
    )

2.POSTメソッドを使用してFORMを発行するページにcsrf_を追加するtokenラベル:
{% csrf_token %}

3、対応するviewで「django.core.context_processors.csrf」コンテキストプロセッサが正しく使用されていることを確認するには、RequestContextを使用し、内部で「django.core.context_processors.csrf」に自動的に使用される2つの方法があります.もう1つの方法は、このプロセッサを手動で使用することです.サンプルコードは次のとおりです.
from django.core.context_processors import csrf

from django.shortcuts import render_to_response

def my_view(request):

    c = {}
    c.update(csrf(request))

    # ... view code here

return render_to_response("a_template.html", c)