def test_ReportWrapperGetters(): r = ReportWrapper(openRedirectReproJson) assert r.getReportID() == '239981' assert r.getLatestActivity() == ("blah open_redirect\n\n[some](http://example.com/redir.php?QUERY_STRING=" "https://google.com)") assert r.getReportBody() == ("blah open_redirect\n\n[some](http://example.com/redir.php?QUERY_STRING=" "https://google.com)") assert r.getReportWeakness() == "Open Redirect" assert r.getReportTitle() == "open redirect" assert r.getVulnDomains() == ['example.com'] r = ReportWrapper(openRedirectUnreproJson) assert r.getReportID() == '240035' assert r.getLatestActivity() == ("this is detected as an open redirect but there is no markdown link to it\n\n" "https://example.com/redir.php?QUERY_STRING=https://google.com") assert r.getReportBody() == ("this is detected as an open redirect but there is no markdown link to it\n\n" "https://example.com/redir.php?QUERY_STRING=https://google.com") assert r.getReportWeakness() == "Open Redirect" assert r.getReportTitle() == "malformed open redirect" assert r.getVulnDomains() == ['example.com']
def processReport(report: ReportWrapper, startTime: datetime) -> Optional[VulnTestInfo]: """ Attempt to verify a given report """ if report.needsBotReply(): if startTime > report.getReportedTime(): return None if config.DEBUG: print("Processing %s" % report.getReportTitle()) for module in modules: if module.match(report.getReportBody(), report.getReportWeakness()): # type: ignore if config.DEBUG: print(module.__file__.split('/')[-1] + " matched id=%s!" % report.getReportID()) vti = module.process(report) # type: ignore if config.DEBUGVERBOSE: print(vti) if vti: postComment(report.getReportID(), vti, addStopMessage=True) if vti.reproduced and config.metadataLogging: metadataVTI = generateMetadataVTI(report, vti) postComment(report.getReportID(), metadataVTI, internal=True) return vti if config.DEBUG: print("No matches") return None
def generateMetadataVTI(report: ReportWrapper, vti: VulnTestInfo) -> VulnTestInfo: """ Given the results of a vulnerability test thar reproduced a vulnerability and a report, generate an internal VTI used to hold metadata about the vulnerability """ internalMetadata = {'id': report.getReportID(), 'title': report.getReportTitle(), 'reportedTime': str(report.getReportedTime()), 'verifiedTime': str(datetime.now()), 'type': vti.type, 'exploitURL': vti.info['src'], 'method': vti.info['method']} if vti.type == 'XSS': internalMetadata['confirmedBrowsers'] = vti.info['confirmedBrowsers'] internalMetadata['alertBrowsers'] = vti.info['alertBrowsers'] internalMetadata['httpType'] = vti.info['httpType'] internalMetadata['cookies'] = vti.info['cookies'] elif vti.type == 'SQLi': internalMetadata['delay'] = vti.info['delay'] internalMetadata['httpType'] = vti.info['httpType'] internalMetadata['cookies'] = vti.info['cookies'] elif vti.type == 'Open Redirect': internalMetadata['redirect'] = vti.info['redirect'] internalMetadata['httpType'] = vti.info['httpType'] internalMetadata['cookies'] = vti.info['cookies'] message = '# Internal Metadata: \n\n```\n%s\n```\n' % json.dumps(internalMetadata, sort_keys=True, indent=4, separators=(',', ': ')) if config.DEBUGVERBOSE: print(internalMetadata) internalVTI = VulnTestInfo(reproduced=False, message=message, info={}, type='') return internalVTI
def processReport(report: ReportWrapper) -> bool: """ Process a report via searching for duplicates and posting comments based off of the confidence levels Returns whether or not the report was classified as a duplicate with a high confidence """ if report.getState() == "new" and not report.hasDuplicateComment( ) and not report.isVerified(): earlierReports = getAllOpenReports( report.getReportedTime()) # type: List[ReportWrapper] idConfTuples = [] # type: List[Tuple[str, int]] matches = [] # type: List[str] for earlierReport in earlierReports: for module in modules: if (module.match(report.getReportBody(), report.getReportWeakness()) and # type: ignore module.match(earlierReport.getReportBody(), earlierReport.getReportWeakness()) ): # type: ignore matches.append(earlierReport.getReportID()) try: confidence = int(isDuplicate(earlierReport, report)[0]) except TypeError: confidence = 0 if confidence == 99: AutoTriageUtils.postComment( report.getReportID(), VulnTestInfo( message='Found a duplicate with 99%% confidence: #%s' % earlierReport.getReportID(), info={}, reproduced=False, type=''), internal=True) if config.DEBUG: print("Detected that %s (%s) is a duplicate of %s (%s)!" % (report.getReportID(), report.getReportTitle(), earlierReport.getReportID(), earlierReport.getReportTitle())) return False # Change to return True to make the bot stop interacting after finding a duplicate elif confidence > 50: idConfTuples.append((earlierReport.getReportID(), confidence)) # If you update the phrases here, you must also update them in AutoTriageUtils.ReportWrapper.hasDuplicateComment if len(idConfTuples) > 0: def idConfToStr(tuple: Tuple) -> str: return ( 'Detected a possible duplicate report with confidence of %s: #%s' % (tuple[1], tuple[0])) AutoTriageUtils.postComment(report.getReportID(), VulnTestInfo(message='\n'.join([ idConfToStr(t) for t in idConfTuples ]), info={}, reproduced=False, type=''), internal=True) if config.DEBUG: print('Found partial matches: %s' % str(idConfTuples)) if len(matches) > 0 and len(matches) <= 5: AutoTriageUtils.postComment( report.getReportID(), VulnTestInfo(message=( 'There are currently %s open reports about this type of ' 'vulnerability: %s' % (str(len(matches)), ', '.join(['#' + id for id in matches]))), info={}, reproduced=False, type=''), internal=True) if config.DEBUG: print( 'Found %s reports on the same type of vulnerability as %s: %s' % (str(len(matches)), str(report.getReportID()), ', '.join( ['#' + id for id in matches]))) return False