· 6 years ago · Oct 03, 2019, 12:28 AM
1""" Flask Session Cookie Decoder/Encoder """
2__author__ = 'Wilson Sumanang, Alexandre ZANNI'
3
4# standard imports
5import sys
6import zlib
7from itsdangerous import base64_decode
8import ast
9
10# Abstract Base Classes (PEP 3119)
11if sys.version_info[0] < 3: # < 3.0
12 raise Exception('Must be using at least Python 3')
13elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
14 from abc import ABCMeta, abstractmethod
15else: # > 3.4
16 from abc import ABC, abstractmethod
17
18# Lib for argument parsing
19import argparse
20
21# external Imports
22from flask.sessions import SecureCookieSessionInterface
23
24class MockApp(object):
25
26 def __init__(self, secret_key):
27 self.secret_key = secret_key
28
29
30if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
31 class FSCM(metaclass=ABCMeta):
32 def encode(secret_key, session_cookie_structure):
33 """ Encode a Flask session cookie """
34 try:
35 app = MockApp(secret_key)
36
37 session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
38 si = SecureCookieSessionInterface()
39 s = si.get_signing_serializer(app)
40
41 return s.dumps(session_cookie_structure)
42 except Exception as e:
43 return "[Encoding error] {}".format(e)
44 raise e
45
46
47 def decode(session_cookie_value, secret_key=None):
48 """ Decode a Flask cookie """
49 try:
50 if(secret_key==None):
51 compressed = False
52 payload = session_cookie_value
53
54 if payload.startswith('.'):
55 compressed = True
56 payload = payload[1:]
57
58 data = payload.split(".")[0]
59
60 data = base64_decode(data)
61 if compressed:
62 data = zlib.decompress(data)
63
64 return data
65 else:
66 app = MockApp(secret_key)
67
68 si = SecureCookieSessionInterface()
69 s = si.get_signing_serializer(app)
70
71 return s.loads(session_cookie_value)
72 except Exception as e:
73 return "[Decoding error] {}".format(e)
74 raise e
75else: # > 3.4
76 class FSCM(ABC):
77 def encode(secret_key, session_cookie_structure):
78 """ Encode a Flask session cookie """
79 try:
80 app = MockApp(secret_key)
81
82 session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
83 si = SecureCookieSessionInterface()
84 s = si.get_signing_serializer(app)
85
86 return s.dumps(session_cookie_structure)
87 except Exception as e:
88 return "[Encoding error] {}".format(e)
89 raise e
90
91
92 def decode(session_cookie_value, secret_key=None):
93 """ Decode a Flask cookie """
94 try:
95 if(secret_key==None):
96 compressed = False
97 payload = session_cookie_value
98
99 if payload.startswith('.'):
100 compressed = True
101 payload = payload[1:]
102
103 data = payload.split(".")[0]
104
105 data = base64_decode(data)
106 if compressed:
107 data = zlib.decompress(data)
108
109 return data
110 else:
111 app = MockApp(secret_key)
112
113 si = SecureCookieSessionInterface()
114 s = si.get_signing_serializer(app)
115
116 return s.loads(session_cookie_value)
117 except Exception as e:
118 return "[Decoding error] {}".format(e)
119 raise e
120
121
122if __name__ == "__main__":
123 # Args are only relevant for __main__ usage
124
125 ## Description for help
126 parser = argparse.ArgumentParser(
127 description='Flask Session Cookie Decoder/Encoder',
128 epilog="Author : Wilson Sumanang, Alexandre ZANNI")
129
130 ## prepare sub commands
131 subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')
132
133 ## create the parser for the encode command
134 parser_encode = subparsers.add_parser('encode', help='encode')
135 parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
136 help='Secret key', required=True)
137 parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
138 help='Session cookie structure', required=True)
139
140 ## create the parser for the decode command
141 parser_decode = subparsers.add_parser('decode', help='decode')
142 parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
143 help='Secret key', required=False)
144 parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
145 help='Session cookie value', required=True)
146
147 ## get args
148 args = parser.parse_args()
149
150 ## find the option chosen
151 if(args.subcommand == 'encode'):
152 if(args.secret_key is not None and args.cookie_structure is not None):
153 print(FSCM.encode(args.secret_key, args.cookie_structure))
154 elif(args.subcommand == 'decode'):
155 if(args.secret_key is not None and args.cookie_value is not None):
156 print(FSCM.decode(args.cookie_value,args.secret_key))
157 elif(args.cookie_value is not None):
158 print(FSCM.decode(args.cookie_value))