class BurpExtender(IBurpExtender, IProxyListener, ITab): def getTabCaption(self): ### ITab return NAME def getUiComponent(self): ### ITab return self.tabs def setFontItalic(self, label): label.setFont( Font(label.getFont().getName(), Font.ITALIC, label.getFont().getSize())) def setFontBold(self, label): label.setFont(Font('Serif', Font.BOLD, label.getFont().getSize())) def registerExtenderCallbacks(self, this_callbacks): ### IBurpExtender global callbacks, helpers global extension_enable, in_scope_only global change_method_to_post callbacks = this_callbacks helpers = callbacks.getHelpers() callbacks.setExtensionName(NAME) self.settings = JPanel(GridBagLayout()) c = GridBagConstraints() self.extension_enable_box = JCheckBox('Enable extension', extension_enable) self.setFontBold(self.extension_enable_box) self.extension_enable_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 0 c.gridwidth = 1 c.weightx = 1 c.fill = GridBagConstraints.NONE c.anchor = GridBagConstraints.WEST self.settings.add(self.extension_enable_box, c) self.in_scope_only_box = JCheckBox('Modify only in-scope requests', in_scope_only) self.setFontBold(self.in_scope_only_box) self.in_scope_only_box.setForeground(Color(0, 0, 153)) c.insets = Insets(40, 5, 5, 5) c.gridx = 0 c.gridy = 1 self.settings.add(self.in_scope_only_box, c) self.change_method_to_post_box = JCheckBox( 'Change HTTP method to POST', change_method_to_post) self.setFontBold(self.change_method_to_post_box) self.change_method_to_post_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 6 self.settings.add(self.change_method_to_post_box, c) change_method_to_post_lbl = JLabel( 'Check to convert PUT/DELETE/PATCH method to POST in all requests.' ) self.setFontItalic(change_method_to_post_lbl) c.gridx = 0 c.gridy = 7 self.settings.add(change_method_to_post_lbl, c) self.change_to_get_box = JCheckBox('Change to GET', change_to_get) self.setFontBold(self.change_to_get_box) self.change_to_get_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 12 self.settings.add(self.change_to_get_box, c) change_to_get_lbl = JLabel( 'Check to convert POST/PUT/DELETE/PATCH url-encoded requests to GET.' ) self.setFontItalic(change_to_get_lbl) c.gridx = 0 c.gridy = 13 self.settings.add(change_to_get_lbl, c) self.tabs = JTabbedPane() self.tabs.addTab('Settings', self.settings) callbacks.customizeUiComponent(self.tabs) callbacks.addSuiteTab(self) callbacks.registerProxyListener(self) print "Successfully loaded %s v%s by Mohammed alsaggaf " % (NAME, VERSION) def text_area_to_list(self, text_area): l = text_area.getText().strip().split('\n') return l if l != [''] else [] def processProxyMessage(self, messageIsRequest, message): ### IProxyListener global callbacks extension_enable = self.extension_enable_box.isSelected() if not extension_enable: return # Do nothing in_scope_only = self.in_scope_only_box.isSelected() change_method_to_post = self.change_method_to_post_box.isSelected() change_to_get = self.change_to_get_box.isSelected() request_response = message.getMessageInfo() request_info = helpers.analyzeRequest(request_response) request_method = request_info.getMethod() if in_scope_only and not callbacks.isInScope(request_info.getUrl()): return # Do nothing when URL is not in scope if not messageIsRequest or request_method not in [ 'POST', 'PUT', 'DELETE', 'PATCH' ]: return # Do nothing http_service = request_response.getHttpService() request = request_response.getRequest() headers = request_info.getHeaders() parameters = request_info.getParameters() new_headers = headers #new added offset = helpers.analyzeRequest(http_service, request).getBodyOffset() body = request[offset:] body = re.sub(",\s*,", ",", body) body = re.sub("{\s*,", "{", body) body = re.sub(",\s*}", "}", body) request = helpers.buildHttpMessage(headers, body) offset = helpers.analyzeRequest(http_service, request).getBodyOffset() body = request[offset:] #new Added if (change_method_to_post and request_method != 'POST') or (change_to_get and \ request_info.getContentType() == IRequestInfo.CONTENT_TYPE_URL_ENCODED): for i in range(len(new_headers)): if new_headers[i].startswith("PUT") or new_headers[i].startswith("DELETE") \ or new_headers[i].startswith("PATCH"): new_headers[i] = new_headers[i].replace( request_method, 'POST', 1) break new_request = helpers.buildHttpMessage( new_headers, body) # Create new request with valid Content-Length if (change_method_to_post and request_method != 'POST') or (change_to_get and \ request_info.getContentType() == IRequestInfo.CONTENT_TYPE_URL_ENCODED): param1 = helpers.buildParameter('method', request_method, IParameter.PARAM_URL) param2 = helpers.buildParameter('_method', request_method, IParameter.PARAM_URL) new_request = helpers.addParameter(new_request, param1) new_request = helpers.addParameter(new_request, param2) if change_to_get: new_request = helpers.toggleRequestMethod( new_request) # Change any URL-encoded request to GET self._callbacks.addToSiteMap(request_response) message.setInterceptAction( IInterceptedProxyMessage.ACTION_FOLLOW_RULES_AND_REHOOK) message.getMessageInfo().setRequest(new_request) message.getMessageInfo().setHighlight('red') self._callbacks.addToSiteMap(request_response)
class tag(ITab): def __init__(self, callbacks, name): self._callbacks = callbacks self.name = name def getTabCaption(self): return self.name def getUiComponent(self): return self.tabs def setFontItalic(self, label): label.setFont( Font(label.getFont().getName(), Font.ITALIC, label.getFont().getSize())) def setFontBold(self, label): label.setFont(Font('Serif', Font.BOLD, label.getFont().getSize())) # 配置界面添加 def tagLoad(self): # 创建窗口 开始 self.tabs = JTabbedPane() self.scan_type_settings = JPanel(GridBagLayout()) c = GridBagConstraints() # 界面选项卡加载 self.tag_1(c) self.tag_2(c) self.tag_3(c) # 添加选项卡 self.tabs.addTab(u'扫描类型设置', self.scan_type_settings) self._callbacks.customizeUiComponent(self.tabs) self._callbacks.addSuiteTab(self) # 选项卡1-标签1-ui def tag_1(self, c): # 创建 检查框 self.is_scan_get_start_box = JCheckBox(u'是否扫描GET类型的参数(推荐打勾)', XssConfig.IS_SCAN_GET_START) self.setFontBold(self.is_scan_get_start_box) self.is_scan_get_start_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 1 self.scan_type_settings.add(self.is_scan_get_start_box, c) # 选项卡1-标签2-ui def tag_2(self, c): # 创建 检查框 self.is_scan_post_start_box = JCheckBox(u'是否扫描POST类型的参数(推荐打勾)', XssConfig.IS_SCAN_POST_START) self.setFontBold(self.is_scan_post_start_box) self.is_scan_post_start_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 2 self.scan_type_settings.add(self.is_scan_post_start_box, c) def tag_3(self, c): # 创建 检查框 self.is_scan_url_path_folders_box = JCheckBox( u'扫描URL路径作为参数', XssConfig.IS_SCAN_URL_PATH_FOLDERS) self.setFontBold(self.is_scan_url_path_folders_box) self.is_scan_url_path_folders_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 3 self.scan_type_settings.add(self.is_scan_url_path_folders_box, c) def getScanTypeList(self): type_list = [] if self.is_scan_get_start_box.isSelected(): type_list.append(0) if self.is_scan_post_start_box.isSelected(): type_list.append(1) if self.is_scan_url_path_folders_box.isSelected(): type_list.append(33) type_list.append(37) return type_list
class tag(ITab): def __init__(self, callbacks, name): self._callbacks = callbacks self.name = name def getTabCaption(self): return self.name def getUiComponent(self): return self.tabs def setFontItalic(self, label): label.setFont( Font(label.getFont().getName(), Font.ITALIC, label.getFont().getSize())) def setFontBold(self, label): label.setFont(Font('Serif', Font.BOLD, label.getFont().getSize())) # 配置界面添加 def tagLoad(self): # 创建窗口 开始 self.tabs = JTabbedPane() self.settings = JPanel(GridBagLayout()) self.forward_requests_settings = JPanel(GridBagLayout()) self.white_list_domain_settings = JPanel(GridBagLayout()) self.white_list_http_method_settings = JPanel(GridBagLayout()) c = GridBagConstraints() # 界面选项卡1-标签加载 self.tag_1_1(c) self.tag_1_2(c) # 界面选项卡2-标签加载 self.tag_2_1(c) self.tag_2_2(c) # 界面选项卡3-标签加载 self.tag_3_1(c) # 界面选项卡4-标签加载 self.tag_4_1(c) self.tag_4_2(c) self.tag_4_3(c) self.tag_4_4(c) self.tag_4_5(c) self.tag_4_6(c) self.tag_4_7(c) self.tag_4_8(c) self.tag_4_9(c) self.tag_4_10(c) self.tag_4_11(c) self.tag_4_12(c) self.tag_4_13(c) self.tag_4_14(c) self.tag_4_15(c) # 添加选项卡 self.tabs.addTab(u'基本设置', self.settings) self.tabs.addTab(u'http请求转发设置', self.forward_requests_settings) self.tabs.addTab(u'白名单域名设置', self.white_list_domain_settings) self.tabs.addTab(u'白名单http方法设置', self.white_list_http_method_settings) self._callbacks.customizeUiComponent(self.tabs) self._callbacks.addSuiteTab(self) # 选项卡1-标签1-ui def tag_1_1(self, c): # 创建 检查框 self.is_start_box = JCheckBox(u'是否启动插件', ForwardRequestsConfig.IS_START) self.setFontBold(self.is_start_box) self.is_start_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 1 self.settings.add(self.is_start_box, c) # 在窗口添加一句话 is_start_box_lbl = JLabel(u'打勾-启动, 不打勾-关闭') self.setFontItalic(is_start_box_lbl) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 2 self.settings.add(is_start_box_lbl, c) # 选项卡1-标签1-值 def isStartBox(self): return self.is_start_box.isSelected() # 选项卡1-标签2-ui def tag_1_2(self, c): # 创建 检查框 self.url_repeated_box = JCheckBox( u'是否启动url重复验证', ForwardRequestsConfig.URL_REPEATED_VERIFY) self.setFontBold(self.url_repeated_box) self.url_repeated_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 3 self.settings.add(self.url_repeated_box, c) # 在窗口添加一句话 url_repeated_box_lbl = JLabel(u'打勾-开启验证, 不打勾-关闭验证') self.setFontItalic(url_repeated_box_lbl) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 4 self.settings.add(url_repeated_box_lbl, c) # 选项卡1-标签2-值 def urlRepeatedBox(self): return self.url_repeated_box.isSelected() # 选项卡2-标签1-ui def tag_2_1(self, c): # 创建 检查框 self.is_proxy_forward_requests_box = JCheckBox( u'是否启动Proxy模块请求转发(推荐打勾)', ForwardRequestsConfig.IS_START_PROXY_FORWARD_REQUESTS) self.setFontBold(self.is_proxy_forward_requests_box) self.is_proxy_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 1 self.forward_requests_settings.add(self.is_proxy_forward_requests_box, c) # 在窗口添加一句话 is_proxy_forward_requests_box_lbl = JLabel(u'打勾-启动, 不打勾-关闭') self.setFontItalic(is_proxy_forward_requests_box_lbl) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 2 self.forward_requests_settings.add(is_proxy_forward_requests_box_lbl, c) # 选项卡2-标签2-ui def tag_2_2(self, c): # 创建 检查框 self.is_repeater_forward_requests_box = JCheckBox( u'是否启动Repeater模块请求转发', ForwardRequestsConfig.IS_START_REPEATER_FORWARD_REQUESTS) self.setFontBold(self.is_repeater_forward_requests_box) self.is_repeater_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 3 self.forward_requests_settings.add( self.is_repeater_forward_requests_box, c) # 在窗口添加一句话 is_repeater_forward_requests_box_lbl = JLabel(u'打勾-启动, 不打勾-关闭') self.setFontItalic(is_repeater_forward_requests_box_lbl) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 4 self.forward_requests_settings.add( is_repeater_forward_requests_box_lbl, c) # 获取允许转发的burp模块列表 def getWhiteListModule(self): white_list_module = [] if self.is_proxy_forward_requests_box.isSelected(): white_list_module.append(4) if self.is_repeater_forward_requests_box.isSelected(): white_list_module.append(64) return white_list_module # 选项卡3-标签1-ui def tag_3_1(self, c): # 输入框-标题 lblParams = JLabel(u'请填写域名:') self.setFontBold(lblParams) lblParams.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 0 c.insets = Insets(5, 5, 5, 5) c.fill = GridBagConstraints.NONE c.anchor = GridBagConstraints.FIRST_LINE_END self.white_list_domain_settings.add(lblParams, c) # 输入框 self.white_list_text_field = JTextField() c.fill = GridBagConstraints.BOTH c.gridx = 1 c.gridy = 0 self.white_list_domain_settings.add(self.white_list_text_field, c) lblParamsNote = JLabel(u"白名单域名列表") self.setFontItalic(lblParamsNote) c.fill = GridBagConstraints.NONE c.gridx = 0 c.gridy = 1 self.white_list_domain_settings.add(lblParamsNote, c) # 添加 文本框 self.white_list_text_area = JTextArea() self.white_list_text_area.setColumns(20) self.white_list_text_area.setRows(10) self.white_list_text_area.setEditable(False) c.fill = GridBagConstraints.BOTH self.white_list_mouse_listener = TextAreaMouseListener( self.white_list_text_area) self.white_list_text_area.addMouseListener( self.white_list_mouse_listener) # 向文本框添加数据 for name in white_list_names: self.white_list_text_area.append(name + '\n' + os.linesep) c.gridx = 1 c.gridy = 1 sp = JScrollPane(self.white_list_text_area) self.white_list_domain_settings.add(sp, c) # 添加 删除 重置 buttonsPanel = JPanel(GridBagLayout()) _c = GridBagConstraints() _c.insets = Insets(3, 3, 3, 3) _c.gridx = 0 _c.fill = GridBagConstraints.BOTH _c.weightx = 1 _c.gridwidth = 1 handlers = ButtonHandlers(self.white_list_text_field, self.white_list_text_area, self.white_list_mouse_listener, white_list_names) # 添加按钮 self.white_list_add_button = JButton( u'添加', actionPerformed=handlers.handler_add) _c.gridy = 1 buttonsPanel.add(self.white_list_add_button, _c) # 删除按钮 self.white_list_rm_button = JButton( u'删除', actionPerformed=handlers.handler_rm) _c.gridy = 2 buttonsPanel.add(self.white_list_rm_button, _c) # 重置按钮 self.white_list_restore_button = JButton( u'重置', actionPerformed=handlers.handler_restore) _c.gridy = 3 buttonsPanel.add(self.white_list_restore_button, _c) c.gridx = 2 c.gridy = 1 c.fill = GridBagConstraints.NONE self.white_list_domain_settings.add(buttonsPanel, c) # 获取白名单域名列表 def getWhiteList(self): return self.text_area_to_list(self.white_list_text_area) # 获取指定text数据 def text_area_to_list(self, text_area): l = [] text_list = text_area.getText().strip().split('\n') for data in text_list: if data == '': continue data = data.replace("\n", '') data = data.replace("\r", '') data = data.strip(' ') l.append(data) return l # 选项卡4-标签1-ui def tag_4_1(self, c): # 创建 检查框 self.is_get_forward_requests_box = JCheckBox( u'转发GET请求', ForwardRequestsConfig.IS_GET_FORWARD_REQUESTS) self.setFontBold(self.is_get_forward_requests_box) self.is_get_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 1 self.white_list_http_method_settings.add( self.is_get_forward_requests_box, c) # 选项卡4-标签2-ui def tag_4_2(self, c): # 创建 检查框 self.is_post_forward_requests_box = JCheckBox( u'转发POST请求', ForwardRequestsConfig.IS_POST_FORWARD_REQUESTS) self.setFontBold(self.is_post_forward_requests_box) self.is_post_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 2 self.white_list_http_method_settings.add( self.is_post_forward_requests_box, c) # 选项卡4-标签3-ui def tag_4_3(self, c): # 创建 检查框 self.is_put_forward_requests_box = JCheckBox( u'转发PUT请求', ForwardRequestsConfig.IS_PUT_FORWARD_REQUESTS) self.setFontBold(self.is_put_forward_requests_box) self.is_put_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 3 self.white_list_http_method_settings.add( self.is_put_forward_requests_box, c) # 选项卡4-标签4-ui def tag_4_4(self, c): # 创建 检查框 self.is_patch_forward_requests_box = JCheckBox( u'转发PATCH请求', ForwardRequestsConfig.IS_PATCH_FORWARD_REQUESTS) self.setFontBold(self.is_patch_forward_requests_box) self.is_patch_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 4 self.white_list_http_method_settings.add( self.is_patch_forward_requests_box, c) # 选项卡4-标签5-ui def tag_4_5(self, c): # 创建 检查框 self.is_delete_forward_requests_box = JCheckBox( u'转发DELETE请求', ForwardRequestsConfig.IS_DELETE_FORWARD_REQUESTS) self.setFontBold(self.is_delete_forward_requests_box) self.is_delete_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 5 self.white_list_http_method_settings.add( self.is_delete_forward_requests_box, c) # 选项卡4-标签6-ui def tag_4_6(self, c): # 创建 检查框 self.is_copy_forward_requests_box = JCheckBox( u'转发COPY请求', ForwardRequestsConfig.IS_COPY_FORWARD_REQUESTS) self.setFontBold(self.is_copy_forward_requests_box) self.is_copy_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 6 self.white_list_http_method_settings.add( self.is_copy_forward_requests_box, c) # 选项卡4-标签7-ui def tag_4_7(self, c): # 创建 检查框 self.is_head_forward_requests_box = JCheckBox( u'转发HEAD请求', ForwardRequestsConfig.IS_HEAD_FORWARD_REQUESTS) self.setFontBold(self.is_head_forward_requests_box) self.is_head_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 7 self.white_list_http_method_settings.add( self.is_head_forward_requests_box, c) # 选项卡4-标签8-ui def tag_4_8(self, c): # 创建 检查框 self.is_options_forward_requests_box = JCheckBox( u'转发OPTIONS请求', ForwardRequestsConfig.IS_OPTIONS_FORWARD_REQUESTS) self.setFontBold(self.is_options_forward_requests_box) self.is_options_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 8 self.white_list_http_method_settings.add( self.is_options_forward_requests_box, c) # 选项卡4-标签9-ui def tag_4_9(self, c): # 创建 检查框 self.is_link_forward_requests_box = JCheckBox( u'转发LINK请求', ForwardRequestsConfig.IS_LINK_FORWARD_REQUESTS) self.setFontBold(self.is_link_forward_requests_box) self.is_link_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 9 self.white_list_http_method_settings.add( self.is_link_forward_requests_box, c) # 选项卡4-标签10-ui def tag_4_10(self, c): # 创建 检查框 self.is_unlink_forward_requests_box = JCheckBox( u'转发UNLINK请求', ForwardRequestsConfig.IS_UNLINK_FORWARD_REQUESTS) self.setFontBold(self.is_unlink_forward_requests_box) self.is_unlink_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 10 self.white_list_http_method_settings.add( self.is_unlink_forward_requests_box, c) # 选项卡4-标签11-ui def tag_4_11(self, c): # 创建 检查框 self.is_purge_forward_requests_box = JCheckBox( u'转发PURGE请求', ForwardRequestsConfig.IS_PURGE_FORWARD_REQUESTS) self.setFontBold(self.is_purge_forward_requests_box) self.is_purge_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 11 self.white_list_http_method_settings.add( self.is_purge_forward_requests_box, c) # 选项卡4-标签12-ui def tag_4_12(self, c): # 创建 检查框 self.is_lock_forward_requests_box = JCheckBox( u'转发LOCK请求', ForwardRequestsConfig.IS_LOCK_FORWARD_REQUESTS) self.setFontBold(self.is_lock_forward_requests_box) self.is_lock_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 12 self.white_list_http_method_settings.add( self.is_lock_forward_requests_box, c) # 选项卡4-标签13-ui def tag_4_13(self, c): # 创建 检查框 self.is_unlock_forward_requests_box = JCheckBox( u'转发UNLOCK请求', ForwardRequestsConfig.IS_UNLOCK_FORWARD_REQUESTS) self.setFontBold(self.is_unlock_forward_requests_box) self.is_unlock_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 13 self.white_list_http_method_settings.add( self.is_unlock_forward_requests_box, c) # 选项卡4-标签14-ui def tag_4_14(self, c): # 创建 检查框 self.is_propfind_forward_requests_box = JCheckBox( u'转发PROPFIND请求', ForwardRequestsConfig.IS_PROPFIND_FORWARD_REQUESTS) self.setFontBold(self.is_propfind_forward_requests_box) self.is_propfind_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 14 self.white_list_http_method_settings.add( self.is_propfind_forward_requests_box, c) # 选项卡4-标签15-ui def tag_4_15(self, c): # 创建 检查框 self.is_view_forward_requests_box = JCheckBox( u'转发VIEW请求', ForwardRequestsConfig.IS_VIEW_FORWARD_REQUESTS) self.setFontBold(self.is_view_forward_requests_box) self.is_view_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 15 self.white_list_http_method_settings.add( self.is_view_forward_requests_box, c) # 获取白名单http方法 def getWhiteListHttpMethod(self): l = [] if self.is_get_forward_requests_box.isSelected(): l.append('GET') if self.is_post_forward_requests_box.isSelected(): l.append('POST') if self.is_put_forward_requests_box.isSelected(): l.append('PUT') if self.is_patch_forward_requests_box.isSelected(): l.append('PATCH') if self.is_delete_forward_requests_box.isSelected(): l.append('DELETE') if self.is_copy_forward_requests_box.isSelected(): l.append('COPY') if self.is_head_forward_requests_box.isSelected(): l.append('HEAD') if self.is_options_forward_requests_box.isSelected(): l.append('OPTIONS') if self.is_link_forward_requests_box.isSelected(): l.append('LINK') if self.is_unlink_forward_requests_box.isSelected(): l.append('UNLINK') if self.is_purge_forward_requests_box.isSelected(): l.append('PURGE') if self.is_lock_forward_requests_box.isSelected(): l.append('LOCK') if self.is_unlock_forward_requests_box.isSelected(): l.append('UNLOCK') if self.is_propfind_forward_requests_box.isSelected(): l.append('PROPFIND') if self.is_view_forward_requests_box.isSelected(): l.append('VIEW') return l
class BurpExtender(IBurpExtender, IProxyListener, ITab): def getTabCaption(self): ### ITab return NAME def getUiComponent(self): ### ITab return self.tabs def setFontItalic(self, label): label.setFont( Font(label.getFont().getName(), Font.ITALIC, label.getFont().getSize())) def setFontBold(self, label): label.setFont(Font('Serif', Font.BOLD, label.getFont().getSize())) def registerExtenderCallbacks(self, this_callbacks): ### IBurpExtender global callbacks, helpers global extension_enable, in_scope_only global remove_csrf_headers, remove_csrf_params, change_method_to_post global change_ct_to_json, change_ct_to_plain, change_to_get callbacks = this_callbacks helpers = callbacks.getHelpers() callbacks.setExtensionName(NAME) self.settings = JPanel(GridBagLayout()) c = GridBagConstraints() self.extension_enable_box = JCheckBox('Enable extension', extension_enable) self.setFontBold(self.extension_enable_box) self.extension_enable_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 0 c.gridwidth = 1 c.weightx = 1 c.fill = GridBagConstraints.NONE c.anchor = GridBagConstraints.WEST self.settings.add(self.extension_enable_box, c) self.in_scope_only_box = JCheckBox('Modify only in-scope requests', in_scope_only) self.setFontBold(self.in_scope_only_box) self.in_scope_only_box.setForeground(Color(0, 0, 153)) c.insets = Insets(40, 5, 5, 5) c.gridx = 0 c.gridy = 1 self.settings.add(self.in_scope_only_box, c) self.remove_csrf_headers_box = JCheckBox('Remove CSRF headers', remove_csrf_params) self.setFontBold(self.remove_csrf_headers_box) self.remove_csrf_headers_box.setForeground(Color(0, 0, 153)) c.insets = Insets(40, 5, 5, 5) c.gridx = 0 c.gridy = 2 self.settings.add(self.remove_csrf_headers_box, c) remove_csrf_headers_box_lbl = JLabel( 'Check to remove headers with CSRF tokens from all requests.') self.setFontItalic(remove_csrf_headers_box_lbl) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 3 self.settings.add(remove_csrf_headers_box_lbl, c) self.remove_csrf_params_box = JCheckBox('Remove CSRF parameters', remove_csrf_params) self.setFontBold(self.remove_csrf_params_box) self.remove_csrf_params_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 4 self.settings.add(self.remove_csrf_params_box, c) remove_csrf_params_box_lbl = JLabel( 'Check to remove URL/body parameters with CSRF tokens from all requests. URL-encoded, multipart, JSON parameters are supported.' ) self.setFontItalic(remove_csrf_params_box_lbl) c.gridx = 0 c.gridy = 5 self.settings.add(remove_csrf_params_box_lbl, c) self.change_method_to_post_box = JCheckBox( 'Change HTTP method to POST', change_method_to_post) self.setFontBold(self.change_method_to_post_box) self.change_method_to_post_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 6 self.settings.add(self.change_method_to_post_box, c) change_method_to_post_lbl = JLabel( 'Check to convert PUT/DELETE/PATCH method to POST in all requests.' ) self.setFontItalic(change_method_to_post_lbl) c.gridx = 0 c.gridy = 7 self.settings.add(change_method_to_post_lbl, c) self.change_ct_to_json_box = JCheckBox('Change media type to json', change_ct_to_json) self.setFontBold(self.change_ct_to_json_box) self.change_ct_to_json_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 8 self.settings.add(self.change_ct_to_json_box, c) change_ct_to_json_lbl = JLabel( 'Check to convert body to json and set Content-Type to application/json in url-encoded requests.' ) self.setFontItalic(change_ct_to_json_lbl) c.gridx = 0 c.gridy = 9 self.settings.add(change_ct_to_json_lbl, c) self.change_ct_to_plain_box = JCheckBox( 'Change Content-Type to text/plain', change_ct_to_plain) self.setFontBold(self.change_ct_to_plain_box) self.change_ct_to_plain_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 10 self.settings.add(self.change_ct_to_plain_box, c) change_ct_to_plain_lbl = JLabel( 'Check to set Content-Type to text/plain in request with non-simple media type. Simple media types - application/application/x-www-form-urlencoded, text/plain, multipart/form-data.' ) self.setFontItalic(change_ct_to_plain_lbl) c.gridx = 0 c.gridy = 11 self.settings.add(change_ct_to_plain_lbl, c) self.change_to_get_box = JCheckBox('Change to GET', change_to_get) self.setFontBold(self.change_to_get_box) self.change_to_get_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 12 self.settings.add(self.change_to_get_box, c) change_to_get_lbl = JLabel( 'Check to convert POST/PUT/DELETE/PATCH url-encoded requests to GET.' ) self.setFontItalic(change_to_get_lbl) c.gridx = 0 c.gridy = 13 self.settings.add(change_to_get_lbl, c) self.csrf_headers_params = JPanel(GridBagLayout()) c = GridBagConstraints() lblParams = JLabel("CSRF parameters:") self.setFontBold(lblParams) lblParams.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 0 c.insets = Insets(5, 5, 5, 5) c.fill = GridBagConstraints.NONE c.anchor = GridBagConstraints.FIRST_LINE_END self.csrf_headers_params.add(lblParams, c) self.csrf_param_text_field = JTextField() c.fill = GridBagConstraints.BOTH c.gridx = 1 c.gridy = 0 self.csrf_headers_params.add(self.csrf_param_text_field, c) lblParamsNote = JLabel( "Remove parameter from request if name contains") self.setFontItalic(lblParamsNote) c.fill = GridBagConstraints.NONE c.gridx = 0 c.gridy = 1 self.csrf_headers_params.add(lblParamsNote, c) self.csrf_params_text_area = JTextArea() self.csrf_params_text_area.setColumns(20) self.csrf_params_text_area.setRows(10) self.csrf_params_text_area.setEditable(False) c.fill = GridBagConstraints.BOTH self.csrf_params_mouse_listener = TextAreaMouseListener( self.csrf_params_text_area) self.csrf_params_text_area.addMouseListener( self.csrf_params_mouse_listener) for name in csrf_params_names: self.csrf_params_text_area.append(name + os.linesep) c.gridx = 1 c.gridy = 1 sp = JScrollPane(self.csrf_params_text_area) self.csrf_headers_params.add(sp, c) buttonsPanel = JPanel(GridBagLayout()) _c = GridBagConstraints() _c.insets = Insets(3, 3, 3, 3) _c.gridx = 0 _c.gridy = 0 _c.fill = GridBagConstraints.BOTH _c.weightx = 1 _c.gridwidth = 1 handlers = ButtonHandlers(self.csrf_param_text_field, self.csrf_params_text_area, self.csrf_params_mouse_listener, csrf_params_names) self.csrf_param_add_button = JButton( 'Add', actionPerformed=handlers.handler_add) self.csrf_param_rm_button = JButton( 'Remove', actionPerformed=handlers.handler_rm) self.csrf_param_restore_button = JButton( 'Restore', actionPerformed=handlers.handler_restore) buttonsPanel.add(self.csrf_param_add_button, _c) _c.gridy = 1 buttonsPanel.add(self.csrf_param_rm_button, _c) _c.gridy = 2 buttonsPanel.add(self.csrf_param_restore_button, _c) _c.gridy = 3 c.gridx = 2 c.gridy = 1 c.fill = GridBagConstraints.NONE self.csrf_headers_params.add(buttonsPanel, c) lblHeaders = JLabel("CSRF headers:") self.setFontBold(lblHeaders) lblHeaders.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 2 c.insets = Insets(40, 5, 5, 5) c.fill = GridBagConstraints.NONE c.anchor = GridBagConstraints.FIRST_LINE_END self.csrf_headers_params.add(lblHeaders, c) self.csrf_header_text_field = JTextField() c.fill = GridBagConstraints.BOTH c.gridx = 1 c.gridy = 2 self.csrf_headers_params.add(self.csrf_header_text_field, c) lblHeadersNote = JLabel("Remove header from request if name equals to") self.setFontItalic(lblHeadersNote) c.fill = GridBagConstraints.NONE c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 3 self.csrf_headers_params.add(lblHeadersNote, c) self.csrf_headers_text_area = JTextArea() self.csrf_headers_text_area.setColumns(20) self.csrf_headers_text_area.setRows(10) self.csrf_headers_text_area.setEditable(False) c.fill = GridBagConstraints.BOTH self.csrf_headers_mouse_listener = TextAreaMouseListener( self.csrf_headers_text_area) self.csrf_headers_text_area.addMouseListener( self.csrf_headers_mouse_listener) for name in csrf_headers_names: self.csrf_headers_text_area.append(name + os.linesep) c.gridx = 1 c.gridy = 3 sp = JScrollPane(self.csrf_headers_text_area) self.csrf_headers_params.add(sp, c) buttonsPanel = JPanel(GridBagLayout()) _c = GridBagConstraints() _c.insets = Insets(3, 3, 3, 3) _c.gridx = 0 _c.gridy = 0 _c.fill = GridBagConstraints.BOTH _c.weightx = 1 _c.gridwidth = 1 handlers = ButtonHandlers(self.csrf_header_text_field, self.csrf_headers_text_area, self.csrf_headers_mouse_listener, csrf_headers_names) self.csrf_header_add_button = JButton( 'Add', actionPerformed=handlers.handler_add) self.csrf_header_rm_button = JButton( 'Remove', actionPerformed=handlers.handler_rm) self.csrf_header_restore_button = JButton( 'Restore', actionPerformed=handlers.handler_restore) buttonsPanel.add(self.csrf_header_add_button, _c) _c.gridy = 1 buttonsPanel.add(self.csrf_header_rm_button, _c) _c.gridy = 2 buttonsPanel.add(self.csrf_header_restore_button, _c) _c.gridy = 3 c.gridx = 2 c.gridy = 3 c.fill = GridBagConstraints.NONE self.csrf_headers_params.add(buttonsPanel, c) self.whitelist = JPanel(GridBagLayout()) c = GridBagConstraints() lblWhitelist = JLabel("URLs whitelist:") self.setFontBold(lblWhitelist) lblWhitelist.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 0 c.insets = Insets(5, 5, 5, 5) c.fill = GridBagConstraints.NONE c.anchor = GridBagConstraints.FIRST_LINE_END self.whitelist.add(lblWhitelist, c) self.whitelist_text_field = JTextField() c.fill = GridBagConstraints.BOTH c.gridx = 1 c.gridy = 0 self.whitelist.add(self.whitelist_text_field, c) lblWhitelistNote = JLabel( "Do not perform request modification if URL starts with") self.setFontItalic(lblWhitelistNote) c.fill = GridBagConstraints.NONE c.gridx = 0 c.gridy = 1 self.whitelist.add(lblWhitelistNote, c) self.whitelist_text_area = JTextArea() self.whitelist_text_area.setColumns(30) self.whitelist_text_area.setRows(10) self.whitelist_text_area.setEditable(False) c.fill = GridBagConstraints.BOTH self.whitelist_mouse_listener = TextAreaMouseListener( self.whitelist_text_area) self.whitelist_text_area.addMouseListener( self.whitelist_mouse_listener) c.gridx = 1 c.gridy = 1 sp = JScrollPane(self.whitelist_text_area) self.whitelist.add(sp, c) buttonsPanel = JPanel(GridBagLayout()) _c = GridBagConstraints() _c.insets = Insets(3, 3, 3, 3) _c.gridx = 0 _c.gridy = 0 _c.fill = GridBagConstraints.BOTH _c.weightx = 1 _c.gridwidth = 1 handlers = ButtonHandlers(self.whitelist_text_field, self.whitelist_text_area, self.whitelist_mouse_listener, []) self.whitelist_add_button = JButton( 'Add', actionPerformed=handlers.handler_add) self.whitelist_rm_button = JButton('Remove', actionPerformed=handlers.handler_rm) self.whitelist_clear_button = JButton( 'Clear', actionPerformed=handlers.handler_restore) buttonsPanel.add(self.whitelist_add_button, _c) _c.gridy = 1 buttonsPanel.add(self.whitelist_rm_button, _c) _c.gridy = 2 buttonsPanel.add(self.whitelist_clear_button, _c) _c.gridy = 3 c.gridx = 2 c.gridy = 1 c.fill = GridBagConstraints.NONE self.whitelist.add(buttonsPanel, c) self.tabs = JTabbedPane() self.tabs.addTab('Settings', self.settings) self.tabs.addTab('CSRF params/headers to remove', self.csrf_headers_params) self.tabs.addTab('Requests whitelist', self.whitelist) callbacks.customizeUiComponent(self.tabs) callbacks.addSuiteTab(self) callbacks.registerProxyListener(self) callbacks.registerContextMenuFactory( SendToWhitelist(self.whitelist_text_area)) print "Successfully loaded %s v%s by Mikhail Egorov @0ang3el" % ( NAME, VERSION) def text_area_to_list(self, text_area): l = text_area.getText().strip().split('\n') return l if l != [''] else [] def filter_headers(self, headers): _headers = headers[:] for header in headers: for csrf_header in self.text_area_to_list( self.csrf_headers_text_area): if header.lower().startswith(csrf_header.lower()): _headers.remove(header) return _headers def processProxyMessage(self, messageIsRequest, message): ### IProxyListener global callbacks extension_enable = self.extension_enable_box.isSelected() if not extension_enable: return # Do nothing in_scope_only = self.in_scope_only_box.isSelected() remove_csrf_headers = self.remove_csrf_headers_box.isSelected() remove_csrf_params = self.remove_csrf_params_box.isSelected() change_method_to_post = self.change_method_to_post_box.isSelected() change_ct_to_json = self.change_ct_to_json_box.isSelected() change_ct_to_plain = self.change_ct_to_plain_box.isSelected() change_to_get = self.change_to_get_box.isSelected() request_response = message.getMessageInfo() request_info = helpers.analyzeRequest(request_response) request_method = request_info.getMethod() if in_scope_only and not callbacks.isInScope(request_info.getUrl()): return # Do nothing when URL is not in scope if not messageIsRequest or request_method not in [ 'POST', 'PUT', 'DELETE', 'PATCH' ]: return # Do nothing for whitelisted in self.text_area_to_list(self.whitelist_text_area): if str(request_info.getUrl()).startswith(whitelisted): return # Do nothing when URL is whitelisted http_service = request_response.getHttpService() request = request_response.getRequest() headers = request_info.getHeaders() parameters = request_info.getParameters() new_headers = headers if remove_csrf_headers: new_headers = self.filter_headers(headers) # Remove CSRF headers if change_ct_to_plain and request_info.getContentType() not in [ IRequestInfo.CONTENT_TYPE_URL_ENCODED, IRequestInfo.CONTENT_TYPE_MULTIPART ]: for i in range(len(new_headers)): if new_headers[i].lower().startswith( 'content-type'): # Change CT to text/plain new_headers[i] = 'Content-Type: text/plain' if remove_csrf_params: for parameter in parameters: # Remove CSRF parameters from request's body or URL for csrf_param in self.text_area_to_list( self.csrf_params_text_area): if parameter.getType() != IParameter.PARAM_COOKIE and \ csrf_param.lower() in parameter.getName().lower(): if request_info.getContentType( ) == IRequestInfo.CONTENT_TYPE_MULTIPART: start = parameter.getNameStart() end = parameter.getNameEnd() request = request[:start] + helpers.stringToBytes( "REPLACEMENT") + request[end:] elif parameter.getType() == IParameter.PARAM_JSON: start = parameter.getNameStart() - 1 end = parameter.getValueEnd() + 1 request = request[:start] + request[end:] offset = helpers.analyzeRequest( http_service, request).getBodyOffset() body = request[offset:] body = re.sub(",\s*,", ",", body) body = re.sub("{\s*,", "{", body) body = re.sub(",\s*}", "}", body) request = helpers.buildHttpMessage(headers, body) elif parameter.getType() in [ IParameter.PARAM_URL, IParameter.PARAM_BODY ]: request = helpers.removeParameter( request, parameter) offset = helpers.analyzeRequest(http_service, request).getBodyOffset() body = request[offset:] if change_ct_to_json and request_info.getContentType( ) == IRequestInfo.CONTENT_TYPE_URL_ENCODED: for i in range(len(new_headers)): if new_headers[i].lower().startswith( 'content-type'): # Change to JSON from URL-encoded new_headers[i] = 'Content-Type: application/json' body = safe_bytes_to_string(body) d = dict((k, v if len(v) > 1 else v[0]) for k, v in parse_qs(body).iteritems()) body = dumps(d) if (change_method_to_post and request_method != 'POST') or (change_to_get and not change_ct_to_json and \ request_info.getContentType() == IRequestInfo.CONTENT_TYPE_URL_ENCODED): for i in range(len(new_headers)): if new_headers[i].startswith("PUT") or new_headers[i].startswith("DELETE") \ or new_headers[i].startswith("PATCH"): new_headers[i] = new_headers[i].replace( request_method, 'POST', 1) break new_request = helpers.buildHttpMessage( new_headers, body) # Create new request with valid Content-Length if (change_method_to_post and request_method != 'POST') or (change_to_get and not change_ct_to_json and \ request_info.getContentType() == IRequestInfo.CONTENT_TYPE_URL_ENCODED): param1 = helpers.buildParameter('method', request_method, IParameter.PARAM_URL) param2 = helpers.buildParameter('_method', request_method, IParameter.PARAM_URL) new_request = helpers.addParameter(new_request, param1) new_request = helpers.addParameter(new_request, param2) if change_to_get: new_request = helpers.toggleRequestMethod( new_request) # Change any URL-encoded request to GET message.setInterceptAction( IInterceptedProxyMessage.ACTION_FOLLOW_RULES_AND_REHOOK) message.getMessageInfo().setRequest(new_request) message.getMessageInfo().setHighlight('red')
class BurpExtender(IBurpExtender, IProxyListener, ITab): def getTabCaption(self): ### ITab return NAME def getUiComponent(self): ### ITab return self.settings def registerExtenderCallbacks(self, this_callbacks): ### IBurpExtender global callbacks, helpers global extension_enable global remove_csrf_headers, remove_csrf_params, change_method_to_post global change_ct_to_json, change_ct_to_plain, change_to_get callbacks = this_callbacks helpers = callbacks.getHelpers() callbacks.setExtensionName(NAME) self.settings = JPanel(GridBagLayout()) c = GridBagConstraints() self.extension_enable_box = JCheckBox('Enable extension', extension_enable) self.extension_enable_box.setFont(Font("Serif", Font.BOLD, 20)) self.extension_enable_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 0 c.gridwidth = 1 c.weightx = 1 c.fill = GridBagConstraints.NONE c.anchor = GridBagConstraints.WEST self.settings.add(self.extension_enable_box, c) self.remove_csrf_headers_box = JCheckBox('Remove CSRF headers', remove_csrf_params) self.remove_csrf_headers_box.setFont(Font("Serif", Font.BOLD, 20)) self.remove_csrf_headers_box.setForeground(Color(0, 0, 153)) c.insets = Insets(40, 5, 5, 5) c.gridx = 0 c.gridy = 1 self.settings.add(self.remove_csrf_headers_box, c) remove_csrf_headers_box_lbl = JLabel( 'Check to remove headers with CSRF tokens from all requests.') c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 2 self.settings.add(remove_csrf_headers_box_lbl, c) self.remove_csrf_params_box = JCheckBox('Remove CSRF parameters', remove_csrf_params) self.remove_csrf_params_box.setFont(Font("Serif", Font.BOLD, 20)) self.remove_csrf_params_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 3 self.settings.add(self.remove_csrf_params_box, c) remove_csrf_params_box_lbl = JLabel( 'Check to remove URL/body parameters with CSRF tokens from all requests. URL-encoded, multipart, JSON parameters are supported.' ) c.gridx = 0 c.gridy = 4 self.settings.add(remove_csrf_params_box_lbl, c) self.change_method_to_post_box = JCheckBox( 'Change HTTP method to POST', change_method_to_post) self.change_method_to_post_box.setFont(Font("Serif", Font.BOLD, 20)) self.change_method_to_post_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 5 self.settings.add(self.change_method_to_post_box, c) change_method_to_post_lbl = JLabel( 'Check to convert PUT/DELETE/PATCH method to POST in all requests.' ) c.gridx = 0 c.gridy = 6 self.settings.add(change_method_to_post_lbl, c) self.change_ct_to_json_box = JCheckBox('Change media type to json', change_ct_to_json) self.change_ct_to_json_box.setFont(Font("Serif", Font.BOLD, 20)) self.change_ct_to_json_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 7 self.settings.add(self.change_ct_to_json_box, c) change_ct_to_json_lbl = JLabel( 'Check to convert body to json and set Content-Type to application/json in url-encoded requests.' ) c.gridx = 0 c.gridy = 8 self.settings.add(change_ct_to_json_lbl, c) self.change_ct_to_plain_box = JCheckBox( 'Change Content-Type to text/plain', change_ct_to_plain) self.change_ct_to_plain_box.setFont(Font("Serif", Font.BOLD, 20)) self.change_ct_to_plain_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 9 self.settings.add(self.change_ct_to_plain_box, c) change_ct_to_plain_lbl = JLabel( 'Check to set Content-Type to text/plain in request with non-simple media type. Simple media types - application/application/x-www-form-urlencoded, text/plain, multipart/form-data.' ) c.gridx = 0 c.gridy = 10 self.settings.add(change_ct_to_plain_lbl, c) self.change_to_get_box = JCheckBox('Change to GET', change_to_get) self.change_to_get_box.setFont(Font("Serif", Font.BOLD, 20)) self.change_to_get_box.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 11 self.settings.add(self.change_to_get_box, c) change_to_get_lbl = JLabel( 'Check to convert POST/PUT/DELETE/PATCH url-encoded requests to GET.' ) c.gridx = 0 c.gridy = 12 self.settings.add(change_to_get_lbl, c) callbacks.customizeUiComponent(self.settings) callbacks.addSuiteTab(self) callbacks.registerProxyListener(self) print "Successfully loaded %s v%s" % (NAME, VERSION) def processProxyMessage(self, messageIsRequest, message): ### IProxyListener extension_enable = self.extension_enable_box.isSelected() if not extension_enable: return # Do nothing remove_csrf_headers = self.remove_csrf_headers_box.isSelected() remove_csrf_params = self.remove_csrf_params_box.isSelected() change_method_to_post = self.change_method_to_post_box.isSelected() change_ct_to_json = self.change_ct_to_json_box.isSelected() change_ct_to_plain = self.change_ct_to_plain_box.isSelected() change_to_get = self.change_to_get_box.isSelected() request_response = message.getMessageInfo() request_info = helpers.analyzeRequest(request_response) request_method = request_info.getMethod() if not messageIsRequest or request_method not in [ 'POST', 'PUT', 'DELETE', 'PATCH' ]: return # Do nothing http_service = request_response.getHttpService() request = request_response.getRequest() headers = request_info.getHeaders() parameters = request_info.getParameters() new_headers = headers if remove_csrf_headers: new_headers = filter_headers(headers) # Remove CSRF headers if change_ct_to_plain and request_info.getContentType() not in [ IRequestInfo.CONTENT_TYPE_URL_ENCODED, IRequestInfo.CONTENT_TYPE_MULTIPART ]: for i in range(len(new_headers)): if new_headers[i].lower().startswith( 'content-type'): # Change CT to text/plain new_headers[i] = 'Content-Type: text/plain' if remove_csrf_params: for parameter in parameters: # Remove CSRF parameters from request's body or URL for csrf_param in csrf_params_names: if parameter.getType() != IParameter.PARAM_COOKIE and \ csrf_param.lower() in parameter.getName().lower(): if request_info.getContentType( ) == IRequestInfo.CONTENT_TYPE_MULTIPART: start = parameter.getNameStart() end = parameter.getNameEnd() request = request[:start] + helpers.stringToBytes( "REPLACEMENT") + request[end:] elif parameter.getType() == IParameter.PARAM_JSON: start = parameter.getNameStart() - 1 end = parameter.getValueEnd() + 1 request = request[:start] + request[end:] offset = helpers.analyzeRequest( http_service, request).getBodyOffset() body = request[offset:] body = re.sub(",\s*,", ",", body) body = re.sub("{\s*,", "{", body) body = re.sub(",\s*}", "}", body) request = helpers.buildHttpMessage(headers, body) elif parameter.getType() in [ IParameter.PARAM_URL, IParameter.PARAM_BODY ]: request = helpers.removeParameter( request, parameter) offset = helpers.analyzeRequest(http_service, request).getBodyOffset() body = request[offset:] if change_ct_to_json and request_info.getContentType( ) == IRequestInfo.CONTENT_TYPE_URL_ENCODED: for i in range(len(new_headers)): if new_headers[i].lower().startswith( 'content-type'): # Change to JSON from URL-encoded new_headers[i] = 'Content-Type: application/json' body = safe_bytes_to_string(body) d = dict((k, v if len(v) > 1 else v[0]) for k, v in parse_qs(body).iteritems()) body = dumps(d) if change_method_to_post or (change_to_get and not change_ct_to_json and \ request_info.getContentType() == IRequestInfo.CONTENT_TYPE_URL_ENCODED): for i in range(len(new_headers)): if new_headers[i].startswith("PUT") or new_headers[i].startswith("DELETE") \ or new_headers[i].startswith("PATCH"): new_headers[i] = new_headers[i].replace( request_method, 'POST', 1) break new_request = helpers.buildHttpMessage( new_headers, body) # Create new request with valid Content-Length if change_to_get and not change_ct_to_json and request_info.getContentType( ) == IRequestInfo.CONTENT_TYPE_URL_ENCODED: new_request = helpers.toggleRequestMethod( new_request) # Change any URL-encoded request to GET message.setInterceptAction( IInterceptedProxyMessage.ACTION_FOLLOW_RULES_AND_REHOOK) message.getMessageInfo().setRequest(new_request) message.getMessageInfo().setHighlight('red')
class BurpExtender(IBurpExtender, IExtensionStateListener, IHttpListener, ITab, FocusListener, ActionListener, MouseAdapter): _version = "0.2" _name = "PyRules" _varsStorage = _name + "_vars" _scriptStorage = _name + "_script" _enabled = 0 _vars = {} def registerExtenderCallbacks(self, callbacks): print "Load:" + self._name + " " + self._version self.callbacks = callbacks self.helpers = callbacks.helpers #Create Tab layout self.jVarsPane = JTextPane() self.jVarsPane.setFont(Font('Monospaced', Font.PLAIN, 11)) self.jVarsPane.addFocusListener(self) self.jMenuPanel = JPanel() self.jLeftUpPanel = JPanel() self.jEnable = JCheckBox() self.jEnable.setFont(Font('Monospaced', Font.BOLD, 11)) self.jEnable.setForeground(Color(0, 0, 204)) self.jEnable.setText(self._name) self.jEnable.addActionListener(self) self.jDocs = JLabel() self.jDocs.setFont(Font('Monospaced', Font.PLAIN, 11)) self.jDocs.setForeground(Color(51, 102, 255)) self.jDocs.setText(Strings.docs_titel) self.jDocs.setToolTipText(Strings.docs_tooltip) self.jDocs.addMouseListener(self) self.jConsoleText = JTextArea() self.jConsoleText.setFont(Font('Monospaced', Font.PLAIN, 10)) self.jConsoleText.setBackground(Color(244, 246, 247)) self.jConsoleText.setEditable(0) self.jConsoleText.setWrapStyleWord(1) self.jConsoleText.setRows(10) self.jScrollConsolePane = JScrollPane() self.jScrollConsolePane.setViewportView(self.jConsoleText) #set initial text self.jConsoleText.setText(Strings.console_disable) self.jMenuPanelLayout = GroupLayout(self.jMenuPanel) self.jMenuPanel.setLayout(self.jMenuPanelLayout) self.jMenuPanelLayout.setHorizontalGroup( self.jMenuPanelLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGroup( self.jMenuPanelLayout.createSequentialGroup().addComponent( self.jEnable).addPreferredGap( LayoutStyle.ComponentPlacement.RELATED, 205, 32767).addComponent(self.jDocs))) self.jMenuPanelLayout.setVerticalGroup( self.jMenuPanelLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGroup( self.jMenuPanelLayout.createSequentialGroup().addGroup( self.jMenuPanelLayout.createParallelGroup( GroupLayout.Alignment.BASELINE).addComponent( self.jEnable).addComponent(self.jDocs)).addGap( 0, 7, 32767))) self.jConsolePane = JPanel() self.jConsoleLayout = GroupLayout(self.jConsolePane) self.jConsolePane.setLayout(self.jConsoleLayout) self.jConsoleLayout.setHorizontalGroup( self.jConsoleLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addComponent( self.jScrollConsolePane)) self.jConsoleLayout.setVerticalGroup( self.jConsoleLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGroup( GroupLayout.Alignment.TRAILING, self.jConsoleLayout.createSequentialGroup().addComponent( self.jScrollConsolePane, GroupLayout.DEFAULT_SIZE, 154, 32767).addContainerGap())) self.jLeftUpPanelLayout = GroupLayout(self.jLeftUpPanel) self.jLeftUpPanel.setLayout(self.jLeftUpPanelLayout) self.jLeftUpPanelLayout.setHorizontalGroup( self.jLeftUpPanelLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addComponent( self.jConsolePane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, 32767).addComponent(self.jMenuPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) self.jLeftUpPanelLayout.setVerticalGroup( self.jLeftUpPanelLayout. createParallelGroup(GroupLayout.Alignment.LEADING).addGroup( GroupLayout.Alignment.TRAILING, self.jLeftUpPanelLayout.createSequentialGroup().addComponent( self.jMenuPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addPreferredGap( LayoutStyle.ComponentPlacement.RELATED).addComponent( self.jConsolePane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, 32767))) self.jScrollpaneLeftDown = JScrollPane() self.jScrollpaneLeftDown.setViewportView(self.jVarsPane) self.jSplitPaneLeft = JSplitPane(JSplitPane.VERTICAL_SPLIT, self.jLeftUpPanel, self.jScrollpaneLeftDown) self.jSplitPaneLeft.setDividerLocation(300) self.jScriptPane = JTextPane() self.jScriptPane.setFont(Font('Monospaced', Font.PLAIN, 11)) self.jScriptPane.addMouseListener(self) self.JScrollPaneRight = JScrollPane() self.JScrollPaneRight.setViewportView(self.jScriptPane) self.jSplitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, self.jSplitPaneLeft, self.JScrollPaneRight) self.jSplitPane.setDividerLocation(400) #Load saved saved settings ##Load vars vars = callbacks.loadExtensionSetting(self._varsStorage) if vars: vars = base64.b64decode(vars) else: # try to load the example try: with open("examples/Simple-CSRF-vars.py") as fvars: vars = fvars.read() # load the default text except: vars = Strings.vars ## initiate the persistant variables locals_ = {} try: exec(vars, {}, locals_) except Exception as e: print e self._vars = locals_ ## update the vars screen self.jVarsPane.document.insertString(self.jVarsPane.document.length, vars, SimpleAttributeSet()) ##Load script script = callbacks.loadExtensionSetting(self._scriptStorage) if script: script = base64.b64decode(script) else: # try to load the example try: with open("examples/Simple-CSRF-script.py") as fscript: script = fscript.read() # load the default text except: script = Strings.script ## compile the rules self._script = script self._code = '' try: self._code = compile(script, '<string>', 'exec') except Exception as e: print( '{}\nReload extension after you correct the error.'.format(e)) ## update the rules screen self.jScriptPane.document.insertString( self.jScriptPane.document.length, script, SimpleAttributeSet()) #Register Extension callbacks.customizeUiComponent(self.getUiComponent()) callbacks.addSuiteTab(self) callbacks.registerExtensionStateListener(self) callbacks.registerHttpListener(self) self.jScriptPane.requestFocus() def getUiComponent(self): return self.jSplitPane def getTabCaption(self): return self._name def actionPerformed(self, event): #Check box was clicked if self.jEnable == event.getSource(): if self._enabled == 1: self._enabled = 0 # console content shows help self.jConsoleText.setText(Strings.console_disable) else: self._enabled = 1 # console content displays the current persistent variable state self.jConsoleText.setText(Strings.console_state) self.jConsoleText.append(pformat(self._vars)) self.jConsoleText.append(Strings.extra_line) self.jConsoleText.append(Strings.console_log) return def mouseClicked(self, event): if event.source == self.jDocs: uri = URI.create("https://github.com/DanNegrea/PyRules") if uri and Desktop.isDesktopSupported() and Desktop.getDesktop( ).isSupported(Desktop.Action.BROWSE): Desktop.getDesktop().browse(uri) return def focusGained(self, event): if self.jConsolePane == event.getSource(): pass #print "Status pane gained focus" #debug return def focusLost(self, event): #Reinitialize the persistent values if self.jVarsPane == event.getSource(): # get the text from the pane end = self.jVarsPane.document.length vars = self.jVarsPane.document.getText(0, end) # compute the new values locals_ = {} exec(vars, {}, locals_) self._vars = locals_ # display the new result in console self.jConsoleText.append(Strings.console_state) self.jConsoleText.append(pformat(self._vars)) self.jConsoleText.append(Strings.extra_line) self.jConsoleText.append(Strings.console_log) # scroll to bottom verticalScrollBar = self.jScrollConsolePane.getVerticalScrollBar() verticalScrollBar.setValue(verticalScrollBar.getMaximum()) return def extensionUnloaded(self): try: #Save the latestest vars and script text ## save vars end = self.jVarsPane.document.length vars = self.jVarsPane.document.getText(0, end) vars = base64.b64encode(vars) self.callbacks.saveExtensionSetting(self._varsStorage, vars) ## save script/rules end = self.jScriptPane.document.length script = self.jScriptPane.document.getText(0, end) script = base64.b64encode(script) self.callbacks.saveExtensionSetting(self._scriptStorage, script) except Exception: traceback.print_exc(file=self.callbacks.getStderr()) print "Unloaded" #debug return def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): if self._enabled == 0: return try: locals_ = { 'extender': self, 'callbacks': self.callbacks, 'helpers': self.helpers, 'toolFlag': toolFlag, 'messageIsRequest': messageIsRequest, 'messageInfo': messageInfo, 'log': self.log } # add the _vars as gloval variables locals_ = dict(locals_, **self._vars) # execute the script/rules try: exec(self.getCode, {}, locals_) # catch exit() call inside the rule except SystemExit: pass # update the persistant variables by searching the local variables with the same name for key in self._vars: # assumption self._vars dictionary is smaller than locals_ if key in locals_: self._vars[key] = locals_[key] except Exception: traceback.print_exc(file=self.callbacks.getStderr()) return #Returns the compiled script @property def getCode(self): end = self.jScriptPane.document.length script = self.jScriptPane.document.getText(0, end) # if the script hasn't changed return the already compile text if script == self._script: return self._code self._script = script # compile, store and return the result self._code = compile(script, '<string>', 'exec') return self._code #Log the information into the console screen def log(self, obj): # if string just append. else use pformat from pprint if isinstance(obj, str): self.jConsoleText.append(obj + "\n") else: self.jConsoleText.append(pformat(obj) + "\n") # scroll to bottom verticalScrollBar = self.jScrollConsolePane.getVerticalScrollBar() verticalScrollBar.setValue(verticalScrollBar.getMaximum()) return
class tag(ITab): def __init__(self, callbacks, name): self._callbacks = callbacks self.name = name def getTabCaption(self): return self.name def getUiComponent(self): return self.tabs def setFontItalic(self, label): label.setFont( Font(label.getFont().getName(), Font.ITALIC, label.getFont().getSize())) def setFontBold(self, label): label.setFont(Font('Serif', Font.BOLD, label.getFont().getSize())) # 配置界面添加 def tagLoad(self): # 创建窗口 开始 self.tabs = JTabbedPane() self.settings = JPanel(GridBagLayout()) self.forward_requests_settings = JPanel(GridBagLayout()) self.white_list_domain_settings = JPanel(GridBagLayout()) c = GridBagConstraints() # 界面选项卡1-标签加载 self.tag_1(c) self.tag_2(c) # 界面选项卡2-标签加载 self.tag_3(c) self.tag_4(c) # 界面选项卡3-标签加载 self.tag_5(c) # 添加选项卡 self.tabs.addTab(u'基本设置', self.settings) self.tabs.addTab(u'http请求转发设置', self.forward_requests_settings) self.tabs.addTab(u'白名单域名设置', self.white_list_domain_settings) self._callbacks.customizeUiComponent(self.tabs) self._callbacks.addSuiteTab(self) # 选项卡1-标签1-ui def tag_1(self, c): # 创建 检查框 self.is_start_box = JCheckBox(u'是否启动插件', ForwardRequestsConfig.IS_START) self.setFontBold(self.is_start_box) self.is_start_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 1 self.settings.add(self.is_start_box, c) # 在窗口添加一句话 is_start_box_lbl = JLabel(u'打勾-启动, 不打勾-关闭') self.setFontItalic(is_start_box_lbl) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 2 self.settings.add(is_start_box_lbl, c) # 选项卡1-标签1-值 def isStartBox(self): return self.is_start_box.isSelected() # 选项卡1-标签2-ui def tag_2(self, c): # 创建 检查框 self.url_repeated_box = JCheckBox( u'是否启动url重复验证', ForwardRequestsConfig.URL_REPEATED_VERIFY) self.setFontBold(self.url_repeated_box) self.url_repeated_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 3 self.settings.add(self.url_repeated_box, c) # 在窗口添加一句话 url_repeated_box_lbl = JLabel(u'打勾-开启验证, 不打勾-关闭验证') self.setFontItalic(url_repeated_box_lbl) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 4 self.settings.add(url_repeated_box_lbl, c) # 选项卡1-标签2-值 def urlRepeatedBox(self): return self.url_repeated_box.isSelected() # 选项卡2-标签1-ui def tag_3(self, c): # 创建 检查框 self.is_proxy_forward_requests_box = JCheckBox( u'是否启动Proxy模块请求转发(推荐打勾)', ForwardRequestsConfig.IS_START_PROXY_FORWARD_REQUESTS) self.setFontBold(self.is_proxy_forward_requests_box) self.is_proxy_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 1 self.forward_requests_settings.add(self.is_proxy_forward_requests_box, c) # 在窗口添加一句话 is_proxy_forward_requests_box_lbl = JLabel(u'打勾-启动, 不打勾-关闭') self.setFontItalic(is_proxy_forward_requests_box_lbl) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 2 self.forward_requests_settings.add(is_proxy_forward_requests_box_lbl, c) # 选项卡2-标签2-ui def tag_4(self, c): # 创建 检查框 self.is_repeater_forward_requests_box = JCheckBox( u'是否启动Repeater模块请求转发', ForwardRequestsConfig.IS_START_REPEATER_FORWARD_REQUESTS) self.setFontBold(self.is_repeater_forward_requests_box) self.is_repeater_forward_requests_box.setForeground(Color(0, 0, 153)) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 3 self.forward_requests_settings.add( self.is_repeater_forward_requests_box, c) # 在窗口添加一句话 is_repeater_forward_requests_box_lbl = JLabel(u'打勾-启动, 不打勾-关闭') self.setFontItalic(is_repeater_forward_requests_box_lbl) c.insets = Insets(5, 5, 5, 5) c.gridx = 0 c.gridy = 4 self.forward_requests_settings.add( is_repeater_forward_requests_box_lbl, c) # 获取允许转发的burp模块列表 def getWhiteListModule(self): white_list_module = [] if self.is_proxy_forward_requests_box.isSelected(): white_list_module.append(4) if self.is_repeater_forward_requests_box.isSelected(): white_list_module.append(64) return white_list_module # 选项卡3-标签1-ui def tag_5(self, c): # 输入框-标题 lblParams = JLabel(u'请填写域名:') self.setFontBold(lblParams) lblParams.setForeground(Color(0, 0, 153)) c.gridx = 0 c.gridy = 0 c.insets = Insets(5, 5, 5, 5) c.fill = GridBagConstraints.NONE c.anchor = GridBagConstraints.FIRST_LINE_END self.white_list_domain_settings.add(lblParams, c) # 输入框 self.white_list_text_field = JTextField() c.fill = GridBagConstraints.BOTH c.gridx = 1 c.gridy = 0 self.white_list_domain_settings.add(self.white_list_text_field, c) lblParamsNote = JLabel(u"白名单域名列表") self.setFontItalic(lblParamsNote) c.fill = GridBagConstraints.NONE c.gridx = 0 c.gridy = 1 self.white_list_domain_settings.add(lblParamsNote, c) # 添加 文本框 self.white_list_text_area = JTextArea() self.white_list_text_area.setColumns(20) self.white_list_text_area.setRows(10) self.white_list_text_area.setEditable(False) c.fill = GridBagConstraints.BOTH self.white_list_mouse_listener = TextAreaMouseListener( self.white_list_text_area) self.white_list_text_area.addMouseListener( self.white_list_mouse_listener) # 向文本框添加数据 for name in white_list_names: self.white_list_text_area.append(name + '\n' + os.linesep) c.gridx = 1 c.gridy = 1 sp = JScrollPane(self.white_list_text_area) self.white_list_domain_settings.add(sp, c) # 添加 删除 重置 buttonsPanel = JPanel(GridBagLayout()) _c = GridBagConstraints() _c.insets = Insets(3, 3, 3, 3) _c.gridx = 0 _c.fill = GridBagConstraints.BOTH _c.weightx = 1 _c.gridwidth = 1 handlers = ButtonHandlers(self.white_list_text_field, self.white_list_text_area, self.white_list_mouse_listener, white_list_names) # 添加按钮 self.white_list_add_button = JButton( u'添加', actionPerformed=handlers.handler_add) _c.gridy = 1 buttonsPanel.add(self.white_list_add_button, _c) # 删除按钮 self.white_list_rm_button = JButton( u'删除', actionPerformed=handlers.handler_rm) _c.gridy = 2 buttonsPanel.add(self.white_list_rm_button, _c) # 重置按钮 self.white_list_restore_button = JButton( u'重置', actionPerformed=handlers.handler_restore) _c.gridy = 3 buttonsPanel.add(self.white_list_restore_button, _c) c.gridx = 2 c.gridy = 1 c.fill = GridBagConstraints.NONE self.white_list_domain_settings.add(buttonsPanel, c) # 获取白名单域名列表 def getWhiteList(self): return self.text_area_to_list(self.white_list_text_area) # 获取指定text数据 def text_area_to_list(self, text_area): l = [] text_list = text_area.getText().strip().split('\n') for data in text_list: if data == '': continue data = data.replace("\n", '') data = data.replace("\r", '') data = data.strip(' ') l.append(data) return l