├── .gitignore ├── gui ├── __init__.py ├── menu.py ├── interception_filters.py ├── match_replace.py ├── tabs.py ├── save_restore.py ├── configuration_tab.py ├── table.py ├── enforcement_detector.py └── export.py ├── helpers ├── __init__.py ├── filters.py ├── initiator.py └── http.py ├── authorization ├── __init__.py └── authorization.py ├── Autorize.png ├── interceptionFilters.png ├── BappManifest.bmf ├── Autorize.py ├── BappDescription.html └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.class -------------------------------------------------------------------------------- /gui/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /helpers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /authorization/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Autorize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PortSwigger/autorize/master/Autorize.png -------------------------------------------------------------------------------- /interceptionFilters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PortSwigger/autorize/master/interceptionFilters.png -------------------------------------------------------------------------------- /BappManifest.bmf: -------------------------------------------------------------------------------- 1 | Uuid: f9bbac8c4acf4aefa4d7dc92a991af2f 2 | ExtensionType: 2 3 | Name: Autorize 4 | RepoName: autorize 5 | ScreenVersion: 1.8.2 6 | SerialVersion: 27 7 | MinPlatformVersion: 0 8 | ProOnly: False 9 | Author: Barak Tawily, AppSec Labs 10 | ShortDescription: Automatically detects authorization enforcement. 11 | EntryPoint: Autorize.py 12 | BuildCommand: 13 | SupportedProducts: Pro, Community 14 | -------------------------------------------------------------------------------- /Autorize.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from burp import IBurpExtender, IHttpListener, IProxyListener 5 | from authorization.authorization import handle_message 6 | from helpers.initiator import Initiator 7 | from helpers.filters import handle_proxy_message 8 | 9 | class BurpExtender(IBurpExtender, IHttpListener, IProxyListener): 10 | 11 | def registerExtenderCallbacks(self, callbacks): 12 | self._callbacks = callbacks 13 | self._helpers = callbacks.getHelpers() 14 | 15 | callbacks.setExtensionName("Autorize") 16 | 17 | initiator = Initiator(self) 18 | 19 | initiator.init_constants() 20 | 21 | initiator.draw_all() 22 | 23 | initiator.implement_all() 24 | 25 | initiator.init_ui() 26 | 27 | initiator.print_welcome_message() 28 | 29 | return 30 | 31 | # 32 | # implement IHttpListener 33 | # 34 | def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): 35 | handle_message(self, toolFlag, messageIsRequest, messageInfo) 36 | 37 | # 38 | # implement IProxyListener 39 | # 40 | def processProxyMessage(self, messageIsRequest, message): 41 | handle_proxy_message(self,message) 42 | 43 | -------------------------------------------------------------------------------- /BappDescription.html: -------------------------------------------------------------------------------- 1 |

Autorize is an extension aimed at helping the penetration tester to detect 2 | authorization vulnerabilities, one of the more time-consuming tasks in a web 3 | application penetration test.

4 | 5 |

It is sufficient to give to the extension the cookies of a low privileged 6 | user and navigate the website with a high privileged user. The extension 7 | automatically repeats every request with the session of the low privileged 8 | user and detects authorization vulnerabilities.

9 | 10 |

It is also possible to repeat every request without any 11 | cookies in order to detect authentication vulnerabilities in 12 | addition to authorization ones.

13 | 14 |

The plugin works without any configuration, but is also highly 15 | customizable, allowing configuration of the granularity of the authorization 16 | enforcement conditions and also which requests the plugin must test and 17 | which not. It is possible to save the state of the plugin and to export a 18 | report of the authorization tests in HTML or in CSV.

19 | 20 |

The reported enforcement statuses are the following:

21 |
    22 |
  1. Bypassed! - Red color
  2. 23 |
  3. Enforced! - Green color
  4. 24 |
  5. Is enforced??? (please configure enforcement detector) - Yellow color
  6. 25 |
26 | -------------------------------------------------------------------------------- /gui/menu.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from burp import IContextMenuFactory 5 | 6 | from java.util import LinkedList 7 | from javax.swing import JMenuItem 8 | from java.awt.event import ActionListener 9 | 10 | from authorization.authorization import send_request_to_autorize 11 | from helpers.http import get_cookie_header_from_message, get_authorization_header_from_message 12 | 13 | from thread import start_new_thread 14 | 15 | class MenuImpl(IContextMenuFactory): 16 | def __init__(self, extender): 17 | self._extender = extender 18 | 19 | def createMenuItems(self, invocation): 20 | responses = invocation.getSelectedMessages() 21 | if responses > 0: 22 | ret = LinkedList() 23 | requestMenuItem = JMenuItem("Send request to Autorize") 24 | cookieMenuItem = JMenuItem("Send Cookie header to Autorize") 25 | authMenuItem = JMenuItem("Send Authorization header to Autorize") 26 | 27 | for response in responses: 28 | requestMenuItem.addActionListener(HandleMenuItems(self._extender,response, "request")) 29 | cookieMenuItem.addActionListener(HandleMenuItems(self._extender, response, "cookie")) 30 | authMenuItem.addActionListener(HandleMenuItems(self._extender, response, "authorization")) 31 | ret.add(requestMenuItem) 32 | ret.add(cookieMenuItem) 33 | ret.add(authMenuItem) 34 | return ret 35 | return None 36 | 37 | class HandleMenuItems(ActionListener): 38 | def __init__(self, extender, messageInfo, menuName): 39 | self._extender = extender 40 | self._menuName = menuName 41 | self._messageInfo = messageInfo 42 | 43 | def actionPerformed(self, e): 44 | if self._menuName == "request": 45 | start_new_thread(send_request_to_autorize, (self._extender, self._messageInfo,)) 46 | 47 | if self._menuName == "cookie": 48 | self._extender.replaceString.setText(get_cookie_header_from_message(self._extender, self._messageInfo)) 49 | 50 | if self._menuName == "authorization": 51 | self._extender.replaceString.setText(get_authorization_header_from_message(self._extender, self._messageInfo)) 52 | -------------------------------------------------------------------------------- /helpers/filters.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from java.awt import GridLayout 5 | from burp import IInterceptedProxyMessage 6 | 7 | def addFilterHelper(typeObj, model, textObj): 8 | typeName = typeObj.getSelectedItem().split(":")[0] 9 | model.addElement(typeName + ": " + textObj.getText().strip()) 10 | textObj.setText("") 11 | 12 | def delFilterHelper(listObj): 13 | index = listObj.getSelectedIndex() 14 | if not index == -1: 15 | listObj.getModel().remove(index) 16 | 17 | def modFilterHelper(listObj, typeObj, textObj): 18 | index = listObj.getSelectedIndex() 19 | if not index == -1: 20 | valt = listObj.getSelectedValue() 21 | val = valt.split(":", 1)[1].strip() 22 | modifiedFilter = valt.split(":", 1)[0].strip() + ":" 23 | typeObj.getModel().setSelectedItem(modifiedFilter) 24 | if ("Scope items" not in valt) and ("Content-Len" not in valt): 25 | textObj.setText(val) 26 | listObj.getModel().remove(index) 27 | 28 | def expand(extender, comp): 29 | comp.setSelectedIndex(0) 30 | comp.setTitleAt(2, "Collapse") 31 | extender.requests_panel.remove(extender.modified_requests_tabs) 32 | extender.requests_panel.remove(extender.original_requests_tabs) 33 | extender.requests_panel.remove(extender.unauthenticated_requests_tabs) 34 | extender.requests_panel.add(comp) 35 | extender.requests_panel.setLayout(GridLayout(1,0)) 36 | extender.requests_panel.revalidate() 37 | extender.expanded_requests = 1 38 | 39 | def collapse(extender, comp): 40 | comp.setSelectedIndex(0) 41 | comp.setTitleAt(2, "Expand") 42 | extender.requests_panel.setLayout(GridLayout(3,0)) 43 | extender.requests_panel.add(extender.modified_requests_tabs) 44 | extender.requests_panel.add(extender.original_requests_tabs) 45 | extender.requests_panel.add(extender.unauthenticated_requests_tabs) 46 | extender.requests_panel.revalidate() 47 | extender.expanded_requests = 0 48 | 49 | def handle_proxy_message(self,message): 50 | currentPort = message.getListenerInterface().split(":")[1] 51 | for i in range(0, self.IFList.getModel().getSize()): 52 | interceptionFilter = self.IFList.getModel().getElementAt(i) 53 | interceptionFilterTitle = interceptionFilter.split(":")[0] 54 | if interceptionFilterTitle == "Drop proxy listener ports": 55 | portsList = interceptionFilter[27:].split(",") 56 | portsList = [int(i) for i in portsList] 57 | if int(currentPort) in portsList: 58 | message.setInterceptAction(IInterceptedProxyMessage.ACTION_DROP) -------------------------------------------------------------------------------- /helpers/initiator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from gui.enforcement_detector import EnforcementDetectors 5 | from gui.interception_filters import InterceptionFilters 6 | from gui.configuration_tab import ConfigurationTab 7 | from gui.match_replace import MatchReplace 8 | from gui.tabs import Tabs, ITabImpl 9 | from gui.table import TableFilter 10 | from gui.export import Export 11 | from gui.menu import MenuImpl 12 | 13 | from java.util import ArrayList 14 | from threading import Lock 15 | 16 | class Initiator(): 17 | def __init__(self, extender): 18 | self._extender = extender 19 | 20 | def init_constants(self): 21 | self.contributors = ["Federico Dotta", "mgeeky", "Marcin Woloszyn", "jpginc", "Eric Harris"] 22 | self._extender.version = 1.8 23 | self._extender._log = ArrayList() 24 | self._extender._lock = Lock() 25 | 26 | self._extender.BYPASSSED_STR = "Bypassed!" 27 | self._extender.IS_ENFORCED_STR = "Is enforced??? (please configure enforcement detector)" 28 | self._extender.ENFORCED_STR = "Enforced!" 29 | 30 | self._extender.intercept = 0 31 | self._extender.lastCookiesHeader = "" 32 | self._extender.lastAuthorizationHeader = "" 33 | 34 | self._extender.currentRequestNumber = 1 35 | self._extender.expanded_requests = 0 36 | 37 | def draw_all(self): 38 | interception_filters = InterceptionFilters(self._extender) 39 | interception_filters.draw() 40 | 41 | enforcement_detectors = EnforcementDetectors(self._extender) 42 | enforcement_detectors.draw() 43 | enforcement_detectors.draw_unauthenticated() 44 | 45 | export = Export(self._extender) 46 | export.draw() 47 | 48 | match_replace = MatchReplace(self._extender) 49 | match_replace.draw() 50 | 51 | table_filter = TableFilter(self._extender) 52 | table_filter.draw() 53 | 54 | cfg_tab = ConfigurationTab(self._extender) 55 | cfg_tab.draw() 56 | 57 | tabs = Tabs(self._extender) 58 | tabs.draw() 59 | 60 | def implement_all(self): 61 | itab = ITabImpl(self._extender) 62 | menu = MenuImpl(self._extender) 63 | 64 | self._extender._callbacks.registerContextMenuFactory(menu) 65 | self._extender._callbacks.addSuiteTab(itab) 66 | self._extender._callbacks.registerHttpListener(self._extender) 67 | self._extender._callbacks.registerProxyListener(self._extender) 68 | 69 | 70 | def init_ui(self): 71 | self._extender._callbacks.customizeUiComponent(self._extender._splitpane) 72 | self._extender._callbacks.customizeUiComponent(self._extender.logTable) 73 | self._extender._callbacks.customizeUiComponent(self._extender.scrollPane) 74 | self._extender._callbacks.customizeUiComponent(self._extender.tabs) 75 | self._extender._callbacks.customizeUiComponent(self._extender.filtersTabs) 76 | 77 | def print_welcome_message(self): 78 | print("""Thank you for installing Autorize v{} extension 79 | Created by Barak Tawily 80 | Contributors: {} 81 | 82 | Github:\nhttps://github.com/Quitten/Autorize""".format(self._extender.version, ", ".join(self.contributors))) 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Autorize 2 | Autorize is an automatic authorization enforcement detection extension for Burp Suite. It was written in Python by Barak Tawily, an application security expert. Autorize was designed to help security testers by performing automatic authorization tests. With the last release now Autorize also perform automatic authentication tests. 3 | 4 | ![alt tag](https://raw.githubusercontent.com/Quitten/Autorize/master/Autorize.png) 5 | 6 | # Installation 7 | 1. Download Burp Suite (obviously): http://portswigger.net/burp/download.html 8 | 2. Download Jython standalone JAR: http://www.jython.org/download.html 9 | 3. Open burp -> Extender -> Options -> Python Environment -> Select File -> Choose the Jython standalone JAR 10 | 4. Install Autorize from the BApp Store or follow these steps: 11 | 5. Download Autorize source code: `git clone git@github.com:Quitten/Autorize.git` 12 | 6. Open Burp -> Extender -> Extensions -> Add -> Choose Autorize.py file. 13 | 7. See the Autorize tab and enjoy automatic authorization detection :) 14 | 15 | 16 | # User Guide - How to use? 17 | 1. After installation, the Autorize tab will be added to Burp. 18 | 2. Open the configuration tab (Autorize -> Configuration). 19 | 3. Get your low-privileged user authorization token header (Cookie / Authorization) and copy it into the textbox containing the text "Insert injected header here". 20 | **Note**: Headers inserted here will be replaced if present or added if not. 21 | 4. Uncheck "Check unauthenticated" if the authentication test is not required (request without any cookies, to check for authentication enforcement in addition to authorization enforcement with the cookies of low-privileged user) 22 | 5. Check "Intercept requests from Repeater" to also intercept the requests that are sent through the Repeater. 23 | 6. Click on "Intercept is off" to start intercepting the traffic in order to allow Autorize to check for authorization enforcement. 24 | 7. Open a browser and configure the proxy settings so the traffic will be passed to Burp. 25 | 8. Browse to the application you want to test with a high privileged user. 26 | 9. The Autorize table will show you the request's URL and enforcement status. 27 | 10. It is possible to click on a specific URL and see the original/modified/unauthenticated request/response in order to investigate the differences. 28 | 29 | 30 | # Authorization Enforcement Status 31 | There are 3 enforcement statuses: 32 | 33 | 1. Bypassed! - Red color 34 | 35 | 2. Enforced! - Green color 36 | 37 | 3. Is enforced??? (please configure enforcement detector) - Yellow color 38 | 39 | The first 2 statuses are clear, so I won't elaborate on them. 40 | 41 | The 3rd status means that Autorize cannot determine if authorization is enforced or not, and so Autorize will ask you to configure a filter in the enforcement detector tabs. There are two different enforcement detector tabs, one for the detection of the enforcement of low-privileged requests and one for the detection of the enforcement of unauthenticated requests. 42 | 43 | The enforcement detector filters will allow Autorize to detect authentication and authorization enforcement in the response of the server by content length or string (literal string or regex) in the message body, headers or in the full request. 44 | 45 | For example, if there is a request enforcement status that is detected as "Authorization enforced??? (please configure enforcement detector)" it is possible to investigate the modified/original/unauthenticated response and see that the modified response body includes the string "You are not authorized to perform action", so you can add a filter with the fingerprint value "You are not authorized to perform action", so Autorize will look for this fingerprint and will automatically detect that authorization is enforced. It is possible to do the same by defining content-length filter or fingerprint in headers. 46 | 47 | # Interception Filters 48 | The interception filter allows you configure what domains you want to be intercepted by Autorize plugin, you can determine by blacklist/whitelist/regex or items in Burp's scope in order to avoid unnecessary domains to be intercepted by Autorize and work more organized. 49 | 50 | Example of interception filters (Note that there is default filter to avoid scripts and images): 51 | ![alt tag](https://raw.githubusercontent.com/Quitten/Autorize/master/interceptionFilters.png) 52 | 53 | 54 | # Authors 55 | - Barak Tawily, CTO @ [enso.security](https://enso.security/) by day, [Application Security Researcher](https://quitten.github.io/) by night, former Application Security Consultant @ [AppSec Labs](https://appsec-labs.com/) 56 | -------------------------------------------------------------------------------- /helpers/http.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import re 5 | from burp import IHttpRequestResponse 6 | 7 | def isStatusCodesReturned(self, messageInfo, statusCodes): 8 | firstHeader = self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders()[0] 9 | if type(statusCodes) == list: 10 | for statusCode in statusCodes: 11 | if statusCode in firstHeader: 12 | return True 13 | elif type(statusCodes) == str or type(statusCodes) == unicode: 14 | # single status code 15 | if statusCodes in firstHeader: 16 | return True 17 | return False 18 | 19 | def makeRequest(self, messageInfo, message): 20 | requestURL = self._helpers.analyzeRequest(messageInfo).getUrl() 21 | return self._callbacks.makeHttpRequest(self._helpers.buildHttpService(str(requestURL.getHost()), int(requestURL.getPort()), requestURL.getProtocol() == "https"), message) 22 | 23 | def makeMessage(self, messageInfo, removeOrNot, authorizeOrNot): 24 | requestInfo = self._helpers.analyzeRequest(messageInfo) 25 | headers = requestInfo.getHeaders() 26 | if removeOrNot: 27 | headers = list(headers) 28 | # flag for query 29 | queryFlag = self.replaceQueryParam.isSelected() 30 | if queryFlag: 31 | param = self.replaceString.getText().split("=") 32 | paramKey = param[0] 33 | paramValue = param[1] 34 | # ([\?&])test=.*?(?=[\s&]) 35 | pattern = r"([\?&]){}=.*?(?=[\s&])".format(paramKey) 36 | patchedHeader = re.sub(pattern, r"\1{}={}".format(paramKey, paramValue), headers[0], count=1, flags=re.DOTALL) 37 | headers[0] = patchedHeader 38 | else: 39 | removeHeaders = self.replaceString.getText() 40 | 41 | # Headers must be entered line by line i.e. each header in a new 42 | # line 43 | removeHeaders = [header for header in removeHeaders.split() if header.endswith(':')] 44 | 45 | for header in headers[:]: 46 | for removeHeader in removeHeaders: 47 | if header.lower().startswith(removeHeader.lower()): 48 | headers.remove(header) 49 | 50 | if authorizeOrNot: 51 | # simple string replace 52 | for k, v in self.badProgrammerMRModel.items(): 53 | if(v["type"] == "Headers (simple string):"): 54 | headers = map(lambda h: h.replace(v["match"], v["replace"]), headers) 55 | if(v["type"] == "Headers (regex):") : 56 | headers = map(lambda h: re.sub(v["regexMatch"], v["replace"], h), headers) 57 | 58 | if not queryFlag: 59 | # fix missing carriage return on *NIX systems 60 | replaceStringLines = self.replaceString.getText().split("\n") 61 | for h in replaceStringLines: 62 | if h == "": # Logic to fix extraneous newline at the end of requests when no temporary headers are added 63 | pass 64 | else: 65 | headers.append(h) 66 | 67 | msgBody = messageInfo.getRequest()[requestInfo.getBodyOffset():] 68 | 69 | # apply the match/replace settings to the body of the request 70 | if authorizeOrNot and msgBody is not None: 71 | msgBody = self._helpers.bytesToString(msgBody) 72 | # simple string replace 73 | for k, v in self.badProgrammerMRModel.items(): 74 | if(v["type"] == "Body (simple string):") : 75 | msgBody = msgBody.replace(v["match"], v["replace"]) 76 | if(v["type"] == "Body (regex):") : 77 | msgBody = re.sub(v["regexMatch"], v["replace"], msgBody) 78 | msgBody = self._helpers.stringToBytes(msgBody) 79 | return self._helpers.buildHttpMessage(headers, msgBody) 80 | 81 | def getResponseHeaders(self, requestResponse): 82 | analyzedResponse = self._helpers.analyzeResponse(requestResponse.getResponse()) 83 | return self._helpers.bytesToString(requestResponse.getResponse()[0:analyzedResponse.getBodyOffset()]) 84 | 85 | def getResponseBody(self, requestResponse): 86 | analyzedResponse = self._helpers.analyzeResponse(requestResponse.getResponse()) 87 | return self._helpers.bytesToString(requestResponse.getResponse()[analyzedResponse.getBodyOffset():]) 88 | 89 | def getResponseContentLength(self, response): 90 | return len(response) - self._helpers.analyzeResponse(response).getBodyOffset() 91 | 92 | def get_cookie_header_from_message(self, messageInfo): 93 | headers = list(self._helpers.analyzeRequest(messageInfo.getRequest()).getHeaders()) 94 | for header in headers: 95 | if header.strip().lower().startswith("cookie:"): 96 | return header 97 | return None 98 | 99 | def get_authorization_header_from_message(self, messageInfo): 100 | headers = list(self._helpers.analyzeRequest(messageInfo.getRequest()).getHeaders()) 101 | for header in headers: 102 | if header.strip().lower().startswith("authorization:"): 103 | return header 104 | return None 105 | 106 | class IHttpRequestResponseImplementation(IHttpRequestResponse): 107 | def __init__(self, service, req, res): 108 | self._httpService = service 109 | self._request = req 110 | self._response = res 111 | self._comment = None 112 | self._highlight = None 113 | 114 | def getComment(self): 115 | return self._comment 116 | 117 | def getHighlight(self): 118 | return self._highlight 119 | 120 | def getHttpService(self): 121 | return self._httpService 122 | 123 | def getRequest(self): 124 | return self._request 125 | 126 | def getResponse(self): 127 | return self._response 128 | 129 | def setComment(self,c): 130 | self._comment = c 131 | 132 | def setHighlight(self,h): 133 | self._highlight = h 134 | 135 | def setHttpService(self,service): 136 | self._httpService = service 137 | 138 | def setRequest(self,req): 139 | self._request = req 140 | 141 | def setResponse(self,res): 142 | self._response = res 143 | -------------------------------------------------------------------------------- /gui/interception_filters.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | sys.path.append("..") 6 | 7 | from javax.swing import JList 8 | from javax.swing import JLabel 9 | from javax.swing import JPanel 10 | from javax.swing import JButton 11 | from javax.swing import JComboBox 12 | from javax.swing import JTextArea 13 | from javax.swing import JScrollPane 14 | from javax.swing import GroupLayout 15 | from javax.swing import DefaultListModel 16 | from javax.swing.border import LineBorder 17 | from helpers.filters import addFilterHelper, delFilterHelper, modFilterHelper 18 | 19 | 20 | class InterceptionFilters(): 21 | def __init__(self, extender): 22 | self._extender = extender 23 | 24 | def draw(self): 25 | """ init interception filters tab 26 | """ 27 | self._extender.savedHeaders = [{"title": "Temporary headers", "headers": "Cookie: Insert=injected; cookie=or;\nHeader: here"}] 28 | # IFStrings has to contains : character 29 | IFStrings = ["Scope items only: (Content is not required)", 30 | "URL Contains (simple string): ", 31 | "URL Contains (regex): ", 32 | "URL Not Contains (simple string): ", 33 | "URL Not Contains (regex): ", 34 | "Request Body contains (simple string): ", 35 | "Request Body contains (regex): ", 36 | "Request Body NOT contains (simple string): ", 37 | "Request Body Not contains (regex): ", 38 | "Response Body contains (simple string): ", 39 | "Response Body contains (regex): ", 40 | "Response Body NOT contains (simple string): ", 41 | "Response Body Not contains (regex): ", 42 | "Header contains: ", 43 | "Header doesn't contain: ", 44 | "Only HTTP methods (newline separated): ", 45 | "Ignore HTTP methods (newline separated): ", 46 | "Ignore spider requests: (Content is not required)", 47 | "Ignore proxy requests: (Content is not required)", 48 | "Ignore target requests: (Content is not required)", 49 | "Ignore OPTIONS requests: (Content is not required)", 50 | "Drop proxy listener ports: (Separated by comma)" 51 | ] 52 | self._extender.IFType = JComboBox(IFStrings) 53 | self._extender.IFType.setBounds(80, 10, 430, 30) 54 | 55 | self._extender.IFModel = DefaultListModel() 56 | self._extender.IFList = JList(self._extender.IFModel) 57 | self._extender.IFList.setPrototypeCellValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") 58 | 59 | scrollIFList = JScrollPane(self._extender.IFList) 60 | scrollIFList.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 61 | scrollIFList.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED) 62 | scrollIFList.setBounds(80, 175, 300, 110) 63 | 64 | # Adding some default interception filters 65 | # self.IFModel.addElement("Scope items only: (Content is not required)") # commented for better first impression. 66 | self._extender.IFModel.addElement("URL Not Contains (regex): (\\.js|\\.css|\\.png|\\.jpg|\\.svg|\\.jpeg|\\.gif|\\.woff|\\.map|\\.bmp|\\.ico)(?![a-z]+)[?]*[\S]*$") 67 | self._extender.IFModel.addElement("Ignore spider requests: ") 68 | 69 | self._extender.IFText = JTextArea("", 5, 30) 70 | 71 | scrollIFText = JScrollPane(self._extender.IFText) 72 | scrollIFText.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 73 | scrollIFText.setBounds(80, 50, 300, 110) 74 | 75 | IFLType = JLabel("Type:") 76 | IFLType.setBounds(10, 10, 140, 30) 77 | 78 | IFLContent = JLabel("Content:") 79 | IFLContent.setBounds(10, 50, 140, 30) 80 | 81 | IFLabelList = JLabel("Filter List:") 82 | IFLabelList.setBounds(10, 165, 140, 30) 83 | 84 | self._extender.IFAdd = JButton("Add filter", actionPerformed=self.addIFFilter) 85 | self._extender.IFAdd.setBounds(390, 85, 120, 30) 86 | self._extender.IFDel = JButton("Remove filter", actionPerformed=self.delIFFilter) 87 | self._extender.IFDel.setBounds(390, 210, 120, 30) 88 | self._extender.IFMod = JButton("Modify filter", actionPerformed=self.modIFFilter) 89 | self._extender.IFMod.setBounds(390, 250, 120, 30) 90 | 91 | self._extender.filtersPnl = JPanel() 92 | layout = GroupLayout(self._extender.filtersPnl) 93 | self._extender.filtersPnl.setLayout(layout) 94 | layout.setAutoCreateGaps(True) 95 | layout.setAutoCreateContainerGaps(True) 96 | 97 | layout.setHorizontalGroup(layout.createSequentialGroup() 98 | .addGroup( 99 | layout.createParallelGroup() 100 | .addComponent( 101 | IFLType, 102 | GroupLayout.PREFERRED_SIZE, 103 | GroupLayout.PREFERRED_SIZE, 104 | GroupLayout.PREFERRED_SIZE, 105 | ) 106 | .addComponent( 107 | IFLContent, 108 | GroupLayout.PREFERRED_SIZE, 109 | GroupLayout.PREFERRED_SIZE, 110 | GroupLayout.PREFERRED_SIZE, 111 | ) 112 | .addComponent( 113 | IFLabelList, 114 | GroupLayout.PREFERRED_SIZE, 115 | GroupLayout.PREFERRED_SIZE, 116 | GroupLayout.PREFERRED_SIZE, 117 | ) 118 | ) 119 | .addGroup( 120 | layout.createParallelGroup() 121 | .addComponent( 122 | self._extender.IFType, 123 | GroupLayout.PREFERRED_SIZE, 124 | GroupLayout.PREFERRED_SIZE, 125 | GroupLayout.PREFERRED_SIZE, 126 | ) 127 | .addComponent( 128 | scrollIFText, 129 | GroupLayout.PREFERRED_SIZE, 130 | GroupLayout.PREFERRED_SIZE, 131 | GroupLayout.PREFERRED_SIZE, 132 | ) 133 | .addComponent( 134 | scrollIFList, 135 | GroupLayout.PREFERRED_SIZE, 136 | GroupLayout.PREFERRED_SIZE, 137 | GroupLayout.PREFERRED_SIZE, 138 | ) 139 | .addComponent( 140 | self._extender.IFAdd, 141 | GroupLayout.PREFERRED_SIZE, 142 | GroupLayout.PREFERRED_SIZE, 143 | GroupLayout.PREFERRED_SIZE, 144 | ) 145 | .addGroup( 146 | layout.createSequentialGroup() 147 | .addComponent( 148 | self._extender.IFDel, 149 | GroupLayout.PREFERRED_SIZE, 150 | GroupLayout.PREFERRED_SIZE, 151 | GroupLayout.PREFERRED_SIZE, 152 | ) 153 | .addComponent( 154 | self._extender.IFMod, 155 | GroupLayout.PREFERRED_SIZE, 156 | GroupLayout.PREFERRED_SIZE, 157 | GroupLayout.PREFERRED_SIZE, 158 | ) 159 | ) 160 | ) 161 | ) 162 | 163 | 164 | layout.setVerticalGroup(layout.createSequentialGroup() 165 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 166 | .addComponent( 167 | IFLType, 168 | GroupLayout.PREFERRED_SIZE, 169 | GroupLayout.PREFERRED_SIZE, 170 | GroupLayout.PREFERRED_SIZE, 171 | ) 172 | .addComponent( 173 | self._extender.IFType, 174 | GroupLayout.PREFERRED_SIZE, 175 | GroupLayout.PREFERRED_SIZE, 176 | GroupLayout.PREFERRED_SIZE, 177 | ) 178 | ) 179 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 180 | .addComponent( 181 | IFLContent, 182 | GroupLayout.PREFERRED_SIZE, 183 | GroupLayout.PREFERRED_SIZE, 184 | GroupLayout.PREFERRED_SIZE, 185 | ) 186 | .addComponent( 187 | scrollIFText, 188 | GroupLayout.PREFERRED_SIZE, 189 | GroupLayout.PREFERRED_SIZE, 190 | GroupLayout.PREFERRED_SIZE, 191 | ) 192 | ) 193 | .addComponent( 194 | self._extender.IFAdd, 195 | GroupLayout.PREFERRED_SIZE, 196 | GroupLayout.PREFERRED_SIZE, 197 | GroupLayout.PREFERRED_SIZE, 198 | ) 199 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 200 | .addComponent( 201 | IFLabelList, 202 | GroupLayout.PREFERRED_SIZE, 203 | GroupLayout.PREFERRED_SIZE, 204 | GroupLayout.PREFERRED_SIZE, 205 | ) 206 | .addComponent( 207 | scrollIFList, 208 | GroupLayout.PREFERRED_SIZE, 209 | GroupLayout.PREFERRED_SIZE, 210 | GroupLayout.PREFERRED_SIZE, 211 | ) 212 | ) 213 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 214 | .addComponent( 215 | self._extender.IFDel, 216 | GroupLayout.PREFERRED_SIZE, 217 | GroupLayout.PREFERRED_SIZE, 218 | GroupLayout.PREFERRED_SIZE, 219 | ) 220 | .addComponent( 221 | self._extender.IFMod, 222 | GroupLayout.PREFERRED_SIZE, 223 | GroupLayout.PREFERRED_SIZE, 224 | GroupLayout.PREFERRED_SIZE, 225 | ) 226 | ) 227 | ) 228 | 229 | 230 | 231 | 232 | 233 | def addIFFilter(self, event): 234 | addFilterHelper(self._extender.IFType, self._extender.IFModel, self._extender.IFText) 235 | 236 | def delIFFilter(self, event): 237 | delFilterHelper(self._extender.IFList) 238 | 239 | def modIFFilter(self, event): 240 | modFilterHelper(self._extender.IFList, self._extender.IFType, self._extender.IFText) 241 | -------------------------------------------------------------------------------- /gui/match_replace.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from java.awt import Color 5 | from javax.swing import JList 6 | from javax.swing import JPanel 7 | from javax.swing import JLabel 8 | from javax.swing import JButton 9 | from javax.swing import JComboBox 10 | from javax.swing import JTextArea 11 | from javax.swing import JScrollPane 12 | from javax.swing import GroupLayout 13 | from javax.swing import DefaultListModel 14 | from javax.swing.border import LineBorder 15 | 16 | import re 17 | 18 | class MatchReplace(): 19 | def __init__(self, extender): 20 | self._extender = extender 21 | 22 | def draw(self): 23 | """ init the match/replace tab 24 | """ 25 | #todo add an option to ignore large requests 26 | padding = 5 27 | labelWidth = 140 28 | labelHeight = 30 29 | editHeight = 110 30 | editWidth = 300 31 | buttonWidth = 120 32 | buttonHeight = 30 33 | column1X = 10 34 | column2X = column1X + labelWidth + padding 35 | column3X = column2X + editWidth + padding 36 | MRStrings = ["Headers (simple string):", 37 | "Headers (regex):", 38 | "Body (simple string):", 39 | "Body (regex):"] 40 | row1Y = 10 41 | row2Y = row1Y + labelHeight + padding 42 | row3Y = row2Y + editHeight + padding 43 | row4Y = row3Y + editHeight + padding 44 | row5Y = row4Y + labelHeight + padding 45 | row6Y = row5Y + buttonHeight + padding 46 | 47 | MRTypeLabel = JLabel("Type:") 48 | MRTypeLabel.setBounds(column1X, row1Y, labelWidth, labelHeight) 49 | 50 | MContent = JLabel("Match:") 51 | MContent.setBounds(column1X, row2Y, labelWidth, labelHeight) 52 | 53 | RContent = JLabel("Replace:") 54 | RContent.setBounds(column1X, row3Y, labelWidth, labelHeight) 55 | 56 | MRLabelList = JLabel("Filter List:") 57 | MRLabelList.setBounds(column1X, row5Y, labelWidth, labelHeight) 58 | 59 | self._extender.MRType = JComboBox(MRStrings) 60 | self._extender.MRType.setBounds(column2X, row1Y, editWidth, labelHeight) 61 | 62 | self._extender.MText = JTextArea("", 5, 30) 63 | scrollMText = JScrollPane(self._extender.MText) 64 | scrollMText.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 65 | scrollMText.setBounds(column2X, row2Y, editWidth, editHeight) 66 | 67 | self._extender.RText = JTextArea("", 5, 30) 68 | scrollRText = JScrollPane(self._extender.RText) 69 | scrollRText.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 70 | scrollRText.setBounds(column2X, row3Y, editWidth, editHeight) 71 | 72 | # i couldn't figure out how to have a model that contained anythin other than a string 73 | # so i'll use 2 models, one with the data and one for the JList 74 | self._extender.badProgrammerMRModel = {} 75 | self._extender.MRModel = DefaultListModel() 76 | self._extender.MRList = JList(self._extender.MRModel) 77 | 78 | scrollMRList = JScrollPane(self._extender.MRList) 79 | scrollMRList.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 80 | scrollMRList.setBounds(column2X, row5Y, editWidth, editHeight) 81 | scrollMRList.setBorder(LineBorder(Color.BLACK)) 82 | 83 | self._extender.MRAdd = JButton("Add filter", actionPerformed=self.addMRFilter) 84 | self._extender.MRAdd.setBounds(column2X, row4Y, buttonWidth, buttonHeight) 85 | self._extender.MRDel = JButton("Remove filter", actionPerformed=self.delMRFilter) 86 | self._extender.MRDel.setBounds(column3X, row5Y, buttonWidth, buttonHeight) 87 | self._extender.MRMod = JButton("Modify filter", actionPerformed=self.modMRFilter) 88 | self._extender.MRMod.setBounds(column3X, row5Y + buttonHeight + padding, buttonWidth, buttonHeight) 89 | 90 | self._extender.MRFeedback = JLabel("") 91 | self._extender.MRFeedback.setBounds(column1X, row6Y, column3X + buttonWidth, labelHeight) 92 | 93 | self._extender.MRPnl = JPanel() 94 | layout = GroupLayout(self._extender.MRPnl) 95 | self._extender.MRPnl.setLayout(layout) 96 | layout.setAutoCreateGaps(True) 97 | layout.setAutoCreateContainerGaps(True) 98 | 99 | layout.setHorizontalGroup(layout.createSequentialGroup() 100 | .addGroup(layout.createParallelGroup() 101 | .addComponent( 102 | MRTypeLabel, 103 | GroupLayout.PREFERRED_SIZE, 104 | GroupLayout.PREFERRED_SIZE, 105 | GroupLayout.PREFERRED_SIZE, 106 | ) 107 | .addComponent( 108 | MContent, 109 | GroupLayout.PREFERRED_SIZE, 110 | GroupLayout.PREFERRED_SIZE, 111 | GroupLayout.PREFERRED_SIZE, 112 | ) 113 | .addComponent( 114 | RContent, 115 | GroupLayout.PREFERRED_SIZE, 116 | GroupLayout.PREFERRED_SIZE, 117 | GroupLayout.PREFERRED_SIZE, 118 | ) 119 | .addComponent( 120 | MRLabelList, 121 | GroupLayout.PREFERRED_SIZE, 122 | GroupLayout.PREFERRED_SIZE, 123 | GroupLayout.PREFERRED_SIZE, 124 | ) 125 | ) 126 | .addGroup(layout.createParallelGroup() 127 | .addComponent( 128 | self._extender.MRType, 129 | GroupLayout.PREFERRED_SIZE, 130 | GroupLayout.PREFERRED_SIZE, 131 | GroupLayout.PREFERRED_SIZE, 132 | ) 133 | .addComponent( 134 | scrollMText, 135 | GroupLayout.PREFERRED_SIZE, 136 | GroupLayout.PREFERRED_SIZE, 137 | GroupLayout.PREFERRED_SIZE, 138 | ) 139 | .addComponent( 140 | scrollRText, 141 | GroupLayout.PREFERRED_SIZE, 142 | GroupLayout.PREFERRED_SIZE, 143 | GroupLayout.PREFERRED_SIZE, 144 | ) 145 | .addComponent( 146 | self._extender.MRAdd, 147 | GroupLayout.PREFERRED_SIZE, 148 | GroupLayout.PREFERRED_SIZE, 149 | GroupLayout.PREFERRED_SIZE, 150 | ) 151 | .addComponent( 152 | self._extender.MRFeedback, 153 | GroupLayout.PREFERRED_SIZE, 154 | GroupLayout.PREFERRED_SIZE, 155 | GroupLayout.PREFERRED_SIZE, 156 | ) 157 | .addComponent( 158 | scrollMRList, 159 | GroupLayout.PREFERRED_SIZE, 160 | GroupLayout.PREFERRED_SIZE, 161 | GroupLayout.PREFERRED_SIZE, 162 | ) 163 | .addComponent( 164 | self._extender.MRMod, 165 | GroupLayout.PREFERRED_SIZE, 166 | GroupLayout.PREFERRED_SIZE, 167 | GroupLayout.PREFERRED_SIZE, 168 | ) 169 | .addComponent( 170 | self._extender.MRDel, 171 | GroupLayout.PREFERRED_SIZE, 172 | GroupLayout.PREFERRED_SIZE, 173 | GroupLayout.PREFERRED_SIZE, 174 | ) 175 | ) 176 | ) 177 | 178 | layout.setVerticalGroup(layout.createSequentialGroup() 179 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 180 | .addComponent( 181 | MRTypeLabel, 182 | GroupLayout.PREFERRED_SIZE, 183 | GroupLayout.PREFERRED_SIZE, 184 | GroupLayout.PREFERRED_SIZE, 185 | ) 186 | .addComponent( 187 | self._extender.MRType, 188 | GroupLayout.PREFERRED_SIZE, 189 | GroupLayout.PREFERRED_SIZE, 190 | GroupLayout.PREFERRED_SIZE, 191 | ) 192 | ) 193 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 194 | .addComponent( 195 | MContent, 196 | GroupLayout.PREFERRED_SIZE, 197 | GroupLayout.PREFERRED_SIZE, 198 | GroupLayout.PREFERRED_SIZE, 199 | ) 200 | .addComponent( 201 | scrollMText, 202 | GroupLayout.PREFERRED_SIZE, 203 | GroupLayout.PREFERRED_SIZE, 204 | GroupLayout.PREFERRED_SIZE, 205 | ) 206 | ) 207 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 208 | .addComponent( 209 | RContent, 210 | GroupLayout.PREFERRED_SIZE, 211 | GroupLayout.PREFERRED_SIZE, 212 | GroupLayout.PREFERRED_SIZE, 213 | ) 214 | .addComponent( 215 | scrollRText, 216 | GroupLayout.PREFERRED_SIZE, 217 | GroupLayout.PREFERRED_SIZE, 218 | GroupLayout.PREFERRED_SIZE, 219 | ) 220 | ) 221 | .addGroup(layout.createSequentialGroup() 222 | .addComponent( 223 | self._extender.MRAdd, 224 | GroupLayout.PREFERRED_SIZE, 225 | GroupLayout.PREFERRED_SIZE, 226 | GroupLayout.PREFERRED_SIZE, 227 | ) 228 | .addComponent( 229 | self._extender.MRFeedback, 230 | GroupLayout.PREFERRED_SIZE, 231 | GroupLayout.PREFERRED_SIZE, 232 | GroupLayout.PREFERRED_SIZE, 233 | ) 234 | ) 235 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 236 | .addComponent( 237 | MRLabelList, 238 | GroupLayout.PREFERRED_SIZE, 239 | GroupLayout.PREFERRED_SIZE, 240 | GroupLayout.PREFERRED_SIZE, 241 | ) 242 | .addComponent( 243 | scrollMRList, 244 | GroupLayout.PREFERRED_SIZE, 245 | GroupLayout.PREFERRED_SIZE, 246 | GroupLayout.PREFERRED_SIZE, 247 | ) 248 | ) 249 | .addComponent( 250 | self._extender.MRMod, 251 | GroupLayout.PREFERRED_SIZE, 252 | GroupLayout.PREFERRED_SIZE, 253 | GroupLayout.PREFERRED_SIZE, 254 | ) 255 | .addComponent( 256 | self._extender.MRDel, 257 | GroupLayout.PREFERRED_SIZE, 258 | GroupLayout.PREFERRED_SIZE, 259 | GroupLayout.PREFERRED_SIZE, 260 | ) 261 | ) 262 | 263 | def addMRFilter(self, event): 264 | typeName = self._extender.MRType.getSelectedItem() 265 | match = self._extender.MText.getText() 266 | replace = self._extender.RText.getText() 267 | key = typeName + " " + match + "->" + replace 268 | if key in self._extender.badProgrammerMRModel: 269 | self._extender.MRFeedback.setText("Match/Replace already exists") 270 | return 271 | 272 | regexMatch = None 273 | try: 274 | if "(regex)" in typeName: 275 | regexMatch = re.compile(match) 276 | except re.error: 277 | self._extender.MRFeedback.setText("ERROR: Invalid regex") 278 | return 279 | self._extender.badProgrammerMRModel[key] = {"match": match, "regexMatch": regexMatch, "replace" : replace, "type": typeName} 280 | self._extender.MRModel.addElement(key) 281 | self._extender.MText.setText("") 282 | self._extender.RText.setText("") 283 | self._extender.MRFeedback.setText("") 284 | 285 | def delMRFilter(self, event): 286 | index = self._extender.MRList.getSelectedIndex() 287 | if not index == -1: 288 | key = self._extender.MRList.getSelectedValue() 289 | del self._extender.badProgrammerMRModel[key] 290 | self._extender.MRList.getModel().remove(index) 291 | 292 | def modMRFilter(self, event): 293 | index = self._extender.MRList.getSelectedIndex() 294 | if not index == -1: 295 | key = self._extender.MRList.getSelectedValue() 296 | self._extender.MRType.getModel().setSelectedItem(self._extender.badProgrammerMRModel[key]["type"]) 297 | self._extender.MText.setText(self._extender.badProgrammerMRModel[key]["match"]) 298 | self._extender.RText.setText(self._extender.badProgrammerMRModel[key]["replace"]) 299 | self.delMRFilter(event) 300 | -------------------------------------------------------------------------------- /gui/tabs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from java.awt.datatransfer import StringSelection 5 | from javax.swing.table import TableRowSorter 6 | from java.awt.event import AdjustmentListener 7 | from java.awt.event import ActionListener 8 | from java.awt.event import MouseAdapter 9 | from javax.swing import JSplitPane 10 | from javax.swing import JMenuItem 11 | from javax.swing import JScrollPane 12 | from javax.swing import JPopupMenu 13 | from javax.swing import JTabbedPane 14 | from javax.swing import JPanel 15 | from java.awt import GridLayout 16 | from java.awt import Toolkit 17 | from java.lang import Math 18 | from java.awt import Dimension 19 | 20 | from burp import ITab 21 | from burp import IMessageEditorController 22 | 23 | from authorization.authorization import handle_message, retestAllRequests 24 | 25 | from thread import start_new_thread 26 | 27 | from table import Table, TableRowFilter 28 | from helpers.filters import expand, collapse 29 | from javax.swing import KeyStroke 30 | from javax.swing import JTable 31 | from javax.swing import AbstractAction 32 | from java.awt.event import KeyEvent 33 | from java.awt.event import InputEvent 34 | from javax.swing import SwingUtilities 35 | 36 | class ITabImpl(ITab): 37 | def __init__(self, extender): 38 | self._extender = extender 39 | 40 | def getTabCaption(self): 41 | return "Autorize" 42 | 43 | def getUiComponent(self): 44 | return self._extender._splitpane 45 | 46 | class Tabs(): 47 | def __init__(self, extender): 48 | self._extender = extender 49 | 50 | def draw(self): 51 | """ init autorize tabs 52 | """ 53 | 54 | self._extender.logTable = Table(self._extender) 55 | 56 | tableWidth = self._extender.logTable.getPreferredSize().width 57 | self._extender.logTable.getColumn("ID").setPreferredWidth(Math.round(tableWidth / 50 * 2)) 58 | self._extender.logTable.getColumn("Method").setPreferredWidth(Math.round(tableWidth / 50 * 3)) 59 | self._extender.logTable.getColumn("URL").setPreferredWidth(Math.round(tableWidth / 50 * 25)) 60 | self._extender.logTable.getColumn("Orig. Len").setPreferredWidth(Math.round(tableWidth / 50 * 4)) 61 | self._extender.logTable.getColumn("Modif. Len").setPreferredWidth(Math.round(tableWidth / 50 * 4)) 62 | self._extender.logTable.getColumn("Unauth. Len").setPreferredWidth(Math.round(tableWidth / 50 * 4)) 63 | self._extender.logTable.getColumn("Authz. Status").setPreferredWidth(Math.round(tableWidth / 50 * 4)) 64 | self._extender.logTable.getColumn("Unauth. Status").setPreferredWidth(Math.round(tableWidth / 50 * 4)) 65 | 66 | self._extender.tableSorter = TableRowSorter(self._extender.tableModel) 67 | rowFilter = TableRowFilter(self._extender) 68 | self._extender.tableSorter.setRowFilter(rowFilter) 69 | self._extender.logTable.setRowSorter(self._extender.tableSorter) 70 | 71 | self._extender._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT) 72 | self._extender._splitpane.setResizeWeight(1) 73 | self._extender.scrollPane = JScrollPane(self._extender.logTable) 74 | self._extender.scrollPane.setMinimumSize(Dimension(1,1)) 75 | self._extender._splitpane.setLeftComponent(self._extender.scrollPane) 76 | self._extender.scrollPane.getVerticalScrollBar().addAdjustmentListener(AutoScrollListener(self._extender)) 77 | 78 | copyURLitem = JMenuItem("Copy URL") 79 | copyURLitem.addActionListener(CopySelectedURL(self._extender)) 80 | 81 | sendRequestMenu = JMenuItem("Send Original Request to Repeater") 82 | sendRequestMenu.addActionListener(SendRequestRepeater(self._extender, self._extender._callbacks, True)) 83 | 84 | sendRequestMenu2 = JMenuItem("Send Modified Request to Repeater") 85 | sendRequestMenu2.addActionListener(SendRequestRepeater(self._extender, self._extender._callbacks, False)) 86 | 87 | # Define the key combination for the shortcut 88 | try: 89 | # The keystroke combo is: Mac -> Command + r / Windows control + r 90 | # This is used to send to the repeater function in burp 91 | controlR = KeyStroke.getKeyStroke(KeyEvent.VK_R, Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx()) 92 | except: 93 | controlR = KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK) 94 | 95 | # The keystroke combo is: Mac -> Command + c / Windows control + c 96 | # This is used to copy the URL to the keyboard. 97 | controlC = KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.META_DOWN_MASK) 98 | 99 | # Get the input and action maps for the JTable 100 | inputMap = self._extender.logTable.getInputMap(JTable.WHEN_FOCUSED) 101 | actionMap = self._extender.logTable.getActionMap() 102 | 103 | # Bind the key combination to the action 104 | inputMap.put(controlR, "SendRequestToRepeaterAction") 105 | actionMap.put("SendRequestToRepeaterAction", SendRequestToRepeaterAction(self._extender, self._extender._callbacks)) 106 | 107 | # Bind the key combination to the action 108 | inputMap.put(controlC, "copyToClipBoard") 109 | actionMap.put("copyToClipBoard", 110 | CopySelectedURLToClipBoard(self._extender, self._extender._callbacks)) 111 | 112 | sendResponseMenu = JMenuItem("Send Responses to Comparer") 113 | sendResponseMenu.addActionListener(SendResponseComparer(self._extender, self._extender._callbacks)) 114 | 115 | retestSelecteditem = JMenuItem("Retest selected request") 116 | retestSelecteditem.addActionListener(RetestSelectedRequest(self._extender)) 117 | 118 | retestAllitem = JMenuItem("Retest all requests") 119 | retestAllitem.addActionListener(RetestAllRequests(self._extender)) 120 | 121 | deleteSelectedItem = JMenuItem("Delete") 122 | deleteSelectedItem.addActionListener(DeleteSelectedRequest(self._extender)) 123 | 124 | self._extender.menu = JPopupMenu("Popup") 125 | self._extender.menu.add(sendRequestMenu) 126 | self._extender.menu.add(sendRequestMenu2) 127 | self._extender.menu.add(sendResponseMenu) 128 | self._extender.menu.add(copyURLitem) 129 | self._extender.menu.add(retestSelecteditem) 130 | self._extender.menu.add(retestAllitem) 131 | self._extender.menu.add(deleteSelectedItem) # disabling this feature until bug will be fixed. 132 | message_editor = MessageEditor(self._extender) 133 | 134 | self._extender.tabs = JTabbedPane() 135 | self._extender._requestViewer = self._extender._callbacks.createMessageEditor(message_editor, False) 136 | self._extender._responseViewer = self._extender._callbacks.createMessageEditor(message_editor, False) 137 | 138 | self._extender._originalrequestViewer = self._extender._callbacks.createMessageEditor(message_editor, False) 139 | self._extender._originalresponseViewer = self._extender._callbacks.createMessageEditor(message_editor, False) 140 | 141 | self._extender._unauthorizedrequestViewer = self._extender._callbacks.createMessageEditor(message_editor, False) 142 | self._extender._unauthorizedresponseViewer = self._extender._callbacks.createMessageEditor(message_editor, False) 143 | 144 | self._extender.original_requests_tabs = JTabbedPane() 145 | self._extender.original_requests_tabs.addMouseListener(Mouseclick(self._extender)) 146 | self._extender.original_requests_tabs.addTab("Original Request", self._extender._originalrequestViewer.getComponent()) 147 | self._extender.original_requests_tabs.addTab("Original Response", self._extender._originalresponseViewer.getComponent()) 148 | self._extender.original_requests_tabs.addTab("Expand", None) 149 | self._extender.original_requests_tabs.setSelectedIndex(0) 150 | 151 | self._extender.unauthenticated_requests_tabs = JTabbedPane() 152 | self._extender.unauthenticated_requests_tabs.addMouseListener(Mouseclick(self._extender)) 153 | self._extender.unauthenticated_requests_tabs.addTab("Unauthenticated Request", self._extender._unauthorizedrequestViewer.getComponent()) 154 | self._extender.unauthenticated_requests_tabs.addTab("Unauthenticated Response", self._extender._unauthorizedresponseViewer.getComponent()) 155 | self._extender.unauthenticated_requests_tabs.addTab("Expand", None) 156 | self._extender.unauthenticated_requests_tabs.setSelectedIndex(0) 157 | 158 | self._extender.modified_requests_tabs = JTabbedPane() 159 | self._extender.modified_requests_tabs.addMouseListener(Mouseclick(self._extender)) 160 | self._extender.modified_requests_tabs.addTab("Modified Request", self._extender._requestViewer.getComponent()) 161 | self._extender.modified_requests_tabs.addTab("Modified Response", self._extender._responseViewer.getComponent()) 162 | self._extender.modified_requests_tabs.addTab("Expand", None) 163 | self._extender.modified_requests_tabs.setSelectedIndex(0) 164 | 165 | self._extender.requests_panel = JPanel(GridLayout(3,0)) 166 | self._extender.requests_panel.add(self._extender.modified_requests_tabs) 167 | self._extender.requests_panel.add(self._extender.original_requests_tabs) 168 | self._extender.requests_panel.add(self._extender.unauthenticated_requests_tabs) 169 | 170 | self._extender.tabs.addTab("Request/Response Viewers", self._extender.requests_panel) 171 | 172 | self._extender.tabs.addTab("Configuration", self._extender._cfg_splitpane) 173 | self._extender.tabs.setSelectedIndex(1) 174 | self._extender.tabs.setMinimumSize(Dimension(1,1)) 175 | self._extender._splitpane.setRightComponent(self._extender.tabs) 176 | 177 | 178 | class SendRequestRepeater(ActionListener): 179 | def __init__(self, extender, callbacks, original): 180 | self._extender = extender 181 | self._callbacks = callbacks 182 | self.original = original 183 | 184 | def actionPerformed(self, e): 185 | if self.original: 186 | request = self._extender._currentlyDisplayedItem._originalrequestResponse 187 | else: 188 | request = self._extender._currentlyDisplayedItem._requestResponse 189 | host = request.getHttpService().getHost() 190 | port = request.getHttpService().getPort() 191 | proto = request.getHttpService().getProtocol() 192 | secure = True if proto == "https" else False 193 | 194 | self._callbacks.sendToRepeater(host, port, secure, request.getRequest(), "Autorize") 195 | 196 | class SendResponseComparer(ActionListener): 197 | def __init__(self, extender, callbacks): 198 | self._extender = extender 199 | self._callbacks = callbacks 200 | 201 | def actionPerformed(self, e): 202 | originalResponse = self._extender._currentlyDisplayedItem._originalrequestResponse 203 | modifiedResponse = self._extender._currentlyDisplayedItem._requestResponse 204 | unauthorizedResponse = self._extender._currentlyDisplayedItem._unauthorizedRequestResponse 205 | 206 | self._callbacks.sendToComparer(originalResponse.getResponse()) 207 | self._callbacks.sendToComparer(modifiedResponse.getResponse()) 208 | self._callbacks.sendToComparer(unauthorizedResponse.getResponse()) 209 | 210 | 211 | class RetestSelectedRequest(ActionListener): 212 | def __init__(self, extender): 213 | self._extender = extender 214 | 215 | def actionPerformed(self, e): 216 | start_new_thread(handle_message, (self._extender, "AUTORIZE", False, self._extender._currentlyDisplayedItem._originalrequestResponse)) 217 | 218 | class RetestAllRequests(ActionListener): 219 | def __init__(self, extender): 220 | self._extender = extender 221 | 222 | def actionPerformed(self, e): 223 | start_new_thread(retestAllRequests, (self._extender,)) 224 | 225 | 226 | class DeleteSelectedRequest(AbstractAction): 227 | def __init__(self, extender): 228 | self._extender = extender 229 | 230 | def actionPerformed(self, e): 231 | # Its ready to delete multiple rows at a time once we can figure out how to select multiple row. 232 | rows = self._extender.logTable.getSelectedRows() 233 | if len(rows) != 0: 234 | rows = [self._extender.logTable.convertRowIndexToModel(row) for row in rows] 235 | SwingUtilities.invokeLater(lambda: self._extender.tableModel.removeRows(rows)) 236 | 237 | class CopySelectedURL(ActionListener): 238 | def __init__(self, extender): 239 | self._extender = extender 240 | 241 | def actionPerformed(self, e): 242 | stringSelection = StringSelection(str(self._extender._helpers.analyzeRequest(self._extender._currentlyDisplayedItem._requestResponse).getUrl())) 243 | clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard() 244 | clpbrd.setContents(stringSelection, None) 245 | 246 | class AutoScrollListener(AdjustmentListener): 247 | def __init__(self, extender): 248 | self._extender = extender 249 | 250 | def adjustmentValueChanged(self, e): 251 | if self._extender.autoScroll.isSelected(): 252 | e.getAdjustable().setValue(e.getAdjustable().getMaximum()) 253 | 254 | class MessageEditor(IMessageEditorController): 255 | def __init__(self, extender): 256 | self._extender = extender 257 | 258 | def getHttpService(self): 259 | return self._extender._currentlyDisplayedItem.getHttpService() 260 | 261 | def getRequest(self): 262 | return self._extender._currentlyDisplayedItem.getRequest() 263 | 264 | def getResponse(self): 265 | return self._extender._currentlyDisplayedItem.getResponse() 266 | 267 | class Mouseclick(MouseAdapter): 268 | def __init__(self, extender): 269 | self._extender = extender 270 | 271 | def mouseReleased(self, evt): 272 | if evt.getComponent().getSelectedIndex() == 2: 273 | if self._extender.expanded_requests == 0: 274 | expand(self._extender, evt.getComponent()) 275 | else: 276 | collapse(self._extender, evt.getComponent()) 277 | 278 | class SendRequestToRepeaterAction(AbstractAction): 279 | def __init__(self, extender, callbacks): 280 | self._extender = extender 281 | self._callbacks = callbacks 282 | 283 | def actionPerformed(self, e): 284 | # Get the selected row of the JTable 285 | row = self._extender.logTable.getSelectedRow() 286 | 287 | # Get the LogEntry object for the selected row 288 | rowModelIndex = self._extender.logTable.convertRowIndexToModel(row) 289 | entry = self._extender.tableModel.getValueAt(rowModelIndex, 0) 290 | 291 | # Get the modified request 292 | request = self._extender._currentlyDisplayedItem._requestResponse 293 | host = request.getHttpService().getHost() 294 | port = request.getHttpService().getPort() 295 | proto = request.getHttpService().getProtocol() 296 | secure = True if proto == "https" else False 297 | 298 | self._callbacks.sendToRepeater(host, port, secure, request.getRequest(), "Autorize") 299 | 300 | class CopySelectedURLToClipBoard(AbstractAction): 301 | def __init__(self, extender, callbacks): 302 | self._extender = extender 303 | self._callbacks = callbacks 304 | 305 | def actionPerformed(self, e): 306 | stringSelection = StringSelection(str(self._extender._helpers.analyzeRequest( 307 | self._extender._currentlyDisplayedItem._requestResponse).getUrl())) 308 | clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard() 309 | clpbrd.setContents(stringSelection, None) -------------------------------------------------------------------------------- /gui/save_restore.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from javax.swing import SwingUtilities 5 | from javax.swing import JFileChooser 6 | from javax.swing import JFrame 7 | 8 | from table import LogEntry, UpdateTableEDT 9 | from helpers.http import get_cookie_header_from_message, get_authorization_header_from_message, IHttpRequestResponseImplementation 10 | 11 | import csv, base64, json, re, sys 12 | 13 | # This code is necessary to maximize the csv field limit for the save and 14 | # restore functionality 15 | maxInt = sys.maxsize 16 | decrement = True 17 | while decrement: 18 | decrement = False 19 | try: 20 | csv.field_size_limit(maxInt) 21 | except OverflowError: 22 | maxInt = int(maxInt/10) 23 | decrement = True 24 | 25 | class SaveRestore(): 26 | def __init__(self, extender): 27 | self._extender = extender 28 | self._checkBoxes = [ 29 | "autoScroll", 30 | "ignore304", 31 | "prevent304", 32 | "interceptRequestsfromRepeater", 33 | "doUnauthorizedRequest", 34 | "replaceQueryParam", 35 | "showAuthBypassModified", 36 | "showAuthPotentiallyEnforcedModified", 37 | "showAuthEnforcedModified", 38 | "showAuthBypassUnauthenticated", 39 | "showAuthPotentiallyEnforcedUnauthenticated", 40 | "showAuthEnforcedUnauthenticated", 41 | "showDisabledUnauthenticated" 42 | ] 43 | 44 | def saveState(self): 45 | parentFrame = JFrame() 46 | fileChooser = JFileChooser() 47 | fileChooser.setDialogTitle("State output file") 48 | userSelection = fileChooser.showSaveDialog(parentFrame) 49 | 50 | if userSelection == JFileChooser.APPROVE_OPTION: 51 | exportFile = fileChooser.getSelectedFile() 52 | with open(exportFile.getAbsolutePath(), 'wb') as csvfile: 53 | csvwriter = csv.writer(csvfile, delimiter='\t', quotechar='|', quoting=csv.QUOTE_MINIMAL) 54 | 55 | # Configuration 56 | tempRow = ["ReplaceString", base64.b64encode(self._extender.replaceString.getText())] 57 | csvwriter.writerow(tempRow) 58 | 59 | for EDFilter in self._extender.EDModel.toArray(): 60 | tempRow = ["EDFilter", base64.b64encode(EDFilter)] 61 | csvwriter.writerow(tempRow) 62 | 63 | for EDFilterUnauth in self._extender.EDModelUnauth.toArray(): 64 | tempRow = ["EDFilterUnauth", base64.b64encode(EDFilterUnauth)] 65 | csvwriter.writerow(tempRow) 66 | 67 | for IFFilter in self._extender.IFModel.toArray(): 68 | tempRow = ["IFFilter", base64.b64encode(IFFilter)] 69 | csvwriter.writerow(tempRow) 70 | 71 | for t in ["AndOrType", "AndOrTypeUnauth"]: 72 | tempRow = [t, getattr(self._extender, t).getSelectedItem()] 73 | csvwriter.writerow(tempRow) 74 | 75 | for key in self._extender.badProgrammerMRModel: 76 | d = dict(self._extender.badProgrammerMRModel[key]) 77 | d["regexMatch"] = d["regexMatch"] is not None 78 | tempRow = ["MatchReplace", base64.b64encode(json.dumps(d))] 79 | csvwriter.writerow(tempRow) 80 | 81 | d = dict((c, getattr(self._extender, c).isSelected()) for c in self._checkBoxes) 82 | tempRow = ["CheckBoxes", json.dumps(d)] 83 | csvwriter.writerow(tempRow) 84 | 85 | isSelected = self._extender.exportPnl.getComponents()[-1].isSelected() 86 | tempRow = ["RemoveDuplicates", json.dumps(isSelected)] 87 | csvwriter.writerow(tempRow) 88 | 89 | # Request/response list 90 | for i in range(0,self._extender._log.size()): 91 | tempRequestResponseHost = self._extender._log.get(i)._requestResponse.getHttpService().getHost() 92 | tempRequestResponsePort = self._extender._log.get(i)._requestResponse.getHttpService().getPort() 93 | tempRequestResponseProtocol = self._extender._log.get(i)._requestResponse.getHttpService().getProtocol() 94 | tempRequestResponseRequest = base64.b64encode(self._extender._log.get(i)._requestResponse.getRequest()) 95 | tempRequestResponseResponse = base64.b64encode(self._extender._log.get(i)._requestResponse.getResponse()) 96 | 97 | tempOriginalRequestResponseHost = self._extender._log.get(i)._originalrequestResponse.getHttpService().getHost() 98 | tempOriginalRequestResponsePort = self._extender._log.get(i)._originalrequestResponse.getHttpService().getPort() 99 | tempOriginalRequestResponseProtocol = self._extender._log.get(i)._originalrequestResponse.getHttpService().getProtocol() 100 | tempOriginalRequestResponseRequest = base64.b64encode(self._extender._log.get(i)._originalrequestResponse.getRequest()) 101 | tempOriginalRequestResponseResponse = base64.b64encode(self._extender._log.get(i)._originalrequestResponse.getResponse()) 102 | 103 | if self._extender._log.get(i)._unauthorizedRequestResponse is not None: 104 | tempUnauthorizedRequestResponseHost = self._extender._log.get(i)._unauthorizedRequestResponse.getHttpService().getHost() 105 | tempUnauthorizedRequestResponsePort = self._extender._log.get(i)._unauthorizedRequestResponse.getHttpService().getPort() 106 | tempUnauthorizedRequestResponseProtocol = self._extender._log.get(i)._unauthorizedRequestResponse.getHttpService().getProtocol() 107 | tempUnauthorizedRequestResponseRequest = base64.b64encode(self._extender._log.get(i)._unauthorizedRequestResponse.getRequest()) 108 | tempUnauthorizedRequestResponseResponse = base64.b64encode(self._extender._log.get(i)._unauthorizedRequestResponse.getResponse()) 109 | else: 110 | tempUnauthorizedRequestResponseHost = None 111 | tempUnauthorizedRequestResponsePort = None 112 | tempUnauthorizedRequestResponseProtocol = None 113 | tempUnauthorizedRequestResponseRequest = None 114 | tempUnauthorizedRequestResponseResponse = None 115 | 116 | tempEnforcementStatus = self._extender._log.get(i)._enfocementStatus 117 | tempEnforcementStatusUnauthorized = self._extender._log.get(i)._enfocementStatusUnauthorized 118 | 119 | tempRow = [tempRequestResponseHost,tempRequestResponsePort,tempRequestResponseProtocol,tempRequestResponseRequest,tempRequestResponseResponse] 120 | tempRow.extend([tempOriginalRequestResponseHost,tempOriginalRequestResponsePort,tempOriginalRequestResponseProtocol,tempOriginalRequestResponseRequest,tempOriginalRequestResponseResponse]) 121 | tempRow.extend([tempUnauthorizedRequestResponseHost,tempUnauthorizedRequestResponsePort,tempUnauthorizedRequestResponseProtocol,tempUnauthorizedRequestResponseRequest,tempUnauthorizedRequestResponseResponse]) 122 | tempRow.extend([tempEnforcementStatus,tempEnforcementStatusUnauthorized]) 123 | 124 | csvwriter.writerow(tempRow) 125 | 126 | def restoreState(self): 127 | parentFrame = JFrame() 128 | fileChooser = JFileChooser() 129 | fileChooser.setDialogTitle("State import file") 130 | userSelection = fileChooser.showDialog(parentFrame, "Restore") 131 | modelMap = { 132 | "IFFilter": self._extender.IFModel, 133 | "EDFilter": self._extender.EDModel, 134 | "EDFilterUnauth": self._extender.EDModelUnauth 135 | } 136 | 137 | if userSelection == JFileChooser.APPROVE_OPTION: 138 | importFile = fileChooser.getSelectedFile() 139 | 140 | with open(importFile.getAbsolutePath(), 'r') as csvfile: 141 | 142 | csvreader = csv.reader(csvfile, delimiter='\t', quotechar='|') 143 | 144 | for row in csvreader: 145 | # Configuration 146 | if row[0] == "ReplaceString": 147 | self._extender.replaceString.setText(base64.b64decode(row[1])) 148 | continue 149 | 150 | if row[0] in modelMap: 151 | f = base64.b64decode(row[1]) 152 | if f not in modelMap[row[0]].toArray(): 153 | modelMap[row[0]].addElement(f) 154 | continue 155 | 156 | if row[0] in {"AndOrType", "AndOrTypeUnauth"}: 157 | getattr(self._extender, row[0]).setSelectedItem(row[1]) 158 | continue 159 | 160 | if row[0] == "MatchReplace": 161 | d = json.loads(base64.b64decode(row[1])) 162 | key = d["type"] + " " + d["match"] + "->" + d["replace"] 163 | if key in self._extender.badProgrammerMRModel: 164 | continue 165 | regexMatch = None 166 | if d["regexMatch"]: 167 | try: 168 | d["regexMatch"] = re.compile(d["match"]) 169 | except re.error: 170 | print("ERROR: Regex to restore is invalid:", d["match"]) 171 | continue 172 | self._extender.badProgrammerMRModel[key] = d 173 | self._extender.MRModel.addElement(key) 174 | continue 175 | 176 | if row[0] == "CheckBoxes": 177 | d = json.loads(row[1]) 178 | for k in d: 179 | getattr(self._extender, k).setSelected(d[k]) 180 | continue 181 | 182 | if row[0] == "RemoveDuplicates": 183 | isSelected = json.loads(row[1]) 184 | try: 185 | self._extender.exportPnl.getComponents()[-1].setSelected(isSelected) 186 | except TypeError: # suppress TypeError: None required for void return 187 | pass 188 | continue 189 | 190 | # Request/response list 191 | tempRequestResponseHost = row[0] 192 | tempRequestResponsePort = row[1] 193 | tempRequestResponseProtocol = row[2] 194 | tempRequestResponseRequest = base64.b64decode(row[3]) 195 | tempRequestResponseResponse = base64.b64decode(row[4]) 196 | 197 | tempRequestResponseHttpService = self._extender._helpers.buildHttpService(tempRequestResponseHost,int(tempRequestResponsePort),tempRequestResponseProtocol) 198 | tempRequestResponse = IHttpRequestResponseImplementation(tempRequestResponseHttpService,tempRequestResponseRequest,tempRequestResponseResponse) 199 | 200 | tempOriginalRequestResponseHost = row[5] 201 | tempOriginalRequestResponsePort = row[6] 202 | tempOriginalRequestResponseProtocol = row[7] 203 | tempOriginalRequestResponseRequest = base64.b64decode(row[8]) 204 | tempOriginalRequestResponseResponse = base64.b64decode(row[9]) 205 | 206 | tempOriginalRequestResponseHttpService = self._extender._helpers.buildHttpService(tempOriginalRequestResponseHost,int(tempOriginalRequestResponsePort),tempOriginalRequestResponseProtocol) 207 | tempOriginalRequestResponse = IHttpRequestResponseImplementation(tempOriginalRequestResponseHttpService,tempOriginalRequestResponseRequest,tempOriginalRequestResponseResponse) 208 | 209 | checkAuthentication = True 210 | if row[10] != '': 211 | tempUnauthorizedRequestResponseHost = row[10] 212 | tempUnauthorizedRequestResponsePort = row[11] 213 | tempUnauthorizedRequestResponseProtocol = row[12] 214 | tempUnauthorizedRequestResponseRequest = base64.b64decode(row[13]) 215 | tempUnauthorizedRequestResponseResponse = base64.b64decode(row[14]) 216 | tempUnauthorizedRequestResponseHttpService = self._extender._helpers.buildHttpService(tempUnauthorizedRequestResponseHost,int(tempUnauthorizedRequestResponsePort),tempUnauthorizedRequestResponseProtocol) 217 | tempUnauthorizedRequestResponse = IHttpRequestResponseImplementation(tempUnauthorizedRequestResponseHttpService,tempUnauthorizedRequestResponseRequest,tempUnauthorizedRequestResponseResponse) 218 | else: 219 | checkAuthentication = False 220 | tempUnauthorizedRequestResponse = None 221 | 222 | tempEnforcementStatus = row[15] 223 | tempEnforcementStatusUnauthorized = row[16] 224 | 225 | self._extender._lock.acquire() 226 | 227 | row = self._extender._log.size() 228 | 229 | if checkAuthentication: 230 | self._extender._log.add( 231 | LogEntry(self._extender.currentRequestNumber, 232 | self._extender._callbacks.saveBuffersToTempFiles(tempRequestResponse), 233 | self._extender._helpers.analyzeRequest(tempRequestResponse).getMethod(), 234 | self._extender._helpers.analyzeRequest(tempRequestResponse).getUrl(), 235 | self._extender._callbacks.saveBuffersToTempFiles(tempOriginalRequestResponse), 236 | tempEnforcementStatus, 237 | self._extender._callbacks.saveBuffersToTempFiles(tempUnauthorizedRequestResponse), 238 | tempEnforcementStatusUnauthorized)) 239 | else: 240 | self._extender._log.add( 241 | LogEntry(self._extender.currentRequestNumber, 242 | self._extender._callbacks.saveBuffersToTempFiles(tempRequestResponse), 243 | self._extender._helpers.analyzeRequest(tempRequestResponse).getMethod(), 244 | self._extender._helpers.analyzeRequest(tempRequestResponse).getUrl(), 245 | self._extender._callbacks.saveBuffersToTempFiles(tempOriginalRequestResponse), 246 | tempEnforcementStatus,None,tempEnforcementStatusUnauthorized)) 247 | 248 | SwingUtilities.invokeLater(UpdateTableEDT(self._extender,"insert",row,row)) 249 | self._extender.currentRequestNumber = self._extender.currentRequestNumber + 1 250 | self._extender._lock.release() 251 | 252 | lastRow = self._extender._log.size() 253 | if lastRow > 0: 254 | cookiesHeader = get_cookie_header_from_message(self._extender, self._extender._log.get(lastRow - 1)._requestResponse) 255 | if cookiesHeader: 256 | self._extender.lastCookiesHeader = cookiesHeader 257 | self._extender.fetchCookiesHeaderButton.setEnabled(True) 258 | authorizationHeader = get_authorization_header_from_message(self._extender, self._extender._log.get(lastRow - 1)._requestResponse) 259 | if authorizationHeader: 260 | self._extender.lastAuthorizationHeader = authorizationHeader 261 | self._extender.fetchAuthorizationHeaderButton.setEnabled(True) 262 | -------------------------------------------------------------------------------- /authorization/authorization.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from operator import truediv 5 | import sys 6 | reload(sys) 7 | 8 | if (sys.version_info[0] == 2): 9 | sys.setdefaultencoding('utf8') 10 | 11 | sys.path.append("..") 12 | 13 | from helpers.http import get_authorization_header_from_message, get_cookie_header_from_message, isStatusCodesReturned, makeMessage, makeRequest, getResponseBody, IHttpRequestResponseImplementation 14 | from gui.table import LogEntry, UpdateTableEDT 15 | from javax.swing import SwingUtilities 16 | from java.net import URL 17 | import re 18 | 19 | def tool_needs_to_be_ignored(self, toolFlag): 20 | for i in range(0, self.IFList.getModel().getSize()): 21 | if self.IFList.getModel().getElementAt(i).split(":")[0] == "Ignore spider requests": 22 | if (toolFlag == self._callbacks.TOOL_SPIDER): 23 | return True 24 | if self.IFList.getModel().getElementAt(i).split(":")[0] == "Ignore proxy requests": 25 | if (toolFlag == self._callbacks.TOOL_PROXY): 26 | return True 27 | if self.IFList.getModel().getElementAt(i).split(":")[0] == "Ignore target requests": 28 | if (toolFlag == self._callbacks.TOOL_TARGET): 29 | return True 30 | return False 31 | 32 | def capture_last_cookie_header(self, messageInfo): 33 | cookies = get_cookie_header_from_message(self, messageInfo) 34 | if cookies: 35 | self.lastCookiesHeader = cookies 36 | self.fetchCookiesHeaderButton.setEnabled(True) 37 | 38 | def capture_last_authorization_header(self, messageInfo): 39 | authorization = get_authorization_header_from_message(self, messageInfo) 40 | if authorization: 41 | self.lastAuthorizationHeader = authorization 42 | self.fetchAuthorizationHeaderButton.setEnabled(True) 43 | 44 | 45 | def valid_tool(self, toolFlag): 46 | return (toolFlag == self._callbacks.TOOL_PROXY or 47 | (toolFlag == self._callbacks.TOOL_REPEATER and 48 | self.interceptRequestsfromRepeater.isSelected())) 49 | 50 | def handle_304_status_code_prevention(self, messageIsRequest, messageInfo): 51 | should_prevent = False 52 | if self.prevent304.isSelected(): 53 | if messageIsRequest: 54 | requestHeaders = list(self._helpers.analyzeRequest(messageInfo).getHeaders()) 55 | newHeaders = list() 56 | for header in requestHeaders: 57 | if not "If-None-Match:" in header and not "If-Modified-Since:" in header: 58 | newHeaders.append(header) 59 | should_prevent = True 60 | if should_prevent: 61 | requestInfo = self._helpers.analyzeRequest(messageInfo) 62 | bodyBytes = messageInfo.getRequest()[requestInfo.getBodyOffset():] 63 | bodyStr = self._helpers.bytesToString(bodyBytes) 64 | messageInfo.setRequest(self._helpers.buildHttpMessage(newHeaders, bodyStr)) 65 | 66 | def message_not_from_autorize(self, messageInfo): 67 | return not self.replaceString.getText() in self._helpers.analyzeRequest(messageInfo).getHeaders() 68 | 69 | def no_filters_defined(self): 70 | return self.IFList.getModel().getSize() == 0 71 | 72 | def message_passed_interception_filters(self, messageInfo): 73 | urlString = str(self._helpers.analyzeRequest(messageInfo).getUrl()) 74 | reqInfo = self._helpers.analyzeRequest(messageInfo) 75 | reqBodyBytes = messageInfo.getRequest()[reqInfo.getBodyOffset():] 76 | bodyStr = self._helpers.bytesToString(reqBodyBytes) 77 | 78 | resInfo = self._helpers.analyzeResponse(messageInfo.getResponse()) 79 | resBodyBytes = messageInfo.getResponse()[resInfo.getBodyOffset():] 80 | resStr = self._helpers.bytesToString(resBodyBytes) 81 | 82 | message_passed_filters = True 83 | for i in range(0, self.IFList.getModel().getSize()): 84 | interceptionFilter = self.IFList.getModel().getElementAt(i) 85 | interceptionFilterTitle = interceptionFilter.split(":")[0] 86 | if interceptionFilterTitle == "Scope items only": 87 | currentURL = URL(urlString) 88 | if not self._callbacks.isInScope(currentURL): 89 | message_passed_filters = False 90 | 91 | if interceptionFilterTitle == "URL Contains (simple string)": 92 | if interceptionFilter[30:] not in urlString: 93 | message_passed_filters = False 94 | 95 | if interceptionFilterTitle == "URL Contains (regex)": 96 | regex_string = interceptionFilter[22:] 97 | if re.search(regex_string, urlString, re.IGNORECASE) is None: 98 | message_passed_filters = False 99 | 100 | if interceptionFilterTitle == "URL Not Contains (simple string)": 101 | if interceptionFilter[34:] in urlString: 102 | message_passed_filters = False 103 | 104 | if interceptionFilterTitle == "URL Not Contains (regex)": 105 | regex_string = interceptionFilter[26:] 106 | if not re.search(regex_string, urlString, re.IGNORECASE) is None: 107 | message_passed_filters = False 108 | 109 | if interceptionFilterTitle == "Request Body contains (simple string)": 110 | if interceptionFilter[40:] not in bodyStr: 111 | message_passed_filters = False 112 | 113 | if interceptionFilterTitle == "Request Body contains (regex)": 114 | regex_string = interceptionFilter[32:] 115 | if re.search(regex_string, bodyStr, re.IGNORECASE) is None: 116 | message_passed_filters = False 117 | 118 | if interceptionFilterTitle == "Request Body NOT contains (simple string)": 119 | if interceptionFilter[44:] in bodyStr: 120 | message_passed_filters = False 121 | 122 | if interceptionFilterTitle == "Request Body Not contains (regex)": 123 | regex_string = interceptionFilter[36:] 124 | if not re.search(regex_string, bodyStr, re.IGNORECASE) is None: 125 | message_passed_filters = False 126 | 127 | if interceptionFilterTitle == "Response Body contains (simple string)": 128 | if interceptionFilter[41:] not in resStr: 129 | message_passed_filters = False 130 | 131 | if interceptionFilterTitle == "Response Body contains (regex)": 132 | regex_string = interceptionFilter[33:] 133 | if re.search(regex_string, resStr, re.IGNORECASE) is None: 134 | message_passed_filters = False 135 | 136 | if interceptionFilterTitle == "Response Body NOT contains (simple string)": 137 | if interceptionFilter[45:] in resStr: 138 | message_passed_filters = False 139 | 140 | if interceptionFilterTitle == "Response Body Not contains (regex)": 141 | regex_string = interceptionFilter[37:] 142 | if not re.search(regex_string, resStr, re.IGNORECASE) is None: 143 | message_passed_filters = False 144 | 145 | if interceptionFilterTitle == "Header contains": 146 | for header in list(resInfo.getHeaders()): 147 | if interceptionFilter[17:] in header: 148 | message_passed_filters = False 149 | 150 | if interceptionFilterTitle == "Header doesn't contain": 151 | for header in list(resInfo.getHeaders()): 152 | if not interceptionFilter[17:] in header: 153 | message_passed_filters = False 154 | 155 | if interceptionFilterTitle == "Only HTTP methods (newline separated)": 156 | filterMethods = interceptionFilter[39:].split("\n") 157 | filterMethods = [x.lower() for x in filterMethods] 158 | reqMethod = str(self._helpers.analyzeRequest(messageInfo).getMethod()) 159 | if reqMethod.lower() not in filterMethods: 160 | message_passed_filters = False 161 | 162 | if interceptionFilterTitle == "Ignore HTTP methods (newline separated)": 163 | filterMethods = interceptionFilter[41:].split("\n") 164 | filterMethods = [x.lower() for x in filterMethods] 165 | reqMethod = str(self._helpers.analyzeRequest(messageInfo).getMethod()) 166 | if reqMethod.lower() in filterMethods: 167 | message_passed_filters = False 168 | 169 | if interceptionFilterTitle == "Ignore OPTIONS requests": 170 | reqMethod = str(self._helpers.analyzeRequest(messageInfo).getMethod()) 171 | if reqMethod == "OPTIONS": 172 | message_passed_filters = False 173 | 174 | return message_passed_filters 175 | 176 | def handle_message(self, toolFlag, messageIsRequest, messageInfo): 177 | if tool_needs_to_be_ignored(self, toolFlag): 178 | return 179 | 180 | capture_last_cookie_header(self, messageInfo) 181 | capture_last_authorization_header(self, messageInfo) 182 | 183 | if (self.intercept and valid_tool(self, toolFlag) or toolFlag == "AUTORIZE"): 184 | handle_304_status_code_prevention(self, messageIsRequest, messageInfo) 185 | 186 | if not messageIsRequest: 187 | if message_not_from_autorize(self, messageInfo): 188 | if self.ignore304.isSelected(): 189 | if isStatusCodesReturned(self, messageInfo, ["304", "204"]): 190 | return 191 | 192 | if no_filters_defined(self): 193 | checkAuthorization(self, messageInfo, 194 | self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(), 195 | self.doUnauthorizedRequest.isSelected()) 196 | else: 197 | if message_passed_interception_filters(self, messageInfo): 198 | checkAuthorization(self, messageInfo,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected()) 199 | 200 | def send_request_to_autorize(self, messageInfo): 201 | if messageInfo.getResponse() is None: 202 | message = makeMessage(self, messageInfo,False,False) 203 | requestResponse = makeRequest(self, messageInfo, message) 204 | checkAuthorization(self, requestResponse,self._helpers.analyzeResponse(requestResponse.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected()) 205 | else: 206 | request = messageInfo.getRequest() 207 | response = messageInfo.getResponse() 208 | httpService = messageInfo.getHttpService() 209 | newHttpRequestResponse = IHttpRequestResponseImplementation(httpService,request,response) 210 | newHttpRequestResponsePersisted = self._callbacks.saveBuffersToTempFiles(newHttpRequestResponse) 211 | checkAuthorization(self, newHttpRequestResponsePersisted,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected()) 212 | 213 | def auth_enforced_via_enforcement_detectors(self, filters, requestResponse, andOrEnforcement): 214 | response = requestResponse.getResponse() 215 | analyzedResponse = self._helpers.analyzeResponse(response) 216 | auth_enforced = False 217 | if andOrEnforcement == "And": 218 | andEnforcementCheck = True 219 | auth_enforced = True 220 | else: 221 | andEnforcementCheck = False 222 | auth_enforced = False 223 | 224 | for filter in filters: 225 | filter = self._helpers.bytesToString(bytes(filter)) 226 | filter_kv = filter.split(":", 1) 227 | inverse = "NOT" in filter_kv[0] 228 | filter_kv[0] = filter_kv[0].replace(" NOT", "") 229 | filter = ":".join(filter_kv) 230 | 231 | if filter.startswith("Status code equals: "): 232 | statusCode = filter[20:] 233 | filterMatched = inverse ^ isStatusCodesReturned(self, requestResponse, statusCode) 234 | 235 | elif filter.startswith("Headers (simple string): "): 236 | filterMatched = inverse ^ (filter[25:] in self._helpers.bytesToString(requestResponse.getResponse()[0:analyzedResponse.getBodyOffset()])) 237 | 238 | elif filter.startswith("Headers (regex): "): 239 | regex_string = filter[17:] 240 | p = re.compile(regex_string, re.IGNORECASE) 241 | filterMatched = inverse ^ bool(p.search(self._helpers.bytesToString(requestResponse.getResponse()[0:analyzedResponse.getBodyOffset()]))) 242 | 243 | elif filter.startswith("Body (simple string): "): 244 | filterMatched = inverse ^ (filter[22:] in self._helpers.bytesToString(requestResponse.getResponse()[analyzedResponse.getBodyOffset():])) 245 | 246 | elif filter.startswith("Body (regex): "): 247 | regex_string = filter[14:] 248 | p = re.compile(regex_string, re.IGNORECASE) 249 | filterMatched = inverse ^ bool(p.search(self._helpers.bytesToString(requestResponse.getResponse()[analyzedResponse.getBodyOffset():]))) 250 | 251 | elif filter.startswith("Full response (simple string): "): 252 | filterMatched = inverse ^ (filter[31:] in self._helpers.bytesToString(requestResponse.getResponse())) 253 | 254 | elif filter.startswith("Full response (regex): "): 255 | regex_string = filter[23:] 256 | p = re.compile(regex_string, re.IGNORECASE) 257 | filterMatched = inverse ^ bool(p.search(self._helpers.bytesToString(requestResponse.getResponse()))) 258 | 259 | elif filter.startswith("Full response length: "): 260 | filterMatched = inverse ^ (str(len(response)) == filter[22:].strip()) 261 | 262 | if andEnforcementCheck: 263 | if auth_enforced and not filterMatched: 264 | auth_enforced = False 265 | else: 266 | if not auth_enforced and filterMatched: 267 | auth_enforced = True 268 | 269 | return auth_enforced 270 | 271 | def checkBypass(self, oldStatusCode, newStatusCode, oldContent, 272 | newContent, filters, requestResponse, andOrEnforcement): 273 | if oldStatusCode == newStatusCode: 274 | auth_enforced = 0 275 | if len(filters) > 0: 276 | auth_enforced = auth_enforced_via_enforcement_detectors(self, filters, requestResponse, andOrEnforcement) 277 | if auth_enforced: 278 | return self.ENFORCED_STR 279 | elif oldContent == newContent: 280 | return self.BYPASSSED_STR 281 | else: 282 | return self.IS_ENFORCED_STR 283 | else: 284 | return self.ENFORCED_STR 285 | 286 | def checkAuthorization(self, messageInfo, originalHeaders, checkUnauthorized): 287 | # Check unauthorized request 288 | if checkUnauthorized: 289 | messageUnauthorized = makeMessage(self, messageInfo, True, False) 290 | requestResponseUnauthorized = makeRequest(self, messageInfo, messageUnauthorized) 291 | unauthorizedResponse = requestResponseUnauthorized.getResponse() 292 | analyzedResponseUnauthorized = self._helpers.analyzeResponse(unauthorizedResponse) 293 | statusCodeUnauthorized = analyzedResponseUnauthorized.getHeaders()[0] 294 | contentUnauthorized = getResponseBody(self, requestResponseUnauthorized) 295 | 296 | message = makeMessage(self, messageInfo, True, True) 297 | requestResponse = makeRequest(self, messageInfo, message) 298 | newResponse = requestResponse.getResponse() 299 | analyzedResponse = self._helpers.analyzeResponse(newResponse) 300 | 301 | oldStatusCode = originalHeaders[0] 302 | newStatusCode = analyzedResponse.getHeaders()[0] 303 | oldContent = getResponseBody(self, messageInfo) 304 | newContent = getResponseBody(self, requestResponse) 305 | 306 | EDFilters = self.EDModel.toArray() 307 | 308 | impression = checkBypass(self, oldStatusCode, newStatusCode, oldContent, newContent, EDFilters, requestResponse, self.AndOrType.getSelectedItem()) 309 | 310 | if checkUnauthorized: 311 | EDFiltersUnauth = self.EDModelUnauth.toArray() 312 | impressionUnauthorized = checkBypass(self, oldStatusCode, statusCodeUnauthorized, oldContent, contentUnauthorized, EDFiltersUnauth, requestResponseUnauthorized, self.AndOrTypeUnauth.getSelectedItem()) 313 | 314 | self._lock.acquire() 315 | 316 | row = self._log.size() 317 | method = self._helpers.analyzeRequest(messageInfo.getRequest()).getMethod() 318 | 319 | if checkUnauthorized: 320 | self._log.add(LogEntry(self.currentRequestNumber,self._callbacks.saveBuffersToTempFiles(requestResponse), method, self._helpers.analyzeRequest(requestResponse).getUrl(),messageInfo,impression,self._callbacks.saveBuffersToTempFiles(requestResponseUnauthorized),impressionUnauthorized)) # same requests not include again. 321 | else: 322 | self._log.add(LogEntry(self.currentRequestNumber,self._callbacks.saveBuffersToTempFiles(requestResponse), method, self._helpers.analyzeRequest(requestResponse).getUrl(),messageInfo,impression,None,"Disabled")) # same requests not include again. 323 | 324 | SwingUtilities.invokeLater(UpdateTableEDT(self,"insert",row,row)) 325 | self.currentRequestNumber = self.currentRequestNumber + 1 326 | self._lock.release() 327 | 328 | def checkAuthorizationV2(self, messageInfo): 329 | checkAuthorization(self, messageInfo, self._extender._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(), self._extender.doUnauthorizedRequest.isSelected()) 330 | 331 | def retestAllRequests(self): 332 | self.logTable.setAutoCreateRowSorter(True) 333 | for i in range(self.tableModel.getRowCount()): 334 | logEntry = self._log.get(self.logTable.convertRowIndexToModel(i)) 335 | handle_message(self, "AUTORIZE", False, logEntry._originalrequestResponse) 336 | -------------------------------------------------------------------------------- /gui/configuration_tab.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from javax.swing import DefaultComboBoxModel 5 | from java.awt.event import ActionListener 6 | from javax.swing import SwingUtilities 7 | from javax.swing import JToggleButton 8 | from javax.swing import JScrollPane 9 | from javax.swing import JTabbedPane 10 | from javax.swing import JOptionPane 11 | from javax.swing import GroupLayout 12 | from javax.swing import JSplitPane 13 | from javax.swing import JComboBox 14 | from javax.swing import JTextArea 15 | from javax.swing import JCheckBox 16 | from javax.swing import JButton 17 | from javax.swing import JPanel 18 | from javax.swing import JLabel 19 | 20 | from table import UpdateTableEDT 21 | 22 | class ConfigurationTab(): 23 | def __init__(self, extender): 24 | self._extender = extender 25 | 26 | def draw(self): 27 | """ init configuration tab 28 | """ 29 | self.DEFUALT_REPLACE_TEXT = "Cookie: Insert=injected; cookie=or;\nHeader: here" 30 | self._extender.startButton = JToggleButton("Autorize is off", 31 | actionPerformed=self.startOrStop) 32 | self._extender.startButton.setBounds(10, 20, 230, 30) 33 | 34 | self._extender.clearButton = JButton("Clear List", actionPerformed=self.clearList) 35 | self._extender.clearButton.setBounds(10, 80, 100, 30) 36 | self._extender.autoScroll = JCheckBox("Auto Scroll") 37 | self._extender.autoScroll.setBounds(145, 80, 130, 30) 38 | 39 | self._extender.ignore304 = JCheckBox("Ignore 304/204 status code responses") 40 | self._extender.ignore304.setBounds(280, 5, 300, 30) 41 | self._extender.ignore304.setSelected(True) 42 | 43 | self._extender.prevent304 = JCheckBox("Prevent 304 Not Modified status code") 44 | self._extender.prevent304.setBounds(280, 25, 300, 30) 45 | self._extender.interceptRequestsfromRepeater = JCheckBox("Intercept requests from Repeater") 46 | self._extender.interceptRequestsfromRepeater.setBounds(280, 45, 300, 30) 47 | 48 | self._extender.doUnauthorizedRequest = JCheckBox("Check unauthenticated") 49 | self._extender.doUnauthorizedRequest.setBounds(280, 65, 300, 30) 50 | self._extender.doUnauthorizedRequest.setSelected(True) 51 | 52 | self._extender.replaceQueryParam = JCheckBox("Replace query params", actionPerformed=self.replaceQueryHanlder) 53 | self._extender.replaceQueryParam.setBounds(280, 85, 300, 30) 54 | self._extender.replaceQueryParam.setSelected(False) 55 | 56 | self._extender.saveHeadersButton = JButton("Add", 57 | actionPerformed=self.saveHeaders) 58 | self._extender.saveHeadersButton.setBounds(315, 115, 80, 30) 59 | 60 | self._extender.removeHeadersButton = JButton("Remove", 61 | actionPerformed=self.removeHeaders) 62 | self._extender.removeHeadersButton.setBounds(400, 115, 80, 30) 63 | 64 | savedHeadersTitles = self.getSavedHeadersTitles() 65 | self._extender.savedHeadersTitlesCombo = JComboBox(savedHeadersTitles) 66 | self._extender.savedHeadersTitlesCombo.addActionListener(SavedHeaderChange(self._extender)) 67 | self._extender.savedHeadersTitlesCombo.setBounds(10, 115, 300, 30) 68 | 69 | self._extender.replaceString = JTextArea(self.DEFUALT_REPLACE_TEXT, 5, 30) 70 | self._extender.replaceString.setWrapStyleWord(True) 71 | self._extender.replaceString.setLineWrap(True) 72 | 73 | scrollReplaceString = JScrollPane(self._extender.replaceString) 74 | scrollReplaceString.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 75 | scrollReplaceString.setBounds(10, 150, 470, 150) 76 | 77 | fromLastRequestLabel = JLabel("From last request:") 78 | fromLastRequestLabel.setBounds(10, 305, 250, 30) 79 | 80 | self._extender.fetchCookiesHeaderButton = JButton("Fetch Cookies header", 81 | actionPerformed=self.fetchCookiesHeader) 82 | self._extender.fetchCookiesHeaderButton.setEnabled(False) 83 | self._extender.fetchCookiesHeaderButton.setBounds(10, 330, 220, 30) 84 | 85 | self._extender.fetchAuthorizationHeaderButton = JButton("Fetch Authorization header", 86 | actionPerformed=self.fetchAuthorizationHeader) 87 | self._extender.fetchAuthorizationHeaderButton.setEnabled(False) 88 | self._extender.fetchAuthorizationHeaderButton.setBounds(260, 330, 220, 30) 89 | 90 | self._extender.filtersTabs = JTabbedPane() 91 | self._extender.filtersTabs = self._extender.filtersTabs 92 | self._extender.filtersTabs.addTab("Enforcement Detector", self._extender.EDPnl) 93 | self._extender.filtersTabs.addTab("Detector Unauthenticated", self._extender.EDPnlUnauth) 94 | self._extender.filtersTabs.addTab("Interception Filters", self._extender.filtersPnl) 95 | self._extender.filtersTabs.addTab("Match/Replace", self._extender.MRPnl) 96 | self._extender.filtersTabs.addTab("Table Filter", self._extender.filterPnl) 97 | self._extender.filtersTabs.addTab("Save/Restore", self._extender.exportPnl) 98 | 99 | self._extender.filtersTabs.setSelectedIndex(2) 100 | self._extender.filtersTabs.setBounds(0, 350, 2000, 700) 101 | 102 | self.config_pnl = JPanel() 103 | layout = GroupLayout(self.config_pnl) 104 | self.config_pnl.setLayout(layout) 105 | layout.setAutoCreateGaps(True) 106 | layout.setAutoCreateContainerGaps(True) 107 | 108 | layout.setHorizontalGroup( 109 | layout.createSequentialGroup() 110 | .addGroup( 111 | layout.createParallelGroup() 112 | .addComponent( 113 | self._extender.startButton, 114 | GroupLayout.PREFERRED_SIZE, 115 | GroupLayout.PREFERRED_SIZE, 116 | GroupLayout.PREFERRED_SIZE, 117 | ) 118 | 119 | .addComponent( 120 | self._extender.clearButton, 121 | GroupLayout.PREFERRED_SIZE, 122 | GroupLayout.PREFERRED_SIZE, 123 | GroupLayout.PREFERRED_SIZE, 124 | ) 125 | .addComponent( 126 | self._extender.savedHeadersTitlesCombo, 127 | GroupLayout.PREFERRED_SIZE, 128 | GroupLayout.PREFERRED_SIZE, 129 | GroupLayout.PREFERRED_SIZE, 130 | ) 131 | .addComponent( 132 | scrollReplaceString, 133 | GroupLayout.PREFERRED_SIZE, 134 | GroupLayout.PREFERRED_SIZE, 135 | GroupLayout.PREFERRED_SIZE, 136 | ) 137 | .addComponent( 138 | fromLastRequestLabel, 139 | GroupLayout.PREFERRED_SIZE, 140 | GroupLayout.PREFERRED_SIZE, 141 | GroupLayout.PREFERRED_SIZE, 142 | ) 143 | .addGroup(layout.createSequentialGroup() 144 | .addComponent( 145 | self._extender.fetchCookiesHeaderButton, 146 | GroupLayout.PREFERRED_SIZE, 147 | GroupLayout.PREFERRED_SIZE, 148 | GroupLayout.PREFERRED_SIZE, 149 | ) 150 | .addComponent( 151 | self._extender.fetchAuthorizationHeaderButton, 152 | GroupLayout.PREFERRED_SIZE, 153 | GroupLayout.PREFERRED_SIZE, 154 | GroupLayout.PREFERRED_SIZE, 155 | ) 156 | ) 157 | 158 | 159 | ) 160 | .addGroup( 161 | layout.createParallelGroup() 162 | .addComponent( 163 | self._extender.ignore304, 164 | GroupLayout.PREFERRED_SIZE, 165 | GroupLayout.PREFERRED_SIZE, 166 | GroupLayout.PREFERRED_SIZE, 167 | ) 168 | .addComponent( 169 | self._extender.prevent304, 170 | GroupLayout.PREFERRED_SIZE, 171 | GroupLayout.PREFERRED_SIZE, 172 | GroupLayout.PREFERRED_SIZE, 173 | ) 174 | .addComponent( 175 | self._extender.interceptRequestsfromRepeater, 176 | GroupLayout.PREFERRED_SIZE, 177 | GroupLayout.PREFERRED_SIZE, 178 | GroupLayout.PREFERRED_SIZE, 179 | ) 180 | .addComponent( 181 | self._extender.doUnauthorizedRequest, 182 | GroupLayout.PREFERRED_SIZE, 183 | GroupLayout.PREFERRED_SIZE, 184 | GroupLayout.PREFERRED_SIZE, 185 | ) 186 | .addComponent( 187 | self._extender.autoScroll, 188 | GroupLayout.PREFERRED_SIZE, 189 | GroupLayout.PREFERRED_SIZE, 190 | GroupLayout.PREFERRED_SIZE, 191 | ) 192 | .addComponent( 193 | self._extender.replaceQueryParam, 194 | GroupLayout.PREFERRED_SIZE, 195 | GroupLayout.PREFERRED_SIZE, 196 | GroupLayout.PREFERRED_SIZE, 197 | ) 198 | .addComponent( 199 | self._extender.saveHeadersButton, 200 | GroupLayout.PREFERRED_SIZE, 201 | GroupLayout.PREFERRED_SIZE, 202 | GroupLayout.PREFERRED_SIZE, 203 | ) 204 | .addComponent( 205 | self._extender.removeHeadersButton, 206 | GroupLayout.PREFERRED_SIZE, 207 | GroupLayout.PREFERRED_SIZE, 208 | GroupLayout.PREFERRED_SIZE, 209 | ) 210 | ) 211 | ) 212 | 213 | layout.setVerticalGroup( 214 | layout.createSequentialGroup() 215 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 216 | 217 | .addComponent( 218 | self._extender.startButton, 219 | GroupLayout.PREFERRED_SIZE, 220 | GroupLayout.PREFERRED_SIZE, 221 | GroupLayout.PREFERRED_SIZE, 222 | ) 223 | .addComponent( 224 | self._extender.ignore304, 225 | GroupLayout.PREFERRED_SIZE, 226 | GroupLayout.PREFERRED_SIZE, 227 | GroupLayout.PREFERRED_SIZE, 228 | ) 229 | ) 230 | .addComponent( 231 | self._extender.prevent304, 232 | GroupLayout.PREFERRED_SIZE, 233 | GroupLayout.PREFERRED_SIZE, 234 | GroupLayout.PREFERRED_SIZE, 235 | ) 236 | .addComponent( 237 | self._extender.interceptRequestsfromRepeater, 238 | GroupLayout.PREFERRED_SIZE, 239 | GroupLayout.PREFERRED_SIZE, 240 | GroupLayout.PREFERRED_SIZE, 241 | ) 242 | .addComponent( 243 | self._extender.doUnauthorizedRequest, 244 | GroupLayout.PREFERRED_SIZE, 245 | GroupLayout.PREFERRED_SIZE, 246 | GroupLayout.PREFERRED_SIZE, 247 | ) 248 | .addComponent( 249 | self._extender.replaceQueryParam, 250 | GroupLayout.PREFERRED_SIZE, 251 | GroupLayout.PREFERRED_SIZE, 252 | GroupLayout.PREFERRED_SIZE, 253 | ) 254 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 255 | .addComponent( 256 | self._extender.clearButton, 257 | GroupLayout.PREFERRED_SIZE, 258 | GroupLayout.PREFERRED_SIZE, 259 | GroupLayout.PREFERRED_SIZE, 260 | ) 261 | .addComponent( 262 | self._extender.autoScroll, 263 | GroupLayout.PREFERRED_SIZE, 264 | GroupLayout.PREFERRED_SIZE, 265 | GroupLayout.PREFERRED_SIZE, 266 | ) 267 | ) 268 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 269 | .addComponent( 270 | self._extender.savedHeadersTitlesCombo, 271 | GroupLayout.PREFERRED_SIZE, 272 | GroupLayout.PREFERRED_SIZE, 273 | GroupLayout.PREFERRED_SIZE, 274 | ) 275 | .addGroup(layout.createSequentialGroup() 276 | .addComponent( 277 | self._extender.saveHeadersButton, 278 | GroupLayout.PREFERRED_SIZE, 279 | GroupLayout.PREFERRED_SIZE, 280 | GroupLayout.PREFERRED_SIZE, 281 | ) 282 | .addComponent( 283 | self._extender.removeHeadersButton, 284 | GroupLayout.PREFERRED_SIZE, 285 | GroupLayout.PREFERRED_SIZE, 286 | GroupLayout.PREFERRED_SIZE, 287 | )) 288 | ) 289 | .addComponent( 290 | scrollReplaceString, 291 | GroupLayout.PREFERRED_SIZE, 292 | GroupLayout.PREFERRED_SIZE, 293 | GroupLayout.PREFERRED_SIZE, 294 | ) 295 | .addComponent( 296 | fromLastRequestLabel, 297 | GroupLayout.PREFERRED_SIZE, 298 | GroupLayout.PREFERRED_SIZE, 299 | GroupLayout.PREFERRED_SIZE, 300 | ) 301 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 302 | .addComponent( 303 | self._extender.fetchCookiesHeaderButton, 304 | GroupLayout.PREFERRED_SIZE, 305 | GroupLayout.PREFERRED_SIZE, 306 | GroupLayout.PREFERRED_SIZE, 307 | ) 308 | .addComponent( 309 | self._extender.fetchAuthorizationHeaderButton, 310 | GroupLayout.PREFERRED_SIZE, 311 | GroupLayout.PREFERRED_SIZE, 312 | GroupLayout.PREFERRED_SIZE, 313 | )) 314 | ) 315 | 316 | self._extender._cfg_splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT) 317 | self._extender._cfg_splitpane.setResizeWeight(0.5) 318 | self._extender._cfg_splitpane.setBounds(0, 0, 1000, 1000) 319 | self._extender._cfg_splitpane.setRightComponent(self._extender.filtersTabs) 320 | self._extender._cfg_splitpane.setLeftComponent(self.config_pnl) 321 | 322 | def startOrStop(self, event): 323 | if self._extender.startButton.getText() == "Autorize is off": 324 | self._extender.startButton.setText("Autorize is on") 325 | self._extender.startButton.setSelected(True) 326 | self._extender.intercept = 1 327 | else: 328 | self._extender.startButton.setText("Autorize is off") 329 | self._extender.startButton.setSelected(False) 330 | self._extender.intercept = 0 331 | 332 | def clearList(self, event): 333 | self._extender._lock.acquire() 334 | oldSize = self._extender._log.size() 335 | self._extender._log.clear() 336 | SwingUtilities.invokeLater(UpdateTableEDT(self._extender,"delete",0, oldSize - 1)) 337 | self._extender._lock.release() 338 | 339 | def replaceQueryHanlder(self, event): 340 | if self._extender.replaceQueryParam.isSelected(): 341 | self._extender.replaceString.setText("paramName=paramValue") 342 | else: 343 | self._extender.replaceString.setText(self.DEFUALT_REPLACE_TEXT) 344 | 345 | def saveHeaders(self, event): 346 | savedHeadersTitle = JOptionPane.showInputDialog("Please provide saved headers title:") 347 | self._extender.savedHeaders.append({'title': savedHeadersTitle, 'headers': self._extender.replaceString.getText()}) 348 | self._extender.savedHeadersTitlesCombo.setModel(DefaultComboBoxModel(self.getSavedHeadersTitles())) 349 | self._extender.savedHeadersTitlesCombo.getModel().setSelectedItem(savedHeadersTitle) 350 | 351 | def removeHeaders(self, event): 352 | model = self._extender.savedHeadersTitlesCombo.getModel() 353 | selectedItem = model.getSelectedItem() 354 | if selectedItem == "Temporary headers": 355 | return 356 | 357 | delObject = None 358 | for savedHeaderObj in self._extender.savedHeaders: 359 | if selectedItem == savedHeaderObj['title']: 360 | delObject = savedHeaderObj 361 | self._extender.savedHeaders.remove(delObject) 362 | model.removeElement(selectedItem) 363 | 364 | def getSavedHeadersTitles(self): 365 | titles = [] 366 | for savedHeaderObj in self._extender.savedHeaders: 367 | titles.append(savedHeaderObj['title']) 368 | return titles 369 | 370 | def fetchCookiesHeader(self, event): 371 | if self._extender.lastCookiesHeader: 372 | self._extender.replaceString.setText(self._extender.lastCookiesHeader) 373 | 374 | def fetchAuthorizationHeader(self, event): 375 | if self._extender.lastAuthorizationHeader: 376 | self._extender.replaceString.setText(self._extender.lastAuthorizationHeader) 377 | 378 | class SavedHeaderChange(ActionListener): 379 | def __init__(self, extender): 380 | self._extender = extender 381 | 382 | def actionPerformed(self, e): 383 | selectedTitle = self._extender.savedHeadersTitlesCombo.getSelectedItem() 384 | headers = [x for x in self._extender.savedHeaders if x['title'] == selectedTitle] 385 | self._extender.replaceString.setText(headers[0]['headers']) 386 | 387 | -------------------------------------------------------------------------------- /gui/table.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from java.awt import Color 5 | from java.lang import String 6 | from java.lang import Integer 7 | from java.lang import Runnable 8 | from javax.swing import JTable 9 | from javax.swing import JLabel 10 | from javax.swing import JPanel 11 | from javax.swing import RowFilter 12 | from javax.swing import JCheckBox 13 | from javax.swing import GroupLayout 14 | from javax.swing import ListSelectionModel 15 | from java.awt.event import MouseAdapter 16 | from java.awt.event import ItemListener 17 | from javax.swing.table import AbstractTableModel 18 | from javax.swing.event import ListSelectionListener 19 | 20 | from helpers.filters import expand, collapse 21 | 22 | class TableFilter(): 23 | def __init__(self, extender): 24 | self._extender = extender 25 | 26 | def draw(self): 27 | """ 28 | init show tab 29 | """ 30 | 31 | filterLModified = JLabel("Modified:") 32 | filterLModified.setBounds(10, 10, 100, 30) 33 | 34 | filterLUnauthenticated = JLabel("Unauthenticated:") 35 | filterLUnauthenticated.setBounds(250, 10, 100, 30) 36 | 37 | self._extender.showAuthBypassModified = JCheckBox(self._extender.BYPASSSED_STR) 38 | self._extender.showAuthBypassModified.setBounds(10, 35, 200, 30) 39 | self._extender.showAuthBypassModified.setSelected(True) 40 | self._extender.showAuthBypassModified.addItemListener(TabTableFilter(self._extender)) 41 | 42 | self._extender.showAuthPotentiallyEnforcedModified = JCheckBox("Is enforced???") 43 | self._extender.showAuthPotentiallyEnforcedModified.setBounds(10, 60, 200, 30) 44 | self._extender.showAuthPotentiallyEnforcedModified.setSelected(True) 45 | self._extender.showAuthPotentiallyEnforcedModified.addItemListener(TabTableFilter(self._extender)) 46 | 47 | self._extender.showAuthEnforcedModified = JCheckBox(self._extender.ENFORCED_STR) 48 | self._extender.showAuthEnforcedModified.setBounds(10, 85, 200, 30) 49 | self._extender.showAuthEnforcedModified.setSelected(True) 50 | self._extender.showAuthEnforcedModified.addItemListener(TabTableFilter(self._extender)) 51 | 52 | self._extender.showAuthBypassUnauthenticated = JCheckBox(self._extender.BYPASSSED_STR) 53 | self._extender.showAuthBypassUnauthenticated.setBounds(250, 35, 200, 30) 54 | self._extender.showAuthBypassUnauthenticated.setSelected(True) 55 | self._extender.showAuthBypassUnauthenticated.addItemListener(TabTableFilter(self._extender)) 56 | 57 | self._extender.showAuthPotentiallyEnforcedUnauthenticated = JCheckBox("Is enforced???") 58 | self._extender.showAuthPotentiallyEnforcedUnauthenticated.setBounds(250, 60, 200, 30) 59 | self._extender.showAuthPotentiallyEnforcedUnauthenticated.setSelected(True) 60 | self._extender.showAuthPotentiallyEnforcedUnauthenticated.addItemListener(TabTableFilter(self._extender)) 61 | 62 | self._extender.showAuthEnforcedUnauthenticated = JCheckBox(self._extender.ENFORCED_STR) 63 | self._extender.showAuthEnforcedUnauthenticated.setBounds(250, 85, 200, 30) 64 | self._extender.showAuthEnforcedUnauthenticated.setSelected(True) 65 | self._extender.showAuthEnforcedUnauthenticated.addItemListener(TabTableFilter(self._extender)) 66 | 67 | self._extender.showDisabledUnauthenticated = JCheckBox("Disabled") 68 | self._extender.showDisabledUnauthenticated.setBounds(250, 110, 200, 30) 69 | self._extender.showDisabledUnauthenticated.setSelected(True) 70 | self._extender.showDisabledUnauthenticated.addItemListener(TabTableFilter(self._extender)) 71 | 72 | self._extender.filterPnl = JPanel() 73 | layout = GroupLayout(self._extender.filterPnl) 74 | self._extender.filterPnl.setLayout(layout) 75 | layout.setAutoCreateGaps(True) 76 | layout.setAutoCreateContainerGaps(True) 77 | 78 | layout.setHorizontalGroup(layout.createSequentialGroup() 79 | .addGroup(layout.createParallelGroup() 80 | .addComponent( 81 | filterLModified, 82 | GroupLayout.PREFERRED_SIZE, 83 | GroupLayout.PREFERRED_SIZE, 84 | GroupLayout.PREFERRED_SIZE, 85 | ) 86 | .addComponent( 87 | self._extender.showAuthBypassModified, 88 | GroupLayout.PREFERRED_SIZE, 89 | GroupLayout.PREFERRED_SIZE, 90 | GroupLayout.PREFERRED_SIZE, 91 | ) 92 | .addComponent( 93 | self._extender.showAuthPotentiallyEnforcedModified, 94 | GroupLayout.PREFERRED_SIZE, 95 | GroupLayout.PREFERRED_SIZE, 96 | GroupLayout.PREFERRED_SIZE, 97 | ) 98 | .addComponent( 99 | self._extender.showAuthEnforcedModified, 100 | GroupLayout.PREFERRED_SIZE, 101 | GroupLayout.PREFERRED_SIZE, 102 | GroupLayout.PREFERRED_SIZE, 103 | ) 104 | ) 105 | .addGroup(layout.createParallelGroup() 106 | .addComponent( 107 | filterLUnauthenticated, 108 | GroupLayout.PREFERRED_SIZE, 109 | GroupLayout.PREFERRED_SIZE, 110 | GroupLayout.PREFERRED_SIZE, 111 | ) 112 | .addComponent( 113 | self._extender.showAuthBypassUnauthenticated, 114 | GroupLayout.PREFERRED_SIZE, 115 | GroupLayout.PREFERRED_SIZE, 116 | GroupLayout.PREFERRED_SIZE, 117 | ) 118 | .addComponent( 119 | self._extender.showAuthPotentiallyEnforcedUnauthenticated, 120 | GroupLayout.PREFERRED_SIZE, 121 | GroupLayout.PREFERRED_SIZE, 122 | GroupLayout.PREFERRED_SIZE, 123 | ) 124 | .addComponent( 125 | self._extender.showAuthEnforcedUnauthenticated, 126 | GroupLayout.PREFERRED_SIZE, 127 | GroupLayout.PREFERRED_SIZE, 128 | GroupLayout.PREFERRED_SIZE, 129 | ) 130 | .addComponent( 131 | self._extender.showDisabledUnauthenticated, 132 | GroupLayout.PREFERRED_SIZE, 133 | GroupLayout.PREFERRED_SIZE, 134 | GroupLayout.PREFERRED_SIZE, 135 | ) 136 | ) 137 | ) 138 | 139 | 140 | layout.setVerticalGroup(layout.createSequentialGroup() 141 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 142 | .addComponent( 143 | filterLModified, 144 | GroupLayout.PREFERRED_SIZE, 145 | GroupLayout.PREFERRED_SIZE, 146 | GroupLayout.PREFERRED_SIZE, 147 | ) 148 | .addComponent( 149 | filterLUnauthenticated, 150 | GroupLayout.PREFERRED_SIZE, 151 | GroupLayout.PREFERRED_SIZE, 152 | GroupLayout.PREFERRED_SIZE, 153 | ) 154 | ) 155 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 156 | .addGroup(layout.createSequentialGroup() 157 | .addComponent( 158 | self._extender.showAuthBypassModified, 159 | GroupLayout.PREFERRED_SIZE, 160 | GroupLayout.PREFERRED_SIZE, 161 | GroupLayout.PREFERRED_SIZE, 162 | ) 163 | .addComponent( 164 | self._extender.showAuthPotentiallyEnforcedModified, 165 | GroupLayout.PREFERRED_SIZE, 166 | GroupLayout.PREFERRED_SIZE, 167 | GroupLayout.PREFERRED_SIZE, 168 | ) 169 | .addComponent( 170 | self._extender.showAuthEnforcedModified, 171 | GroupLayout.PREFERRED_SIZE, 172 | GroupLayout.PREFERRED_SIZE, 173 | GroupLayout.PREFERRED_SIZE, 174 | ) 175 | ) 176 | .addGroup(layout.createSequentialGroup() 177 | .addComponent( 178 | self._extender.showAuthBypassUnauthenticated, 179 | GroupLayout.PREFERRED_SIZE, 180 | GroupLayout.PREFERRED_SIZE, 181 | GroupLayout.PREFERRED_SIZE, 182 | ) 183 | .addComponent( 184 | self._extender.showAuthPotentiallyEnforcedUnauthenticated, 185 | GroupLayout.PREFERRED_SIZE, 186 | GroupLayout.PREFERRED_SIZE, 187 | GroupLayout.PREFERRED_SIZE, 188 | ) 189 | .addComponent( 190 | self._extender.showAuthEnforcedUnauthenticated, 191 | GroupLayout.PREFERRED_SIZE, 192 | GroupLayout.PREFERRED_SIZE, 193 | GroupLayout.PREFERRED_SIZE, 194 | ) 195 | .addComponent( 196 | self._extender.showDisabledUnauthenticated, 197 | GroupLayout.PREFERRED_SIZE, 198 | GroupLayout.PREFERRED_SIZE, 199 | GroupLayout.PREFERRED_SIZE, 200 | ) 201 | ) 202 | ) 203 | ) 204 | 205 | class TabTableFilter(ItemListener): 206 | def __init__(self, extender): 207 | self._extender = extender 208 | 209 | def itemStateChanged(self, e): 210 | self._extender.tableSorter.sort() 211 | 212 | class TableModel(AbstractTableModel): 213 | def __init__(self, extender): 214 | self._extender = extender 215 | 216 | def removeRows(self, rows): 217 | rows.sort(reverse=True) 218 | for row in rows: 219 | self._extender._log.pop(row) 220 | self.fireTableDataChanged() 221 | 222 | def getRowCount(self): 223 | try: 224 | return self._extender._log.size() 225 | except: 226 | return 0 227 | 228 | def getColumnCount(self): 229 | return 8 230 | 231 | def getColumnName(self, columnIndex): 232 | data = ['ID','Method', 'URL', 'Orig. Len', 'Modif. Len', "Unauth. Len", 233 | "Authz. Status", "Unauth. Status"] 234 | try: 235 | return data[columnIndex] 236 | except IndexError: 237 | return "" 238 | 239 | def getColumnClass(self, columnIndex): 240 | data = [Integer, String, String, Integer, Integer, Integer, String, String] 241 | try: 242 | return data[columnIndex] 243 | except IndexError: 244 | return "" 245 | 246 | def getValueAt(self, rowIndex, columnIndex): 247 | logEntry = self._extender._log.get(rowIndex) 248 | if columnIndex == 0: 249 | return logEntry._id 250 | if columnIndex == 1: 251 | return logEntry._method 252 | if columnIndex == 2: 253 | return logEntry._url.toString() 254 | if columnIndex == 3: 255 | response = logEntry._originalrequestResponse.getResponse() 256 | return len(logEntry._originalrequestResponse.getResponse()) - self._extender._helpers.analyzeResponse(response).getBodyOffset() 257 | if columnIndex == 4: 258 | response = logEntry._requestResponse.getResponse() 259 | return len(logEntry._requestResponse.getResponse()) - self._extender._helpers.analyzeResponse(response).getBodyOffset() 260 | if columnIndex == 5: 261 | if logEntry._unauthorizedRequestResponse is not None: 262 | response = logEntry._unauthorizedRequestResponse.getResponse() 263 | return len(logEntry._unauthorizedRequestResponse.getResponse()) - self._extender._helpers.analyzeResponse(response).getBodyOffset() 264 | else: 265 | return 0 266 | if columnIndex == 6: 267 | return logEntry._enfocementStatus 268 | if columnIndex == 7: 269 | return logEntry._enfocementStatusUnauthorized 270 | return "" 271 | 272 | class TableSelectionListener(ListSelectionListener): 273 | """Class Responsible for the multi-row deletion""" 274 | def __init__(self, extender): 275 | self._extender = extender 276 | 277 | def valueChanged(self, e): 278 | rows = [i for i in self._table.getSelectedRows()] 279 | self._extender.tableModel.removeRows(rows) 280 | 281 | class Table(JTable): 282 | def __init__(self, extender): 283 | self._extender = extender 284 | self._extender.tableModel = TableModel(extender) 285 | self.setModel(self._extender.tableModel) 286 | self.addMouseListener(Mouseclick(self._extender)) 287 | self.getColumnModel().getColumn(0).setPreferredWidth(450) 288 | self.setRowSelectionAllowed(True) 289 | # Enables multi-row selection 290 | self.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) 291 | 292 | def prepareRenderer(self, renderer, row, col): 293 | comp = JTable.prepareRenderer(self, renderer, row, col) 294 | value = self._extender.tableModel.getValueAt(self._extender.logTable.convertRowIndexToModel(row), col) 295 | if col == 6 or col == 7: 296 | if value == self._extender.BYPASSSED_STR: 297 | comp.setBackground(Color(255, 153, 153)) 298 | comp.setForeground(Color.BLACK) 299 | elif value == self._extender.IS_ENFORCED_STR: 300 | comp.setBackground(Color(255, 204, 153)) 301 | comp.setForeground(Color.BLACK) 302 | elif value == self._extender.ENFORCED_STR: 303 | comp.setBackground(Color(204, 255, 153)) 304 | comp.setForeground(Color.BLACK) 305 | else: 306 | comp.setForeground(Color.BLACK) 307 | comp.setBackground(Color.WHITE) 308 | 309 | selectedRows = self._extender.logTable.getSelectedRows() 310 | if row in selectedRows: 311 | comp.setBackground(Color(201, 215, 255)) 312 | comp.setForeground(Color.BLACK) 313 | 314 | return comp 315 | 316 | def changeSelection(self, row, col, toggle, extend): 317 | # show the log entry for the selected row 318 | logEntry = self._extender._log.get(self._extender.logTable.convertRowIndexToModel(row)) 319 | self._extender._requestViewer.setMessage(logEntry._requestResponse.getRequest(), True) 320 | self._extender._responseViewer.setMessage(logEntry._requestResponse.getResponse(), False) 321 | self._extender._originalrequestViewer.setMessage(logEntry._originalrequestResponse.getRequest(), True) 322 | self._extender._originalresponseViewer.setMessage(logEntry._originalrequestResponse.getResponse(), False) 323 | 324 | if logEntry._unauthorizedRequestResponse is not None: 325 | self._extender._unauthorizedrequestViewer.setMessage(logEntry._unauthorizedRequestResponse.getRequest(), True) 326 | self._extender._unauthorizedresponseViewer.setMessage(logEntry._unauthorizedRequestResponse.getResponse(), False) 327 | else: 328 | self._extender._unauthorizedrequestViewer.setMessage("Request disabled", True) 329 | self._extender._unauthorizedresponseViewer.setMessage("Response disabled", False) 330 | 331 | self._extender._currentlyDisplayedItem = logEntry 332 | 333 | if col == 3: 334 | collapse(self._extender, self._extender.modified_requests_tabs) 335 | collapse(self._extender, self._extender.unauthenticated_requests_tabs) 336 | expand(self._extender, self._extender.original_requests_tabs) 337 | elif col == 4 or col == 6: 338 | collapse(self._extender, self._extender.original_requests_tabs) 339 | collapse(self._extender, self._extender.unauthenticated_requests_tabs) 340 | expand(self._extender, self._extender.modified_requests_tabs) 341 | elif col == 5 or col == 7: 342 | collapse(self._extender, self._extender.original_requests_tabs) 343 | collapse(self._extender, self._extender.modified_requests_tabs) 344 | expand(self._extender, self._extender.unauthenticated_requests_tabs) 345 | else: 346 | collapse(self._extender, self._extender.original_requests_tabs) 347 | collapse(self._extender, self._extender.modified_requests_tabs) 348 | collapse(self._extender, self._extender.unauthenticated_requests_tabs) 349 | 350 | JTable.changeSelection(self, row, col, toggle, extend) 351 | return 352 | 353 | class LogEntry: 354 | def __init__(self, id, requestResponse, method, url, originalrequestResponse, enforcementStatus, unauthorizedRequestResponse, enforcementStatusUnauthorized): 355 | self._id = id 356 | self._requestResponse = requestResponse 357 | self._originalrequestResponse = originalrequestResponse 358 | self._method = method 359 | self._url = url 360 | self._enfocementStatus = enforcementStatus 361 | self._unauthorizedRequestResponse = unauthorizedRequestResponse 362 | self._enfocementStatusUnauthorized = enforcementStatusUnauthorized 363 | return 364 | 365 | class Mouseclick(MouseAdapter): 366 | def __init__(self, extender): 367 | self._extender = extender 368 | 369 | def mouseReleased(self, evt): 370 | if evt.button == 3: 371 | self._extender.menu.show(evt.getComponent(), evt.getX(), evt.getY()) 372 | 373 | class TableRowFilter(RowFilter): 374 | def __init__(self, extender): 375 | self._extender = extender 376 | 377 | def include(self, entry): 378 | if self._extender.showAuthBypassModified.isSelected() and self._extender.BYPASSSED_STR == entry.getValue(6): 379 | return True 380 | elif self._extender.showAuthPotentiallyEnforcedModified.isSelected() and self._extender.IS_ENFORCED_STR == entry.getValue(6): 381 | return True 382 | elif self._extender.showAuthEnforcedModified.isSelected() and self._extender.ENFORCED_STR == entry.getValue(6): 383 | return True 384 | elif self._extender.showAuthBypassUnauthenticated.isSelected() and self._extender.BYPASSSED_STR == entry.getValue(7): 385 | return True 386 | elif self._extender.showAuthPotentiallyEnforcedUnauthenticated.isSelected() and self._extender.IS_ENFORCED_STR == entry.getValue(7): 387 | return True 388 | elif self._extender.showAuthEnforcedUnauthenticated.isSelected() and self._extender.ENFORCED_STR == entry.getValue(7): 389 | return True 390 | elif self._extender.showDisabledUnauthenticated.isSelected() and "Disabled" == entry.getValue(7): 391 | return True 392 | else: 393 | return False 394 | 395 | class UpdateTableEDT(Runnable): 396 | def __init__(self,extender,action,firstRow,lastRow): 397 | self._extender=extender 398 | self._action=action 399 | self._firstRow=firstRow 400 | self._lastRow=lastRow 401 | 402 | def run(self): 403 | if self._action == "insert": 404 | self._extender.tableModel.fireTableRowsInserted(self._firstRow, self._lastRow) 405 | elif self._action == "update": 406 | self._extender.tableModel.fireTableRowsUpdated(self._firstRow, self._lastRow) 407 | elif self._action == "delete": 408 | self._extender.tableModel.fireTableRowsDeleted(self._firstRow, self._lastRow) 409 | else: 410 | print("Invalid action in UpdateTableEDT") 411 | 412 | -------------------------------------------------------------------------------- /gui/enforcement_detector.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | sys.path.append("..") 6 | 7 | from javax.swing import JLabel 8 | from javax.swing import JList 9 | from javax.swing import JPanel 10 | from javax.swing import JButton 11 | from javax.swing import JTextArea 12 | from javax.swing import JComboBox 13 | from javax.swing import GroupLayout 14 | from javax.swing import JScrollPane 15 | from javax.swing import DefaultListModel 16 | from javax.swing.border import LineBorder 17 | 18 | from helpers.filters import addFilterHelper, delFilterHelper, modFilterHelper 19 | 20 | class EnforcementDetectors(): 21 | def __init__(self, extender): 22 | self._extender = extender 23 | 24 | def draw(self): 25 | """ 26 | init enforcement detector tab 27 | """ 28 | 29 | EDLType = JLabel("Type:") 30 | EDLType.setBounds(10, 10, 140, 30) 31 | 32 | EDLContent = JLabel("Content:") 33 | EDLContent.setBounds(10, 50, 140, 30) 34 | 35 | EDLabelList = JLabel("Filter List:") 36 | EDLabelList.setBounds(10, 165, 140, 30) 37 | 38 | EDStrings = [ 39 | "Headers (simple string): (enforced message headers contain)", 40 | "Headers NOT (simple string): (enforced message headers NOT contain)", 41 | "Headers (regex): (enforced message headers contain)", 42 | "Headers NOT (regex): (enforced message headers NOT contain)", 43 | "Body (simple string): (enforced message body contains)", 44 | "Body NOT (simple string): (enforced message body NOT contains)", 45 | "Body (regex): (enforced message body contains)", 46 | "Body NOT (regex): (enforced message body NOT contains)", 47 | "Full response (simple string): (enforced message contains)", 48 | "Full response NOT (simple string): (enforced message NOT contains)", 49 | "Full response (regex): (enforced message contains)", 50 | "Full response NOT (regex): (enforced message NOT contains)", 51 | "Full response length: (of enforced response)", 52 | "Full response NOT length: (of enforced response)", 53 | "Status code equals: (numbers only)", 54 | "Status code NOT equals: (numbers only)" 55 | ] 56 | self._extender.EDType = JComboBox(EDStrings) 57 | self._extender.EDType.setBounds(80, 10, 430, 30) 58 | 59 | self._extender.EDText = JTextArea("", 5, 30) 60 | 61 | scrollEDText = JScrollPane(self._extender.EDText) 62 | scrollEDText.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 63 | scrollEDText.setBounds(80, 50, 300, 110) 64 | 65 | self._extender.EDModel = DefaultListModel() 66 | self._extender.EDList = JList(self._extender.EDModel) 67 | self._extender.EDList.setPrototypeCellValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") 68 | scrollEDList = JScrollPane(self._extender.EDList) 69 | scrollEDList.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 70 | scrollEDList.setBounds(80, 175, 300, 110) 71 | 72 | self._extender.EDAdd = JButton("Add filter", actionPerformed=self.addEDFilter) 73 | self._extender.EDAdd.setBounds(390, 85, 120, 30) 74 | self._extender.EDDel = JButton("Remove filter", actionPerformed=self.delEDFilter) 75 | self._extender.EDDel.setBounds(390, 210, 120, 30) 76 | self._extender.EDMod = JButton("Modify filter", actionPerformed=self.modEDFilter) 77 | self._extender.EDMod.setBounds(390, 250, 120, 30) 78 | 79 | AndOrStrings = ["And", "Or"] 80 | self._extender.AndOrType = JComboBox(AndOrStrings) 81 | self._extender.AndOrType.setBounds(390, 170, 120, 30) 82 | 83 | self._extender.EDPnl = JPanel() 84 | layout = GroupLayout(self._extender.EDPnl) 85 | self._extender.EDPnl.setLayout(layout) 86 | layout.setAutoCreateGaps(True) 87 | layout.setAutoCreateContainerGaps(True) 88 | 89 | layout.setHorizontalGroup( 90 | layout.createSequentialGroup() 91 | .addGroup( 92 | layout.createParallelGroup() 93 | .addComponent( 94 | EDLType, 95 | GroupLayout.PREFERRED_SIZE, 96 | GroupLayout.PREFERRED_SIZE, 97 | GroupLayout.PREFERRED_SIZE, 98 | ) 99 | .addComponent( 100 | EDLContent, 101 | GroupLayout.PREFERRED_SIZE, 102 | GroupLayout.PREFERRED_SIZE, 103 | GroupLayout.PREFERRED_SIZE, 104 | ) 105 | .addComponent( 106 | EDLabelList, 107 | GroupLayout.PREFERRED_SIZE, 108 | GroupLayout.PREFERRED_SIZE, 109 | GroupLayout.PREFERRED_SIZE, 110 | ) 111 | ) 112 | .addGroup( 113 | layout.createParallelGroup() 114 | .addComponent( 115 | self._extender.EDType, 116 | GroupLayout.PREFERRED_SIZE, 117 | GroupLayout.PREFERRED_SIZE, 118 | GroupLayout.PREFERRED_SIZE, 119 | ) 120 | .addComponent( 121 | scrollEDText, 122 | GroupLayout.PREFERRED_SIZE, 123 | GroupLayout.PREFERRED_SIZE, 124 | GroupLayout.PREFERRED_SIZE, 125 | ) 126 | .addComponent( 127 | scrollEDList, 128 | GroupLayout.PREFERRED_SIZE, 129 | GroupLayout.PREFERRED_SIZE, 130 | GroupLayout.PREFERRED_SIZE, 131 | ) 132 | .addComponent( 133 | self._extender.EDAdd, 134 | GroupLayout.PREFERRED_SIZE, 135 | GroupLayout.PREFERRED_SIZE, 136 | GroupLayout.PREFERRED_SIZE, 137 | ) 138 | .addComponent( 139 | self._extender.AndOrType, 140 | GroupLayout.PREFERRED_SIZE, 141 | GroupLayout.PREFERRED_SIZE, 142 | GroupLayout.PREFERRED_SIZE, 143 | ) 144 | .addComponent( 145 | self._extender.EDDel, 146 | GroupLayout.PREFERRED_SIZE, 147 | GroupLayout.PREFERRED_SIZE, 148 | GroupLayout.PREFERRED_SIZE, 149 | ) 150 | .addComponent( 151 | self._extender.EDMod, 152 | GroupLayout.PREFERRED_SIZE, 153 | GroupLayout.PREFERRED_SIZE, 154 | GroupLayout.PREFERRED_SIZE, 155 | ) 156 | ) 157 | ) 158 | 159 | layout.setVerticalGroup( 160 | layout.createSequentialGroup() 161 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 162 | .addComponent( 163 | EDLType, 164 | GroupLayout.PREFERRED_SIZE, 165 | GroupLayout.PREFERRED_SIZE, 166 | GroupLayout.PREFERRED_SIZE, 167 | ) 168 | .addComponent( 169 | self._extender.EDType, 170 | GroupLayout.PREFERRED_SIZE, 171 | GroupLayout.PREFERRED_SIZE, 172 | GroupLayout.PREFERRED_SIZE, 173 | ) 174 | ) 175 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 176 | .addComponent( 177 | EDLContent, 178 | GroupLayout.PREFERRED_SIZE, 179 | GroupLayout.PREFERRED_SIZE, 180 | GroupLayout.PREFERRED_SIZE, 181 | ) 182 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 183 | .addComponent( 184 | scrollEDText, 185 | GroupLayout.PREFERRED_SIZE, 186 | GroupLayout.PREFERRED_SIZE, 187 | GroupLayout.PREFERRED_SIZE, 188 | ) 189 | 190 | ) 191 | ) 192 | .addComponent( 193 | self._extender.EDAdd, 194 | GroupLayout.PREFERRED_SIZE, 195 | GroupLayout.PREFERRED_SIZE, 196 | GroupLayout.PREFERRED_SIZE, 197 | ) 198 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 199 | .addComponent( 200 | EDLabelList, 201 | GroupLayout.PREFERRED_SIZE, 202 | GroupLayout.PREFERRED_SIZE, 203 | GroupLayout.PREFERRED_SIZE, 204 | ) 205 | .addComponent( 206 | self._extender.AndOrType, 207 | GroupLayout.PREFERRED_SIZE, 208 | GroupLayout.PREFERRED_SIZE, 209 | GroupLayout.PREFERRED_SIZE, 210 | ) 211 | ) 212 | .addComponent( 213 | scrollEDList, 214 | GroupLayout.PREFERRED_SIZE, 215 | GroupLayout.PREFERRED_SIZE, 216 | GroupLayout.PREFERRED_SIZE, 217 | ) 218 | .addComponent( 219 | self._extender.EDDel, 220 | GroupLayout.PREFERRED_SIZE, 221 | GroupLayout.PREFERRED_SIZE, 222 | GroupLayout.PREFERRED_SIZE, 223 | ) 224 | .addComponent( 225 | self._extender.EDMod, 226 | GroupLayout.PREFERRED_SIZE, 227 | GroupLayout.PREFERRED_SIZE, 228 | GroupLayout.PREFERRED_SIZE, 229 | ) 230 | ) 231 | 232 | 233 | def draw_unauthenticated(self): 234 | """ init enforcement detector tab 235 | """ 236 | 237 | EDLType = JLabel("Type:") 238 | EDLType.setBounds(10, 10, 140, 30) 239 | 240 | EDLContent = JLabel("Content:") 241 | EDLContent.setBounds(10, 50, 140, 30) 242 | 243 | EDLabelList = JLabel("Filter List:") 244 | EDLabelList.setBounds(10, 165, 140, 30) 245 | 246 | EDStrings = [ 247 | "Headers (simple string): (enforced message headers contain)", 248 | "Headers NOT (simple string): (enforced message headers NOT contain)", 249 | "Headers (regex): (enforced message headers contain)", 250 | "Headers NOT (regex): (enforced message headers NOT contain)", 251 | "Body (simple string): (enforced message body contains)", 252 | "Body NOT (simple string): (enforced message body NOT contains)", 253 | "Body (regex): (enforced message body contains)", 254 | "Body NOT (regex): (enforced message body NOT contains)", 255 | "Full response (simple string): (enforced message contains)", 256 | "Full response NOT (simple string): (enforced message NOT contains)", 257 | "Full response (regex): (enforced message contains)", 258 | "Full response NOT (regex): (enforced message NOT contains)", 259 | "Full response length: (of enforced response)", 260 | "Full response NOT length: (of enforced response)", 261 | "Status code equals: (numbers only)", 262 | "Status code NOT equals: (numbers only)" 263 | ] 264 | self._extender.EDTypeUnauth = JComboBox(EDStrings) 265 | self._extender.EDTypeUnauth.setBounds(80, 10, 430, 30) 266 | 267 | self._extender.EDTextUnauth = JTextArea("", 5, 30) 268 | 269 | scrollEDTextUnauth = JScrollPane(self._extender.EDTextUnauth) 270 | scrollEDTextUnauth.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 271 | scrollEDTextUnauth.setBounds(80, 50, 300, 110) 272 | 273 | self._extender.EDModelUnauth = DefaultListModel() 274 | self._extender.EDListUnauth = JList(self._extender.EDModelUnauth) 275 | self._extender.EDListUnauth.setPrototypeCellValue("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") 276 | scrollEDListUnauth = JScrollPane(self._extender.EDListUnauth) 277 | scrollEDListUnauth.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) 278 | scrollEDListUnauth.setBounds(80, 175, 300, 110) 279 | 280 | self._extender.EDAddUnauth = JButton("Add filter", 281 | actionPerformed=self.addEDFilterUnauth) 282 | self._extender.EDAddUnauth.setBounds(390, 85, 120, 30) 283 | self._extender.EDDelUnauth = JButton("Remove filter", 284 | actionPerformed=self.delEDFilterUnauth) 285 | self._extender.EDDelUnauth.setBounds(390, 210, 120, 30) 286 | self._extender.EDModUnauth = JButton("Modify filter", 287 | actionPerformed=self.modEDFilterUnauth) 288 | self._extender.EDModUnauth.setBounds(390, 250, 120, 30) 289 | 290 | AndOrStrings = ["And", "Or"] 291 | self._extender.AndOrTypeUnauth = JComboBox(AndOrStrings) 292 | self._extender.AndOrTypeUnauth.setBounds(390, 170, 120, 30) 293 | 294 | self._extender.EDPnlUnauth = JPanel() 295 | layout = GroupLayout(self._extender.EDPnlUnauth) 296 | self._extender.EDPnlUnauth.setLayout(layout) 297 | layout.setAutoCreateGaps(True) 298 | layout.setAutoCreateContainerGaps(True) 299 | 300 | layout.setHorizontalGroup( 301 | layout.createSequentialGroup() 302 | .addGroup( 303 | layout.createParallelGroup() 304 | .addComponent( 305 | EDLType, 306 | GroupLayout.PREFERRED_SIZE, 307 | GroupLayout.PREFERRED_SIZE, 308 | GroupLayout.PREFERRED_SIZE, 309 | ) 310 | .addComponent( 311 | EDLContent, 312 | GroupLayout.PREFERRED_SIZE, 313 | GroupLayout.PREFERRED_SIZE, 314 | GroupLayout.PREFERRED_SIZE, 315 | ) 316 | .addComponent( 317 | EDLabelList, 318 | GroupLayout.PREFERRED_SIZE, 319 | GroupLayout.PREFERRED_SIZE, 320 | GroupLayout.PREFERRED_SIZE, 321 | ) 322 | ) 323 | .addGroup( 324 | layout.createParallelGroup() 325 | .addComponent( 326 | self._extender.EDTypeUnauth, 327 | GroupLayout.PREFERRED_SIZE, 328 | GroupLayout.PREFERRED_SIZE, 329 | GroupLayout.PREFERRED_SIZE, 330 | ) 331 | .addComponent( 332 | scrollEDTextUnauth, 333 | GroupLayout.PREFERRED_SIZE, 334 | GroupLayout.PREFERRED_SIZE, 335 | GroupLayout.PREFERRED_SIZE, 336 | ) 337 | .addComponent( 338 | scrollEDListUnauth, 339 | GroupLayout.PREFERRED_SIZE, 340 | GroupLayout.PREFERRED_SIZE, 341 | GroupLayout.PREFERRED_SIZE, 342 | ) 343 | .addComponent( 344 | self._extender.EDAddUnauth, 345 | GroupLayout.PREFERRED_SIZE, 346 | GroupLayout.PREFERRED_SIZE, 347 | GroupLayout.PREFERRED_SIZE, 348 | ) 349 | .addComponent( 350 | self._extender.AndOrTypeUnauth, 351 | GroupLayout.PREFERRED_SIZE, 352 | GroupLayout.PREFERRED_SIZE, 353 | GroupLayout.PREFERRED_SIZE, 354 | ) 355 | .addComponent( 356 | self._extender.EDDelUnauth, 357 | GroupLayout.PREFERRED_SIZE, 358 | GroupLayout.PREFERRED_SIZE, 359 | GroupLayout.PREFERRED_SIZE, 360 | ) 361 | .addComponent( 362 | self._extender.EDModUnauth, 363 | GroupLayout.PREFERRED_SIZE, 364 | GroupLayout.PREFERRED_SIZE, 365 | GroupLayout.PREFERRED_SIZE, 366 | ) 367 | ) 368 | ) 369 | 370 | 371 | 372 | layout.setVerticalGroup( 373 | layout.createSequentialGroup() 374 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 375 | .addComponent( 376 | EDLType, 377 | GroupLayout.PREFERRED_SIZE, 378 | GroupLayout.PREFERRED_SIZE, 379 | GroupLayout.PREFERRED_SIZE, 380 | ) 381 | .addComponent( 382 | self._extender.EDTypeUnauth, 383 | GroupLayout.PREFERRED_SIZE, 384 | GroupLayout.PREFERRED_SIZE, 385 | GroupLayout.PREFERRED_SIZE, 386 | ) 387 | ) 388 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 389 | .addComponent( 390 | EDLContent, 391 | GroupLayout.PREFERRED_SIZE, 392 | GroupLayout.PREFERRED_SIZE, 393 | GroupLayout.PREFERRED_SIZE, 394 | ) 395 | .addComponent( 396 | scrollEDTextUnauth, 397 | GroupLayout.PREFERRED_SIZE, 398 | GroupLayout.PREFERRED_SIZE, 399 | GroupLayout.PREFERRED_SIZE, 400 | ) 401 | ) 402 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 403 | .addComponent( 404 | self._extender.EDAddUnauth, 405 | GroupLayout.PREFERRED_SIZE, 406 | GroupLayout.PREFERRED_SIZE, 407 | GroupLayout.PREFERRED_SIZE, 408 | ) 409 | ) 410 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 411 | .addComponent( 412 | EDLabelList, 413 | GroupLayout.PREFERRED_SIZE, 414 | GroupLayout.PREFERRED_SIZE, 415 | GroupLayout.PREFERRED_SIZE, 416 | ) 417 | .addComponent( 418 | self._extender.AndOrTypeUnauth, 419 | GroupLayout.PREFERRED_SIZE, 420 | GroupLayout.PREFERRED_SIZE, 421 | GroupLayout.PREFERRED_SIZE, 422 | ) 423 | ) 424 | .addComponent( 425 | scrollEDListUnauth, 426 | GroupLayout.PREFERRED_SIZE, 427 | GroupLayout.PREFERRED_SIZE, 428 | GroupLayout.PREFERRED_SIZE, 429 | ) 430 | .addComponent( 431 | self._extender.EDDelUnauth, 432 | GroupLayout.PREFERRED_SIZE, 433 | GroupLayout.PREFERRED_SIZE, 434 | GroupLayout.PREFERRED_SIZE, 435 | ) 436 | .addComponent( 437 | self._extender.EDModUnauth, 438 | GroupLayout.PREFERRED_SIZE, 439 | GroupLayout.PREFERRED_SIZE, 440 | GroupLayout.PREFERRED_SIZE, 441 | ) 442 | ) 443 | 444 | def addEDFilter(self, event): 445 | addFilterHelper(self._extender.EDType, self._extender.EDModel, self._extender.EDText) 446 | 447 | def delEDFilter(self, event): 448 | delFilterHelper(self._extender.EDList) 449 | 450 | def modEDFilter(self, event): 451 | modFilterHelper(self._extender.EDList, self._extender.EDType, self._extender.EDText) 452 | 453 | def addEDFilterUnauth(self, event): 454 | addFilterHelper(self._extender.EDTypeUnauth, self._extender.EDModelUnauth, self._extender.EDTextUnauth) 455 | 456 | def delEDFilterUnauth(self, event): 457 | delFilterHelper(self._extender.EDListUnauth) 458 | 459 | def modEDFilterUnauth(self, event): 460 | modFilterHelper(self._extender.EDListUnauth, self._extender.EDTypeUnauth, self._extender.EDTextUnauth) 461 | -------------------------------------------------------------------------------- /gui/export.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | sys.path.append("..") 6 | 7 | from java.io import File 8 | from java.awt import Font 9 | from javax.swing import JLabel 10 | from javax.swing import JLabel 11 | from javax.swing import JPanel 12 | from javax.swing import JFrame 13 | from javax.swing import JButton 14 | from javax.swing import JCheckBox 15 | from javax.swing import JComboBox 16 | from javax.swing import GroupLayout 17 | from javax.swing import JFileChooser 18 | from java.awt.event import ItemListener 19 | 20 | from save_restore import SaveRestore 21 | 22 | class RemoveDups(ItemListener): 23 | def __init__(self, extender): 24 | self._extender = extender 25 | 26 | def itemStateChanged(self, e): 27 | return True 28 | 29 | class Export(): 30 | def __init__(self, extender): 31 | self._extender = extender 32 | self.BYPASSSED_STR = extender.BYPASSSED_STR 33 | self.ENFORCED_STR = extender.ENFORCED_STR 34 | self.IS_ENFORCED_STR = extender.IS_ENFORCED_STR 35 | self._log = extender._log 36 | self.save_restore = SaveRestore(extender) 37 | 38 | def draw(self): 39 | """ init Save/Restore 40 | """ 41 | 42 | exportLabel = JLabel("Export:") 43 | exportLabel.setBounds(10, 10, 100, 30) 44 | labelFont = exportLabel.getFont() 45 | boldFont = Font(labelFont.getFontName(), Font.BOLD, labelFont.getSize()) 46 | exportLabel.setFont(boldFont) 47 | 48 | exportLType = JLabel("File Type:") 49 | exportLType.setBounds(10, 50, 100, 30) 50 | 51 | exportFileTypes = ["HTML", "CSV"] 52 | self.exportType = JComboBox(exportFileTypes) 53 | self.exportType.setBounds(100, 50, 200, 30) 54 | 55 | exportES = ["All Statuses", "As table filter", 56 | self._extender.BYPASSSED_STR, 57 | self._extender.IS_ENFORCED_STR, 58 | self._extender.ENFORCED_STR] 59 | self.exportES = JComboBox(exportES) 60 | self.exportES.setBounds(100, 90, 200, 30) 61 | 62 | exportLES = JLabel("Statuses:") 63 | exportLES.setBounds(10, 90, 100, 30) 64 | 65 | self.removeDuplicates = JCheckBox("Remove Duplicates") 66 | self.removeDuplicates.setBounds(8, 120, 300, 30) 67 | self.removeDuplicates.setSelected(True) 68 | self.removeDuplicates.addItemListener(RemoveDups(self._extender)) 69 | 70 | self.exportButton = JButton("Export", 71 | actionPerformed=self.export) 72 | self.exportButton.setBounds(390, 50, 100, 30) 73 | 74 | saveRestoreLabel = JLabel("State (incl. Configuration):") 75 | saveRestoreLabel.setBounds(10, 160, 250, 30) 76 | saveRestoreLabel.setFont(boldFont) 77 | 78 | self.saveStateButton = JButton("Save", 79 | actionPerformed=self.saveStateAction) 80 | self.saveStateButton.setBounds(10, 200, 100, 30) 81 | 82 | self.restoreStateButton = JButton("Restore", 83 | actionPerformed=self.restoreStateAction) 84 | self.restoreStateButton.setBounds(390, 200, 100, 30) 85 | 86 | self._extender.exportPnl = JPanel() 87 | layout = GroupLayout(self._extender.exportPnl) 88 | self._extender.exportPnl.setLayout(layout) 89 | layout.setAutoCreateGaps(True) 90 | layout.setAutoCreateContainerGaps(True) 91 | 92 | layout.setHorizontalGroup(layout.createSequentialGroup() 93 | .addGroup(layout.createParallelGroup() 94 | .addComponent( 95 | exportLabel, 96 | GroupLayout.PREFERRED_SIZE, 97 | GroupLayout.PREFERRED_SIZE, 98 | GroupLayout.PREFERRED_SIZE, 99 | ) 100 | .addComponent( 101 | exportLType, 102 | GroupLayout.PREFERRED_SIZE, 103 | GroupLayout.PREFERRED_SIZE, 104 | GroupLayout.PREFERRED_SIZE, 105 | ) 106 | .addComponent( 107 | exportLES, 108 | GroupLayout.PREFERRED_SIZE, 109 | GroupLayout.PREFERRED_SIZE, 110 | GroupLayout.PREFERRED_SIZE, 111 | ) 112 | .addComponent( 113 | self.removeDuplicates, 114 | GroupLayout.PREFERRED_SIZE, 115 | GroupLayout.PREFERRED_SIZE, 116 | GroupLayout.PREFERRED_SIZE, 117 | ) 118 | .addComponent( 119 | saveRestoreLabel, 120 | GroupLayout.PREFERRED_SIZE, 121 | GroupLayout.PREFERRED_SIZE, 122 | GroupLayout.PREFERRED_SIZE, 123 | ) 124 | .addComponent( 125 | self.saveStateButton, 126 | GroupLayout.PREFERRED_SIZE, 127 | GroupLayout.PREFERRED_SIZE, 128 | GroupLayout.PREFERRED_SIZE, 129 | ) 130 | ) 131 | .addGroup(layout.createParallelGroup() 132 | .addComponent( 133 | self.exportES, 134 | GroupLayout.PREFERRED_SIZE, 135 | GroupLayout.PREFERRED_SIZE, 136 | GroupLayout.PREFERRED_SIZE, 137 | ) 138 | .addComponent( 139 | self.exportType, 140 | GroupLayout.PREFERRED_SIZE, 141 | GroupLayout.PREFERRED_SIZE, 142 | GroupLayout.PREFERRED_SIZE, 143 | ) 144 | ) 145 | .addGroup(layout.createParallelGroup() 146 | .addComponent( 147 | self.exportButton, 148 | GroupLayout.PREFERRED_SIZE, 149 | GroupLayout.PREFERRED_SIZE, 150 | GroupLayout.PREFERRED_SIZE, 151 | ) 152 | .addComponent( 153 | self.restoreStateButton, 154 | GroupLayout.PREFERRED_SIZE, 155 | GroupLayout.PREFERRED_SIZE, 156 | GroupLayout.PREFERRED_SIZE, 157 | ) 158 | ) 159 | ) 160 | 161 | layout.setVerticalGroup(layout.createSequentialGroup() 162 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 163 | .addComponent( 164 | exportLabel, 165 | GroupLayout.PREFERRED_SIZE, 166 | GroupLayout.PREFERRED_SIZE, 167 | GroupLayout.PREFERRED_SIZE, 168 | ) 169 | ) 170 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 171 | .addComponent( 172 | exportLType, 173 | GroupLayout.PREFERRED_SIZE, 174 | GroupLayout.PREFERRED_SIZE, 175 | GroupLayout.PREFERRED_SIZE, 176 | ) 177 | .addComponent( 178 | self.exportType, 179 | GroupLayout.PREFERRED_SIZE, 180 | GroupLayout.PREFERRED_SIZE, 181 | GroupLayout.PREFERRED_SIZE, 182 | ) 183 | .addComponent( 184 | self.exportButton, 185 | GroupLayout.PREFERRED_SIZE, 186 | GroupLayout.PREFERRED_SIZE, 187 | GroupLayout.PREFERRED_SIZE, 188 | ) 189 | ) 190 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 191 | .addComponent( 192 | exportLES, 193 | GroupLayout.PREFERRED_SIZE, 194 | GroupLayout.PREFERRED_SIZE, 195 | GroupLayout.PREFERRED_SIZE, 196 | ) 197 | .addComponent( 198 | self.exportES, 199 | GroupLayout.PREFERRED_SIZE, 200 | GroupLayout.PREFERRED_SIZE, 201 | GroupLayout.PREFERRED_SIZE, 202 | ) 203 | ) 204 | .addGroup(layout.createSequentialGroup() 205 | .addComponent( 206 | self.removeDuplicates, 207 | GroupLayout.PREFERRED_SIZE, 208 | GroupLayout.PREFERRED_SIZE, 209 | GroupLayout.PREFERRED_SIZE, 210 | ) 211 | ) 212 | .addGroup(layout.createSequentialGroup() 213 | .addComponent( 214 | saveRestoreLabel, 215 | GroupLayout.PREFERRED_SIZE, 216 | GroupLayout.PREFERRED_SIZE, 217 | GroupLayout.PREFERRED_SIZE, 218 | ) 219 | ) 220 | .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 221 | .addComponent( 222 | self.saveStateButton, 223 | GroupLayout.PREFERRED_SIZE, 224 | GroupLayout.PREFERRED_SIZE, 225 | GroupLayout.PREFERRED_SIZE, 226 | ) 227 | .addComponent( 228 | self.restoreStateButton, 229 | GroupLayout.PREFERRED_SIZE, 230 | GroupLayout.PREFERRED_SIZE, 231 | GroupLayout.PREFERRED_SIZE, 232 | ) 233 | ) 234 | ) 235 | 236 | 237 | 238 | def export(self, event): 239 | if self.exportType.getSelectedItem() == "HTML": 240 | self.exportToHTML() 241 | else: 242 | self.exportToCSV() 243 | 244 | def saveStateAction(self, event): 245 | self.save_restore.saveState() 246 | 247 | def restoreStateAction(self, event): 248 | self.save_restore.restoreState() 249 | 250 | def exportToHTML(self): 251 | parentFrame = JFrame() 252 | fileChooser = JFileChooser() 253 | fileChooser.setSelectedFile(File("AutorizeReport.html")) 254 | fileChooser.setDialogTitle("Save Autorize Report") 255 | userSelection = fileChooser.showSaveDialog(parentFrame) 256 | if userSelection == JFileChooser.APPROVE_OPTION: 257 | fileToSave = fileChooser.getSelectedFile() 258 | 259 | enforcementStatusFilter = self.exportES.getSelectedItem() 260 | htmlContent = """Autorize Report by Barak Tawily 261 | 284 | 285 |

Autorize Report

286 |
287 | 288 | """ 289 | unique_HTML_lines = set() # set to keep track of unique values 290 | for i in range(0,self._log.size()): 291 | if self.removeDuplicates.isSelected(): 292 | # line data only looks for method, url, and authorized status. Does not factor in size of request during comparision 293 | lineData = "\t%s\t%s\t%s\t%s\n" % (self._log.get(i)._method, self._log.get(i)._url, self._log.get(i)._enfocementStatus,self._log.get(i)._enfocementStatusUnauthorized) 294 | if lineData in unique_HTML_lines: # Skip if line is already in set 295 | continue 296 | else: # Add line to set and continue with execution 297 | unique_HTML_lines.add(lineData) 298 | color_modified = "" 299 | if self._log.get(i)._enfocementStatus == self.BYPASSSED_STR: 300 | color_modified = "red" 301 | elif self._log.get(i)._enfocementStatus == self.IS_ENFORCED_STR: 302 | color_modified = "yellow" 303 | elif self._log.get(i)._enfocementStatus == self.ENFORCED_STR: 304 | color_modified = "LawnGreen" 305 | 306 | color_unauthorized = "" 307 | if self._log.get(i)._enfocementStatusUnauthorized == self.BYPASSSED_STR: 308 | color_unauthorized = "red" 309 | elif self._log.get(i)._enfocementStatusUnauthorized == self.IS_ENFORCED_STR: 310 | color_unauthorized = "yellow" 311 | elif self._log.get(i)._enfocementStatusUnauthorized == self.ENFORCED_STR: 312 | color_unauthorized = "LawnGreen" 313 | 314 | if enforcementStatusFilter == "All Statuses": 315 | htmlContent += "" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, color_modified, self._log.get(i)._enfocementStatus, color_unauthorized, self._log.get(i)._enfocementStatusUnauthorized) 316 | elif enforcementStatusFilter == "As table filter": 317 | if ((self._extender.showAuthBypassModified.isSelected() and self.BYPASSSED_STR == self._log.get(i)._enfocementStatus) or 318 | (self._extender.showAuthPotentiallyEnforcedModified.isSelected() and "Is enforced???" == self._log.get(i)._enfocementStatus) or 319 | (self._extender.showAuthEnforcedModified.isSelected() and self.ENFORCED_STR == self._log.get(i)._enfocementStatus) or 320 | (self._extender.showAuthBypassUnauthenticated.isSelected() and self.BYPASSSED_STR == self._log.get(i)._enfocementStatusUnauthorized) or 321 | (self._extender.showAuthPotentiallyEnforcedUnauthenticated.isSelected() and "Is enforced???" == self._log.get(i)._enfocementStatusUnauthorized) or 322 | (self._extender.showAuthEnforcedUnauthenticated.isSelected() and self.ENFORCED_STR == self._log.get(i)._enfocementStatusUnauthorized) or 323 | (self._extender.showDisabledUnauthenticated.isSelected() and "Disabled" == self._log.get(i)._enfocementStatusUnauthorized)): 324 | htmlContent += "" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, color_modified, self._log.get(i)._enfocementStatus, color_unauthorized, self._log.get(i)._enfocementStatusUnauthorized) 325 | else: 326 | if (enforcementStatusFilter == self._log.get(i)._enfocementStatus) or (enforcementStatusFilter == self._log.get(i)._enfocementStatusUnauthorized): 327 | htmlContent += "" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, color_modified, self._log.get(i)._enfocementStatus, color_unauthorized, self._log.get(i)._enfocementStatusUnauthorized) 328 | 329 | htmlContent += "
IDMethodURLOriginal lengthModified lengthUnauthorized lengthAuthorization Enforcement StatusAuthorization Unauthenticated Status
%d%s%s%d%d%d%s%s
%d%s%s%d%d%d%s%s
%d%s%s%d%d%d%s%s
" 330 | f = open(fileToSave.getAbsolutePath(), 'w') 331 | f.writelines(htmlContent) 332 | f.close() 333 | 334 | def exportToCSV(self): 335 | parentFrame = JFrame() 336 | fileChooser = JFileChooser() 337 | fileChooser.setSelectedFile(File("AutorizeReport.csv")) 338 | fileChooser.setDialogTitle("Save Autorize Report") 339 | userSelection = fileChooser.showSaveDialog(parentFrame) 340 | if userSelection == JFileChooser.APPROVE_OPTION: 341 | fileToSave = fileChooser.getSelectedFile() 342 | 343 | enforcementStatusFilter = self.exportES.getSelectedItem() 344 | csvContent = "id\tMethod\tURL\tOriginal length\tModified length\tUnauthorized length\tAuthorization Enforcement Status\tAuthorization Unauthenticated Status\n" 345 | 346 | unique_CVS_lines = set() 347 | for i in range(0, self._log.size()): 348 | if self.removeDuplicates.isSelected(): 349 | # line data only looks for method, url, and authorized status. Does not factor in size of request during comparision 350 | lineData = "\t%s\t%s\t%s\t%s\n" % (self._log.get(i)._method, self._log.get(i)._url, self._log.get(i)._enfocementStatus,self._log.get(i)._enfocementStatusUnauthorized) 351 | if lineData in unique_CVS_lines: # Skip if line is already in set 352 | continue 353 | else: # Add line to set and continue with execution 354 | unique_CVS_lines.add(lineData) 355 | if enforcementStatusFilter == "All Statuses": 356 | csvContent += "%d\t%s\t%s\t%d\t%d\t%d\t%s\t%s\n" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, self._log.get(i)._enfocementStatus, self._log.get(i)._enfocementStatusUnauthorized) 357 | elif enforcementStatusFilter == "As table filter": 358 | if ((self._extender.showAuthBypassModified.isSelected() and self.BYPASSSED_STR == self._log.get(i)._enfocementStatus) or 359 | (self._extender.showAuthPotentiallyEnforcedModified.isSelected() and "Is enforced???" == self._log.get(i)._enfocementStatus) or 360 | (self._extender.showAuthEnforcedModified.isSelected() and self.ENFORCED_STR == self._log.get(i)._enfocementStatus) or 361 | (self._extender.showAuthBypassUnauthenticated.isSelected() and self.BYPASSSED_STR == self._log.get(i)._enfocementStatusUnauthorized) or 362 | (self._extender.showAuthPotentiallyEnforcedUnauthenticated.isSelected() and "Is enforced???" == self._log.get(i)._enfocementStatusUnauthorized) or 363 | (self._extender.showAuthEnforcedUnauthenticated.isSelected() and self.ENFORCED_STR == self._log.get(i)._enfocementStatusUnauthorized) or 364 | (self._extender.showDisabledUnauthenticated.isSelected() and "Disabled" == self._log.get(i)._enfocementStatusUnauthorized)): 365 | csvContent += "%d\t%s\t%s\t%d\t%d\t%d\t%s\t%s\n" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, self._log.get(i)._enfocementStatus, self._log.get(i)._enfocementStatusUnauthorized) 366 | else: 367 | if (enforcementStatusFilter == self._log.get(i)._enfocementStatus) or (enforcementStatusFilter == self._log.get(i)._enfocementStatusUnauthorized): 368 | csvContent += "%d\t%s\t%s\t%d\t%d\t%d\t%s\t%s\n" % (self._log.get(i)._id, self._log.get(i)._method, self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse is not None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse is not None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse is not None else 0, self._log.get(i)._enfocementStatus, self._log.get(i)._enfocementStatusUnauthorized) 369 | 370 | 371 | f = open(fileToSave.getAbsolutePath(), 'w') 372 | f.writelines(csvContent) 373 | f.close() 374 | --------------------------------------------------------------------------------