使用Jython开发flask-session-manager-for-burp插件

之前电面被问到是否开发过burp插件,回答没有。。很尴尬。。之前都是用burp自带的功能进行测试,没有了解过插件方面,今天看了看插件,发现好多不错的插件,打算自己魔改一个出来,就以flask-session-manager为基础改一个出来吧,方便平时的测试,后期如果再改的话,可能要改成爆破secret_key的方式来探测是否是弱密钥。

Jython开发环境搭建

本机是Mac,所以只讲一下Mac上的安装方式

1
brew install jython
1
2
3
4
5
$ jython
Jython 2.7.1 (default:0df7adb1b397, Jun 30 2017, 19:02:43)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.8.0_201
Type "help", "copyright", "credits" or "license" for more information.
>>>

终端输入出现上面这些就说明装好了,炒鸡简单

配置burp

1.png

如图配置就行

Jython 第三方库安装

中途势必会用到flask相关的库,所以先安装第三方库,和平时安装一样,不过要调用jython自带的pip

1
2
3
4
5
6
7
8
9
10
# dawn @ dawndeMacBook-Pro in /usr/local/Cellar/jython/2.7.1/libexec/bin [15:25:00]
$ ./pip install flask
Requirement already satisfied: flask in /usr/local/Cellar/jython/2.7.1/libexec/Lib/site-packages
Requirement already satisfied: itsdangerous>=0.24 in /usr/local/Cellar/jython/2.7.1/libexec/Lib/site-packages (from flask)
Requirement already satisfied: Werkzeug>=0.14 in /usr/local/Cellar/jython/2.7.1/libexec/Lib/site-packages (from flask)
Requirement already satisfied: Jinja2>=2.10 in /usr/local/Cellar/jython/2.7.1/libexec/Lib/site-packages (from flask)
Requirement already satisfied: click>=5.1 in /usr/local/Cellar/jython/2.7.1/libexec/Lib/site-packages (from flask)
Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/Cellar/jython/2.7.1/libexec/Lib/site-packages (from Jinja2>=2.10->flask)
You are using pip version 9.0.1, however version 19.0.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

然后新建一个flask_session_attack.py,开始写代码了。。

Jython代码编写

首先引入burp的接口

1
2
3
4
5
from burp import IBurpExtender
from burp import IContextMenuFactory
from burp import IBurpExtenderCallbacks
from burp import IHttpRequestResponse
from burp import IHttpListener

https://portswigger.net/burp/extender/api/ 查看burp提供的详细接口文档

这个 IBurpExtender 和 IBurpExtenderCallbacks 都是必须引入的,其它的根据具体情况决定是否引入,比如IHttpListener是获取http请求以及响应内容的接口等。

然后找找flask-session-manager源代码,稍微改一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import zlib
import ast
from itsdangerous import base64_decode
from flask.sessions import SecureCookieSessionInterface


class MockApp(object):

def __init__(self, secret_key):
self.secret_key = secret_key


def session_cookie_encoder(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)


def session_cookie_decoder(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if (secret_key == None):
compressed = False
payload = session_cookie_value

if payload.startswith(b'.'):
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)


def decode(cookie, secret_key):
print(session_cookie_decoder(cookie, secret_key))


def encode(cookie_structure,secret_key):
print(session_cookie_encoder(secret_key,cookie_structure))

然后写BurpExtender类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from javax.swing import JMenuItem
from javax.swing import JOptionPane
class BurpExtender(IBurpExtender, IHttpListener, IContextMenuFactory, IHttpRequestResponse,
IBurpExtenderCallbacks):
# 首先需要继承上面引入的接口,不然没法调用

def registerExtenderCallbacks(self, callbacks):
self._actionName = "decode_flask_session" # 选项名称
self._actionName1 = "encode_flask_session" # 选项名称
self._helers = callbacks.getHelpers()
self._callbacks = callbacks
callbacks.setExtensionName("flask_session_manager") # 插件名称
callbacks.registerHttpListener(self) # 注册
callbacks.registerContextMenuFactory(self) # 注册

return

def createMenuItems(self, invocation):
'''
重写的方法,作用是创建菜单子选项,看函数名就差不多能理解了
'''
menu = []
# invocation 是一个不知道哪来的值,没关系,文档里有这个,看看就懂了。
# getSelectedMessages 也不知道哪来的,同上
responses = invocation.getSelectedMessages()
if len(responses) == 1:
# 可以看到上面已经引用了java的swing包了,这就是jython的特性所在,可以引入java的包使用
# 这里创建了两个子选项,按下动作分别指向两个函数 decode_session 和 encode_session
menu.append(
JMenuItem(self._actionName, None, actionPerformed=lambda x, inv=invocation: self.decode_session(inv)))
menu.append(JMenuItem(self._actionName1,None,actionPerformed=lambda x: self.encode_session()))
return menu
return None

def decode_session(self, invocation):
# 解密函数,因为解密需要cookie和secret_key,所以这里造了一个对话框让用户输入已知的secret_key
# 我不知道JOptionPane怎么用,于是百度了一下 'java swing JOptionPane' 就全有了
secret_key = JOptionPane.showInputDialog(None, "secret_key:", "input", JOptionPane.QUESTION_MESSAGE)
invMessage = invocation.getSelectedMessages()
# request 就是一个完整的请求报文
request = invMessage[0].getRequest().tostring()
# 获取选中的需要解密的cookie所在的位置
select_msg_index = invocation.getSelectionBounds()
# 提取cookie
select_cookie = request[select_msg_index[0]:select_msg_index[1]]
# 调用上面的decode函数进行解密
decode(select_cookie, secret_key)

def encode_session(self):
# cookie_structure是需要加密伪造的json格式的原始数据
# 例如 {u'username': u'admin'}
cookie_structure = JOptionPane.showInputDialog(None, "cookie_structure:", "input", JOptionPane.QUESTION_MESSAGE)
secret_key = JOptionPane.showInputDialog(None, "secret_key:", "input", JOptionPane.QUESTION_MESSAGE)
encode(cookie_structure, secret_key)

注释都写在上面了,差不多就这样了,已经能用了。如果想进一步开发,还是要多看看它给的文档。

完整源码

作者

Dawnnnnnn

发布于

2019-03-29

更新于

2022-07-06

许可协议

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

评论