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 flask import current_app
|
||||||
|
from itsdangerous import Signer
|
||||||
from itsdangerous.url_safe import URLSafeTimedSerializer
|
from itsdangerous.url_safe import URLSafeTimedSerializer
|
||||||
from itsdangerous.exc import ( # noqa: F401
|
from itsdangerous.exc import ( # noqa: F401
|
||||||
BadTimeSignature,
|
BadTimeSignature,
|
||||||
|
@ -19,3 +20,17 @@ def unserialize(data, secret=None, max_age=432000):
|
||||||
secret = current_app.config["SECRET_KEY"]
|
secret = current_app.config["SECRET_KEY"]
|
||||||
s = URLSafeTimedSerializer(secret)
|
s = URLSafeTimedSerializer(secret)
|
||||||
return s.loads(data, max_age=max_age)
|
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.sessions import SessionInterface, SessionMixin
|
||||||
from flask.json.tag import TaggedJSONSerializer
|
from flask.json.tag import TaggedJSONSerializer
|
||||||
from werkzeug.datastructures import CallbackDict
|
from werkzeug.datastructures import CallbackDict
|
||||||
|
from itsdangerous import BadSignature, want_bytes
|
||||||
from CTFd.cache import cache
|
from CTFd.cache import cache
|
||||||
from CTFd.utils import text_type
|
from CTFd.utils import text_type
|
||||||
|
from CTFd.utils.security.signing import sign, unsign
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
@ -50,7 +52,7 @@ class CachingSessionInterface(SessionInterface):
|
||||||
def _generate_sid(self):
|
def _generate_sid(self):
|
||||||
return str(uuid4())
|
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.key_prefix = key_prefix
|
||||||
self.use_signer = use_signer
|
self.use_signer = use_signer
|
||||||
self.permanent = permanent
|
self.permanent = permanent
|
||||||
|
@ -61,6 +63,14 @@ class CachingSessionInterface(SessionInterface):
|
||||||
sid = self._generate_sid()
|
sid = self._generate_sid()
|
||||||
return self.session_class(sid=sid, permanent=self.permanent)
|
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):
|
if not six.PY2 and not isinstance(sid, text_type):
|
||||||
sid = sid.decode("utf-8", "strict")
|
sid = sid.decode("utf-8", "strict")
|
||||||
val = cache.get(self.key_prefix + sid)
|
val = cache.get(self.key_prefix + sid)
|
||||||
|
@ -99,7 +109,12 @@ class CachingSessionInterface(SessionInterface):
|
||||||
value=val,
|
value=val,
|
||||||
timeout=total_seconds(app.permanent_session_lifetime),
|
timeout=total_seconds(app.permanent_session_lifetime),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.use_signer:
|
||||||
|
session_id = sign(want_bytes(session.sid))
|
||||||
|
else:
|
||||||
session_id = session.sid
|
session_id = session.sid
|
||||||
|
|
||||||
response.set_cookie(
|
response.set_cookie(
|
||||||
app.session_cookie_name,
|
app.session_cookie_name,
|
||||||
session_id,
|
session_id,
|
||||||
|
|
Loading…
Reference in New Issue