mirror of https://github.com/JohnHammond/CTFd.git
Sign sessions using SECRET_KEY to simplify revocation (#1219)
* Sign sessions using `SECRET_KEY` * Add `CTFd.utils.security.signing.sign` and `CTFd.utils.security.signing.unsign`bulk-clear-sessions
parent
83efc4d5eb
commit
60c46af58a
|
@ -1,4 +1,5 @@
|
|||
from flask import current_app
|
||||
from itsdangerous import Signer
|
||||
from itsdangerous.url_safe import URLSafeTimedSerializer
|
||||
from itsdangerous.exc import ( # noqa: F401
|
||||
BadTimeSignature,
|
||||
|
@ -19,3 +20,17 @@ def unserialize(data, secret=None, max_age=432000):
|
|||
secret = current_app.config["SECRET_KEY"]
|
||||
s = URLSafeTimedSerializer(secret)
|
||||
return s.loads(data, max_age=max_age)
|
||||
|
||||
|
||||
def sign(data, secret=None):
|
||||
if secret is None:
|
||||
secret = current_app.config["SECRET_KEY"]
|
||||
s = Signer(secret)
|
||||
return s.sign(data)
|
||||
|
||||
|
||||
def unsign(data, secret=None):
|
||||
if secret is None:
|
||||
secret = current_app.config["SECRET_KEY"]
|
||||
s = Signer(secret)
|
||||
return s.unsign(data)
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from flask.sessions import SessionInterface, SessionMixin
|
||||
from flask.json.tag import TaggedJSONSerializer
|
||||
from werkzeug.datastructures import CallbackDict
|
||||
from itsdangerous import BadSignature, want_bytes
|
||||
from CTFd.cache import cache
|
||||
from CTFd.utils import text_type
|
||||
from CTFd.utils.security.signing import sign, unsign
|
||||
from uuid import uuid4
|
||||
import six
|
||||
|
||||
|
@ -50,7 +52,7 @@ class CachingSessionInterface(SessionInterface):
|
|||
def _generate_sid(self):
|
||||
return str(uuid4())
|
||||
|
||||
def __init__(self, key_prefix, use_signer=False, permanent=False):
|
||||
def __init__(self, key_prefix, use_signer=True, permanent=False):
|
||||
self.key_prefix = key_prefix
|
||||
self.use_signer = use_signer
|
||||
self.permanent = permanent
|
||||
|
@ -61,6 +63,14 @@ class CachingSessionInterface(SessionInterface):
|
|||
sid = self._generate_sid()
|
||||
return self.session_class(sid=sid, permanent=self.permanent)
|
||||
|
||||
if self.use_signer:
|
||||
try:
|
||||
sid_as_bytes = unsign(sid)
|
||||
sid = sid_as_bytes.decode()
|
||||
except BadSignature:
|
||||
sid = self._generate_sid()
|
||||
return self.session_class(sid=sid, permanent=self.permanent)
|
||||
|
||||
if not six.PY2 and not isinstance(sid, text_type):
|
||||
sid = sid.decode("utf-8", "strict")
|
||||
val = cache.get(self.key_prefix + sid)
|
||||
|
@ -99,7 +109,12 @@ class CachingSessionInterface(SessionInterface):
|
|||
value=val,
|
||||
timeout=total_seconds(app.permanent_session_lifetime),
|
||||
)
|
||||
session_id = session.sid
|
||||
|
||||
if self.use_signer:
|
||||
session_id = sign(want_bytes(session.sid))
|
||||
else:
|
||||
session_id = session.sid
|
||||
|
||||
response.set_cookie(
|
||||
app.session_cookie_name,
|
||||
session_id,
|
||||
|
|
Loading…
Reference in New Issue