160 lines
5.5 KiB
Python
160 lines
5.5 KiB
Python
""" Flask Session Cookie Decoder/Encoder """
|
|
__author__ = 'Wilson Sumanang, Alexandre ZANNI'
|
|
|
|
# standard imports
|
|
import sys
|
|
import zlib
|
|
from itsdangerous import base64_decode
|
|
import ast
|
|
|
|
# Abstract Base Classes (PEP 3119)
|
|
if sys.version_info[0] < 3: # < 3.0
|
|
raise Exception('Must be using at least Python 3')
|
|
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
|
|
from abc import ABCMeta, abstractmethod
|
|
else: # > 3.4
|
|
from abc import ABC, abstractmethod
|
|
|
|
# Lib for argument parsing
|
|
import argparse
|
|
|
|
# external Imports
|
|
from flask.sessions import SecureCookieSessionInterface
|
|
|
|
class MockApp(object):
|
|
|
|
def __init__(self, secret_key):
|
|
self.secret_key = secret_key
|
|
|
|
|
|
if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
|
|
class FSCM(metaclass=ABCMeta):
|
|
def encode(secret_key, session_cookie_structure):
|
|
""" Encode a Flask session cookie """
|
|
try:
|
|
app = MockApp(secret_key)
|
|
|
|
session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
|
|
si = SecureCookieSessionInterface()
|
|
s = si.get_signing_serializer(app)
|
|
|
|
return s.dumps(session_cookie_structure)
|
|
except Exception as e:
|
|
return "[Encoding error] {}".format(e)
|
|
raise e
|
|
|
|
|
|
def decode(session_cookie_value, secret_key=None):
|
|
""" Decode a Flask cookie """
|
|
try:
|
|
if(secret_key==None):
|
|
compressed = False
|
|
payload = session_cookie_value
|
|
|
|
if payload.startswith('.'):
|
|
compressed = True
|
|
payload = payload[1:]
|
|
|
|
data = payload.split(".")[0]
|
|
|
|
data = base64_decode(data)
|
|
if compressed:
|
|
data = zlib.decompress(data)
|
|
|
|
return data
|
|
else:
|
|
app = MockApp(secret_key)
|
|
|
|
si = SecureCookieSessionInterface()
|
|
s = si.get_signing_serializer(app)
|
|
|
|
return s.loads(session_cookie_value)
|
|
except Exception as e:
|
|
return "[Decoding error] {}".format(e)
|
|
raise e
|
|
else: # > 3.4
|
|
class FSCM(ABC):
|
|
def encode(secret_key, session_cookie_structure):
|
|
""" Encode a Flask session cookie """
|
|
try:
|
|
app = MockApp(secret_key)
|
|
|
|
session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
|
|
si = SecureCookieSessionInterface()
|
|
s = si.get_signing_serializer(app)
|
|
|
|
return s.dumps(session_cookie_structure)
|
|
except Exception as e:
|
|
return "[Encoding error] {}".format(e)
|
|
raise e
|
|
|
|
|
|
def decode(session_cookie_value, secret_key=None):
|
|
""" Decode a Flask cookie """
|
|
try:
|
|
if(secret_key==None):
|
|
compressed = False
|
|
payload = session_cookie_value
|
|
|
|
if payload.startswith('.'):
|
|
compressed = True
|
|
payload = payload[1:]
|
|
|
|
data = payload.split(".")[0]
|
|
|
|
data = base64_decode(data)
|
|
if compressed:
|
|
data = zlib.decompress(data)
|
|
|
|
return data
|
|
else:
|
|
app = MockApp(secret_key)
|
|
|
|
si = SecureCookieSessionInterface()
|
|
s = si.get_signing_serializer(app)
|
|
|
|
return s.loads(session_cookie_value)
|
|
except Exception as e:
|
|
return "[Decoding error] {}".format(e)
|
|
raise e
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Args are only relevant for __main__ usage
|
|
|
|
## Description for help
|
|
parser = argparse.ArgumentParser(
|
|
description='Flask Session Cookie Decoder/Encoder',
|
|
epilog="Author : Wilson Sumanang, Alexandre ZANNI")
|
|
|
|
## prepare sub commands
|
|
subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')
|
|
|
|
## create the parser for the encode command
|
|
parser_encode = subparsers.add_parser('encode', help='encode')
|
|
parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
|
|
help='Secret key', required=True)
|
|
parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
|
|
help='Session cookie structure', required=True)
|
|
|
|
## create the parser for the decode command
|
|
parser_decode = subparsers.add_parser('decode', help='decode')
|
|
parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
|
|
help='Secret key', required=False)
|
|
parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
|
|
help='Session cookie value', required=True)
|
|
|
|
## get args
|
|
args = parser.parse_args()
|
|
|
|
## find the option chosen
|
|
if(args.subcommand == 'encode'):
|
|
if(args.secret_key is not None and args.cookie_structure is not None):
|
|
print(FSCM.encode(args.secret_key, args.cookie_structure))
|
|
elif(args.subcommand == 'decode'):
|
|
if(args.secret_key is not None and args.cookie_value is not None):
|
|
print(FSCM.decode(args.cookie_value,args.secret_key))
|
|
elif(args.cookie_value is not None):
|
|
print(FSCM.decode(args.cookie_value))
|
|
|