def processStructured(report: ReportWrapper, token: str='') -> VulnTestInfo: """ Process the given report into a AutoTriageUtils.VulnTestInfo named tuple given that it contains structured data """ info = extractJson(report.getLatestActivity()) if info is None: return VulnTestInfo(reproduced=False, message=('Failed to parse JSON! Please try again.'), type='XSS', info={'report': report.getLatestActivity()}) # Pass it off to a helper that can try to handle any inconsistencies url, cookies, type, data = extractDataFromJson(info) if not AutoTriageUtils.isProgramURL(url): return VulnTestInfo(reproduced=False, message=('The url provided (`%s`) is not a program URL!') % url, type='XSS', info={'src': url, 'method': 'structured'}) if type.lower() == 'post': results = testPOSTXSS(url, cookies, data) elif type.lower() == 'get': results = testGETXSS(url, cookies) else: return VulnTestInfo(reproduced=False, message='Found an invalid value "type"=%s in the JSON blob!' % type, type='XSS', info={'src': url, 'method': 'structured'}) reproduced, alertBox, message, confirmedBrowsers, alertBrowsers = makeMarkdownTable(results, token) if reproduced: return VulnTestInfo(reproduced=True, message='Successfully found and confirmed an XSS at `%s`!\n' '\n\n%s\n\n' 'Metadata: {"vulnDomain": "%s"}' % (url, message, urlparse(url).hostname), type='XSS', info={'src': url, 'method': 'unstructured', 'confirmedBrowsers': confirmedBrowsers, 'alertBrowsers': alertBrowsers, 'httpType': type, 'cookies': cookies}) # noqa elif alertBox: return VulnTestInfo(reproduced=False, message=('Failed to confirm the vulnerability! Detected an alert box ' 'but the token: `"%s"` was not found!' '\n\n%s\n\n') % (token, message), type='XSS', info={'src': url, 'method': 'unstructured'}) else: return VulnTestInfo(reproduced=False, message=("Failed to validate XSS at `%s` via structured data. Either try " "again or wait for manual review of your bug.") % url, type='XSS', info={'method': 'structured'})
def processStructured(report: ReportWrapper, token: str='') -> VulnTestInfo: """ Process the given report into a VulnTestInfo named tuple given that it contains structured data """ info = extractJson(report.getLatestActivity()) if info is None: return VulnTestInfo(reproduced=False, message=('Failed to parse JSON! Please try again.'), type='Open Redirect', info={'report': report.getLatestActivity()}) # Pass it off to a helper that can try to handle any inconsistencies url, cookies, type, data = extractDataFromJson(info) if not isProgramURL(url): return VulnTestInfo(reproduced=False, message=('The url provided (`%s`) is not a program URL!') % url, type='Open Redirect', info={'src': url, 'method': 'structured'}) if type.lower() == 'post': res = testPOSTOpenRedirect(url, cookies, data) elif type.lower() == 'get': res = testGETOpenRedirect(url, cookies) else: return VulnTestInfo(reproduced=False, message='Found an invalid value "type"=%s in the JSON blob!' % type, type='Open Redirect', info={'src': url, 'method': 'structured'}) if res and token.lower() in urlparse(res).hostname.lower(): return VulnTestInfo(reproduced=True, message=('Successfully found and confirmed an open redirect from `%s` to `%s`!\n' 'Metadata: {"vulnDomain": "%s"}') % (url, res, urlparse(url).hostname), type='Open Redirect', info={'src': url, 'redirect': res, 'method': 'structured', 'httpType': type, 'cookies': cookies}) elif res: return VulnTestInfo(reproduced=False, message=tokenNotFoundMessage % (url, res, token, token), type='Open Redirect', info={'src': url, 'redirect': res, 'method': 'structured'}) else: return VulnTestInfo(reproduced=False, message=("Failed to validate open redirect at `%s` via structured data. Either try again " "or wait for manual review of your bug.") % url, type='Open Redirect', info={'method': 'structured'})
def process(report: ReportWrapper) -> Optional[VulnTestInfo]: """ Process the given report into a VulnTestInfo named tuple """ # If the user has not yet been prompted for automatic triaging if not report.botHasCommented(): token = AutoTriageUtils.generateToken() return VulnTestInfo(reproduced=False, message=constants.initialMessage(token, 'redirect to a domain', 'Open Redirect'), type='Open Redirect', info={}) elif report.shouldBackoff(): if not report.hasPostedBackoffComment(): addFailureToDB(report.getReporterUsername(), report.getReportID()) return VulnTestInfo(reproduced=False, message=('Automatic verification of vulnerability has failed, Backing off! Falling ' 'back to human verification. '), type='Open Redirect', info={}) else: return None elif report.isVerified(): return None try: if isStructured(report.getLatestActivity()): return processStructured(report, token=report.getToken()) else: return processUnstructured(report, token=report.getToken()) except Exception as e: print("Caught exception: %s" % str(e)) traceback.print_exc() print("+" * 80) return VulnTestInfo(reproduced=False, message=('Internal error detected! Backing off...'), type='Open Redirect', info={})
def processUnstructured(report: ReportWrapper, token: str = '') -> VulnTestInfo: """ Process the given report into a VulnTestInfo named tuple given that it doesn't contain structured data """ urls = extractURLs(report.getLatestActivity()) if config.DEBUG: print("URLs=%s" % str(urls)) if len(urls) > 5: if config.DEBUG: print("User submitted %s URLs. Skipping...") return VulnTestInfo( reproduced=False, message='Found %s URLs. Please resubmit with a single URL to test.', type='SQLi', info={ 'URLs': str(urls), 'method': 'structured' }) testedURLs = [] for url in urls: if isProgramURL(url): # Unstructured reports are treated as a GET delay = testGETSQLDelay(url, {}) if delay and abs(delay - int(token)) < maxTimeDiff: return VulnTestInfo( reproduced=True, message=('Successfully found and confirmed SQLi at `%s`!\n' 'Metadata: {"vulnDomain": "%s"}') % (url, urlparse(url).hostname), type='SQLi', info={ 'src': url, 'method': 'unstructured', 'delay': int(delay), 'httpType': 'GET', 'cookies': {} }) elif delay: return VulnTestInfo(reproduced=False, message=wrongDelayMessage % (str(int(delay)), token, token), type='SQLi', info={ 'src': url, 'method': 'unstructured' }) else: testedURLs.append(url) if len(testedURLs) > 0: return VulnTestInfo(reproduced=False, message=constants.structuredDataMessage % ('SQLi'), type='SQLi', info={'method': 'unstructured'}) else: return VulnTestInfo(reproduced=False, message=constants.failedToFindURLsMessage, type='SQLi', info={'method': 'unstructured'})
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 processUnstructured(report: ReportWrapper, token: str='') -> AutoTriageUtils.VulnTestInfo: """ Process the given report into a AutoTriageUtils.VulnTestInfo named tuple given that it doesn't contain structured data """ urls = extractURLs(report.getLatestActivity()) if config.DEBUG: print("URLs=%s" % str(urls)) if len(urls) > 5: if config.DEBUG: print("User submitted %s URLs. Skipping...") return VulnTestInfo(reproduced=False, message='Found %s URLs. Please resubmit with a single URL to test.', type='XSS', info={'URLs': str(urls), 'method': 'structured'}) testedURLs = [] for url in urls: if AutoTriageUtils.isProgramURL(url): testedURLs.append(url) results = testGETXSS(url, {}) reproduced, alertBox, message, confirmedBrowsers, alertBrowsers = makeMarkdownTable(results, token) if reproduced: return VulnTestInfo(reproduced=True, message=('Successfully found and confirmed an XSS at `%s`!\n' '\n\n%s\n\n' 'Metadata: {"vulnDomain": "%s"}') % (url, message, urlparse(url).hostname), type='XSS', info={'src': url, 'method': 'unstructured', 'confirmedBrowsers': confirmedBrowsers, 'alertBrowsers': alertBrowsers, 'httpType': 'GET', 'cookies': {}}) elif alertBox: return VulnTestInfo(reproduced=False, message=('Failed to confirm the vulnerability! Detected an alert ' 'box but the token: `"%s"` was not found!' '\n\n%s\n\n') % (token, message), type='XSS', info={'src': url, 'method': 'unstructured'}) if len(testedURLs) > 0: return VulnTestInfo(reproduced=False, message=constants.structuredDataMessage % 'XSS', type='XSS', info={'method': 'unstructured'}) else: return VulnTestInfo(reproduced=False, message=constants.failedToFindURLsMessage, type='XSS', info={'method': 'unstructured'})
def processUnstructured(report: ReportWrapper, token: str='') -> VulnTestInfo: """ Process the given report into a VulnTestInfo named tuple given that it doesn't contain structured data """ urls = extractURLs(report.getLatestActivity()) if config.DEBUG: print("URLs=%s" % str(urls)) if len(urls) > 5: if config.DEBUG: print("User submitted %s URLs. Skipping...") return VulnTestInfo(reproduced=False, message=('Found %s URLs. Please resubmit with a single URL to test.'), type='Open Redirect', info={'URLs': str(urls), 'method': 'structured'}) testedURLs = [] for url in urls: if isProgramURL(url): res = testGETOpenRedirect(url, {}) print("res=%s" % str(urlparse(res).hostname)) if res and token.lower() in urlparse(res).hostname.lower(): return VulnTestInfo(reproduced=True, message=('Successfully found and confirmed an open redirect from `%s` to `%s`!\n' 'Metadata: {"vulnDomain": "%s"}') % (url, res, urlparse(url).hostname), type='Open Redirect', info={'src': url, 'redirect': res, 'method': 'unstructured', 'httpType': 'GET', 'cookies': {}}) # nopep8 elif res: return VulnTestInfo(reproduced=False, message=tokenNotFoundMessage % (url, res, token, token), type='Open Redirect', info={'src': url, 'redirect': res, 'method': 'unstructured'}) else: testedURLs.append(url) if len(testedURLs) > 0: return VulnTestInfo(reproduced=False, message=constants.structuredDataMessage % 'open redirect', type='Open Redirect', info={'method': 'unstructured'}) else: return VulnTestInfo(reproduced=False, message=constants.failedToFindURLsMessage, type='Open Redirect', info={'method': 'unstructured'})
def processStructured(report: ReportWrapper, token: str = '') -> VulnTestInfo: """ Process the given report into a VulnTestInfo named tuple given that it contains structured data """ info = extractJson(report.getLatestActivity()) if info is None: return VulnTestInfo( reproduced=False, message=('Failed to parse JSON! Please try again.'), type='SQLi', info={'report': report.getLatestActivity()}) # Pass it off to a helper that can try to handle any inconsistencies url, cookies, type, data = extractDataFromJson(info) if not isProgramURL(url): return VulnTestInfo( reproduced=False, message=('The url provided (`%s`) is not a program URL!') % url, type='SQLi', info={ 'src': url, 'method': 'structured' }) if type.lower() == 'post': delay = testPOSTSQLDelay(url, cookies, data) elif type.lower() == 'get': delay = testGETSQLDelay(url, cookies) else: return VulnTestInfo( reproduced=False, message='Found an invalid value "type"=%s in the JSON blob!' % type, type='SQLi', info={ 'src': url, 'method': 'structured' }) if delay and abs(delay - int(token)) < maxTimeDiff: return VulnTestInfo( reproduced=True, message=('Successfully found and confirmed SQLi at `%s`!\n' 'Metadata: {"vulnDomain": "%s"}') % (url, urlparse(url).hostname), type='SQLi', info={ 'src': url, 'method': 'structured', 'delay': int(delay), 'httpType': type, 'cookies': cookies }) elif delay: return VulnTestInfo(reproduced=False, message=wrongDelayMessage % (str(int(delay)), token, token), type='SQLi', info={ 'src': url, 'method': 'structured' }) else: return VulnTestInfo( reproduced=False, message= ("Failed to validate SQLi at `%s` via structured data. Either try again or wait " "for manual review of your bug.") % url, type='SQLi', info={'method': 'structured'})