7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

FlaskにおけるSECRET_KEYの役割についてざっくり理解する

Posted at

SECRET_KEY

公式ドキュメント

セッションCookieに安全に署名するために使用され、拡張機能またはアプリケーションによるその他のセキュリティ関連のニーズに使用できる秘密鍵。それは長い乱数bytesまたはstr.

データベースの設定と、セッション情報を暗号化するためのキーを設定します。

一言で

結論、SECRET_KEYとは

セッション情報(Cookie)を暗号化する際に使用する秘密鍵(文字列)

ということですね。この文をちゃんと理解するためには、Cookieについても深く知っておく必要がありそうです。以下でCookieについても今一度確認してみましょう。

Cookie

HTTP Cookie (ウェブ Cookie、ブラウザー Cookie) は、サーバーがユーザーのウェブブラウザーに送信する小さなデータであり、ブラウザーに保存され、その後のリクエストと共に同じサーバーへ返送されます。一般的には、二つのリクエストが同じブラウザーから送信されたものであるかを知るために使用されます。例えば、ユーザーのログイン状態を維持することができます。Cookie は、ステートレスな HTTP プロトコルのためにステートフルな情報を記憶します。

Cookieとはユーザーのログイン状態が記録されたデータのことで、クライアント側(webにアクセスしているスマホやPC)に直接保存されものです。以下のようにChromeの設定や、デベロッパーツールなどからもみることができます。

設定画面
DevTools

保存方法

具体的に何をして保存されるかというと、クライアントがサーバーにアクセスした時にサーバーが以下のレスポンスヘッダーを含めて応答することでクライアントの端末にCookieデータが保存されています。

Set-Cookie: <cookie-name>=<cookie-value>

したがって、どんな<cookie-value>を送るかはサーバー側に委ねられています。

セッション情報の管理

セッション情報を<cookie-name>=<cookie-value>に記述して送信することでセッションを管理するのですが、この実装方式には大きく分けて以下の2種類があります。

  • セッションのキー情報のみクライアントのブラウザに送信する
  • セッション情報全てをクライアントのブラウザに送信する

一つは、Cookie等にセッションのキー情報のみを保存し、セッションの中身はサーバー側で保存する方式です。キーのことをセッションIDと呼び、セッションIDには乱数を使います。この方式は、通常暗号化は用いません。
もう一つは、Cookieそのものにセッションの値を入れる方式で、CookieStoreなどと呼ばれます。セッションの値は、利用者からも改ざんされるとまずいので、CookieStoreに格納する値は暗号化します。CookieStoreのメリットは、サーバー側で状態を保持する必要がない点で、RESTとの相性がよく、サーバーの負荷分散が容易だという現実的なメリットもあります。

Flaskで作ったアプリケーションは基本的に後者のセッション情報全て送信する方式を採用しているようです。この方式では、利用者が自身のセッション情報を改ざんできてしまう危険性があるため、改ざんを防ぐために暗号化を施す必要があり、この暗号化にSECRET_KEYが使われます。

セッション情報をいじってみる

セッション情報を改ざんされるといってもピンと来ないため、シンプルな例を用いてセッション情報をいじってみて改ざんという現象のイメージができるようにします。

例えば、以下のようにルーティングが設定されているアプリを考えてみます。

@dev.route("/register/<string:session_id>")
def send_cookie(session_id):
    content = f"session: {session_id}として登録しました"

    response = make_response(content)
    response.set_cookie('session_id', value=session_id)
    return response

@dev.route("/login_mitaina")
def get_cookie():
    session = request.cookies.get('session_id', None)

    if session == 'HogeHoge':
        content = "こんにちは、HogeHogeさん"
        # HogeHogeさん用の処理
    elif session == 'fuga':
        content = "こんにちは、fugaさん"
        # fugaさん用の処理
    else:
        content = "piyopiyo"
    return make_response(content)

HogeHogeとして登録

ブラウザ(Chrome)を使用して↓のような感じでリクエストを送ってみます。
スクリーンショット 2022-12-25 20.00.44.png

その後、/login_mitainaへアクセスすると、正しくログインできてそうですね。
スクリーンショット 2022-12-24 10.33.13.png

ここで、Cookieの修正を試してみましょう。
Chromeのデベロッパーツールから確認してみると、Name: session_id, Value: HogeHogeとしてChromeのCookieに登録されていることが確認できます。このデベロッパーツールからCookieを修正することができて、Valueのところをダブルクリックすると値を自由に編集できます。今回はfugaに変更してみました。

修正前 修正後
スクリーンショット 2022-12-24 11.19.55.png スクリーンショット 2022-12-24 11.20.49.png

再度/login_mitainaへアクセスすると、fugaさんとして認識されてしまっていることが確認できます。ちょっと改ざんのイメージが付きましたね。
スクリーンショット 2022-12-24 10.43.55.png

セッション情報暗号化の利点

上記の例ではsession_idを想定しましたが、session_id以外でも例えばECサイトであればカート内の商品数とか、クーポンの保有数とか、そのあたりがCookieにcart_item: 3, coupon_num: 4とかで保存されてたらcoupon_num: 1000とかにいじりたくなっちゃいますよね(←良くない)

仮にこれがSECRET_KEYで暗号化されていて、暗号化前はcoupon_num: 4であったものがXalo88f_feem: YYYfjkooooみたいな文字列でブラウザのCookieに保存されていたら簡単には改ざんできなさそうだなと想像が付きます。
SECRET_KEYが漏れてしまった場合、Xalo88f_feem: YYYfjkoooocoupon_num: 4に復号することが可能になりセッション情報の改ざんをされる恐れが出てくるため、やはりSECRET_KEYは慎重に管理する必要がありますね。

7
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?