['Check.Pasv.Cookie.Secure.php', 'InsecureCookie', 'pass'],\ ['Check.Pasv.CrossDomain.ScriptReference.php', 'CrossJS', 'pass'], \ ['Check.Pasv.Header.ContentTypeMissing.php', 'XContent', 'pass'], \ ['Check.Pasv.Header.FrameOptions.php', 'XFrame', 'pass'],\ ['Check.Pasv.Header.IeXssProtection.php', 'IE8XSSfilter ', 'pass'], \ ['Check.Pasv.Header.CacheControl.php', 'CacheControl', 'pass'], \ ['Check.Pasv.Header.MimeSniff.php', 'NoContentHeader', 'pass'],\ ['Check.Pasv.Header.WeakAuth.php', 'WeakAuth', 'pass'], \ ['Check.Pasv.InformationDisclosure.Comments.php', 'InfoComments', 'pass'], \ ['Check.Pasv.InformationDisclosure.DatabaseErrors.php', 'InfoDb', 'pass'], \ ['Check.Pasv.InformationDisclosure.DebugErrors.php', 'InfoDebug', 'pass'], \ ['Check.Pasv.InformationDisclosure.InUrl.php', 'InfoUrl', 'pass'], \ ['watcher/Check.Pasv.Cookie.Secure.php', 'InsecureCookie', 'pass'],\ ] zap = ZAP(proxies={'http': zapUrl, 'https': zapUrl}) alerts = zap.alerts uniqueUrls = set([]) # alertsPerUrl is a dictionary of urlsummary to a dictionary of type to set of alertshortnames ;) alertsPerUrl = {} plugins = set([]) for alert in alerts: url = alert.get('url') # Grab the url before any '?' url = url.split('?')[0] #print 'URL: ' + url urlEl = url.split('/') if (len(urlEl) > 4):
def test_zap(zapconfig): parser = SafeConfigParser() parser.read(zapconfig) zapUrl = parser.get("Proxy", "url") zap = ZAP(proxies={'http': zapUrl, 'https': zapUrl}) if (parser.getboolean("Actions", "start")): # print "platform=" + platform.system() if (platform.system() == "Windows"): zapScript = "start /b zap.bat" else: zapScript = "zap.sh" zapInstall = parser.get("Proxy", "install") if (len(zapInstall) == 0): if (platform.system() == "Windows"): # Win 7 default path zapInstall = "C:\Program Files (x86)\OWASP\Zed Attack Proxy" if (not os.path.exists(zapInstall)): # Win XP default path zapInstall = "C:\Program Files\OWASP\Zed Attack Proxy" else: # No default path for Mac OS or Linux print "Installation directory must be set in " + zapconfig if (len(parser.get("Proxy", "home")) > 0): zapScript = zapScript + " -d " + parser.get("Proxy", "home") os.chdir(zapInstall) os.system(zapScript) time.sleep(20) spiderUrls = parser.get("Actions", "spider") if (len(spiderUrls) > 0): for spiderUrl in spiderUrls.split(','): zap.urlopen(spiderUrl) # Give the sites tree a chance to get updated time.sleep(2) print 'Spidering %s' % spiderUrl zap.start_spider(spiderUrl) # Give the Spider a chance to start time.sleep(2) while (int(zap.spider_status[0]) < 100): #print 'Spider progress %: ' + zap.spider_status[0] time.sleep(5) print 'Finished spidering %s' % spiderUrl print 'Spider completed' # Give the passive scanner a chance to finish time.sleep(5) scanUrls = parser.get("Actions", "scan") if (len(scanUrls) > 0): for scanUrl in scanUrls.split(','): print 'Scanning %s' % scanUrl zap.start_scan(scanUrl) while (int(zap.scan_status[0]) < 100): #print 'Scan progress %: ' + zap.scan_status[0] time.sleep(5) print 'Finished scanning %s' % scanUrl print 'Scanner completed' saveSession = parser.get("Actions", "savesession") if (len(saveSession) > 0): time.sleep(5) # Will this help?? zap.save_session(saveSession) #zapAlerts = zap.alerts # Save for later, in case ZAP is stopped.. zapAlerts = copy.deepcopy( zap.alerts) # Save for later, in case ZAP is stopped.. if (parser.getboolean("Actions", "stop")): # TODO: this is causing problems right now :( zap.shutdown() requireAlertsStr = parser.get("Alerts", "require") if (len(requireAlertsStr) > 0): for requireAlertStr in requireAlertsStr.split("\n"): requireAlert = ast.literal_eval(requireAlertStr) # Check at least one match found in the alerts found = False for alert in zapAlerts: if (match_alerts(alert, requireAlert)): found = True break if (not found): # No match, fail the test print "Required alert not present: " + requireAlertStr assert 0 ignoreAlertsStr = parser.get("Alerts", "ignore") ignoreAlerts = [] if (len(ignoreAlertsStr) > 0): for ignoreAlertStr in ignoreAlertsStr.split("\n"): ignoreAlerts.append(ast.literal_eval(ignoreAlertStr)) strippedAlerts = strip_alerts(zapAlerts, ignoreAlerts) saveAlerts = parser.get("Alerts", "savealerts") if (len(saveAlerts) > 0): alertsFile = open(saveAlerts, 'w') for alert in strippedAlerts: alertsFile.write(alert_to_str(alert)) alertsFile.write("\n") alertsFile.close() assert len(strippedAlerts) == 0
def test_zap(zapconfig): parser = SafeConfigParser() parser.read(zapconfig) zapUrl = parser.get("Proxy", "url"); zap = ZAP(proxies={'http': zapUrl, 'https': zapUrl}) if (parser.getboolean("Actions", "start")): # print "platform=" + platform.system() if (platform.system() == "Windows"): zapScript = "start /b zap.bat" else: zapScript = "zap.sh" zapInstall = parser.get("Proxy", "install"); if (len(zapInstall) == 0): if (platform.system() == "Windows"): # Win 7 default path zapInstall = "C:\Program Files (x86)\OWASP\Zed Attack Proxy"; if ( not os.path.exists(zapInstall)): # Win XP default path zapInstall = "C:\Program Files\OWASP\Zed Attack Proxy"; else: # No default path for Mac OS or Linux print "Installation directory must be set in " + zapconfig if (len(parser.get("Proxy", "home")) > 0): zapScript = zapScript + " -d " + parser.get("Proxy", "home") os.chdir(zapInstall); os.system(zapScript); time.sleep(20); spiderUrls = parser.get("Actions", "spider"); if (len(spiderUrls) > 0): for spiderUrl in spiderUrls.split(','): zap.urlopen(spiderUrl) # Give the sites tree a chance to get updated time.sleep(2) print 'Spidering %s' % spiderUrl zap.start_spider(spiderUrl) # Give the Spider a chance to start time.sleep(2) while (int(zap.spider_status[0]) < 100): #print 'Spider progress %: ' + zap.spider_status[0] time.sleep(5) print 'Finished spidering %s' % spiderUrl print 'Spider completed' # Give the passive scanner a chance to finish time.sleep(5) scanUrls = parser.get("Actions", "scan"); if (len(scanUrls) > 0): for scanUrl in scanUrls.split(','): print 'Scanning %s' % scanUrl zap.start_scan(scanUrl) while (int(zap.scan_status[0]) < 100): #print 'Scan progress %: ' + zap.scan_status[0] time.sleep(5) print 'Finished scanning %s' % scanUrl print 'Scanner completed' saveSession = parser.get("Actions", "savesession"); if (len(saveSession) > 0): time.sleep(5) # Will this help?? zap.save_session(saveSession) #zapAlerts = zap.alerts # Save for later, in case ZAP is stopped.. zapAlerts = copy.deepcopy(zap.alerts) # Save for later, in case ZAP is stopped.. if (parser.getboolean("Actions", "stop")): # TODO: this is causing problems right now :( zap.shutdown() requireAlertsStr = parser.get("Alerts", "require") if (len(requireAlertsStr) > 0): for requireAlertStr in requireAlertsStr.split("\n"): requireAlert = ast.literal_eval(requireAlertStr) # Check at least one match found in the alerts found = False for alert in zapAlerts: if ( match_alerts(alert, requireAlert)): found = True break if (not found): # No match, fail the test print "Required alert not present: " + requireAlertStr assert 0 ignoreAlertsStr = parser.get("Alerts", "ignore") ignoreAlerts = [] if (len(ignoreAlertsStr) > 0): for ignoreAlertStr in ignoreAlertsStr.split("\n"): ignoreAlerts.append(ast.literal_eval(ignoreAlertStr)) strippedAlerts = strip_alerts(zapAlerts, ignoreAlerts) saveAlerts = parser.get("Alerts", "savealerts") if (len(saveAlerts) > 0): alertsFile = open(saveAlerts, 'w') for alert in strippedAlerts: alertsFile.write(alert_to_str(alert)) alertsFile.write("\n") alertsFile.close() assert len(strippedAlerts) == 0
class ZapPlugin(MinionPlugin): zap = ZAP(proxies={'http': 'http://127.0.0.1:8090', 'https': 'http://127.0.0.1:8090'}) default = { "template" : { "target" : { "type" : "url", "is_list" : True, "required" : True} }, "safechecks" : { "type" : "bool", "value" : True} } def __init__(self): MinionPlugin.__init__(self, ZapPlugin.default) self.state = MinionPlugin.STATUS_PENDING self.messages = { "PENDING" : "Plugin is pending execution.", "WAITING" : "Execution is suspending, waiting for RESUME.", "RUNNING" : "Execution is in progress.", "COMPLETE" : "Execution is finished.", "CANCELLED" : "Execution was cancelled.", "FAILED" : "Execution failed." } self.allow_states = { MinionPlugin.STATUS_PENDING : [MinionPlugin.STATE_START], MinionPlugin.STATUS_WAITING : [MinionPlugin.STATE_RESUME, MinionPlugin.STATE_TERMINATE], MinionPlugin.STATUS_RUNNING : [MinionPlugin.STATE_SUSPEND, MinionPlugin.STATE_TERMINATE], MinionPlugin.STATUS_COMPLETE : [], MinionPlugin.STATUS_CANCELLED : [], MinionPlugin.STATUS_FAILED : [] } def do_validate(self, config): return True def do_validate_key(self, key, value): return True def do_status(self): return self.create_status(True, self.messages[self.state], self.state) def do_start(self): target = "http://localhost:8080/bodgeit/" print "ZapPlugin pre start" try: zct = ZapScanThread() zct.setZap(self.zap) zct.setTarget(target) zct.start() except Exception as e: print "ZapPlugin failed %s" % e print "ZapPlugin post start" self.state = MinionPlugin.STATUS_RUNNING #return self.create_status(True, self.messages[self.state], self.state) return self.create_std_status(True, self.state) def do_suspend(self): self.state = MinionPlugin.STATUS_WAITING return self.create_status(True, self.messages[self.state], self.state) def do_resume(self): self.state = MinionPlugin.STATUS_RUNNING return self.create_status(True, self.messages[self.state], self.state) def do_terminate(self): self.state = MinionPlugin.STATUS_CANCELLED return self.create_status(True, self.messages[self.state], self.state) def do_get_states(self): return self.allow_states[self.state]
def _blocking_zap_main(self): logging.debug("ZAPPlugin._blocking_zap_main") self.report_progress(15, 'Starting ZAP') try: self.zap = ZAP(proxies={'http': 'http://127.0.0.1:%d' % self.zap_port, 'https': 'http://127.0.0.1:%d' % self.zap_port}) target = self.configuration['target'] time.sleep(5) logging.info('Accessing target %s' % target) while (True): try: self.zap.urlopen(target) break except IOError as e: time.sleep(2) # Give the sites tree a chance to get updated time.sleep(2) logging.info('Spidering target %s' % target) self.report_progress(34, 'Spidering target') self.zap.start_spider(target) # Give the Spider a chance to start time.sleep(2) while True: spider_progress = int(self.zap.spider_status[0]) logging.debug('Spider progress %d' % spider_progress) progress = 34 + (spider_progress / 3) self.report_progress(progress, 'Spidering target') if spider_progress == 100: break time.sleep(5) logging.debug('Spider completed') self.report_progress(67, 'Scanning target') if self.configuration.get('scan'): # Give the passive scanner a chance to finish time.sleep(5) logging.debug('Scanning target %s' % target) self.zap.start_scan(target) time.sleep(5) while True: scan_progress = int(self.zap.spider_status[0]) logging.debug('Scan progress %d' % scan_progress) progress = 67 + (scan_progress / 3) self.report_progress(progress, 'Scanning target') if scan_progress == 100: break time.sleep(5) self.report_progress(100, 'Completing scan') logging.debug('Scan completed? %s' % self.zap.scan_status[0]) self.report_issues(self.get_results()) logging.info('Scan completed, shutting down') self.zap.shutdown() self.report_finish() except Exception as e: logging.exception("Error while executing zap plugin")
class ZAPPlugin(ExternalProcessPlugin): PLUGIN_NAME = "ZAP" PLUGIN_VERSION = "0.1" ZAP_NAME = "zap.sh" def do_configure(self): logging.debug("ZAPPlugin.do_configure") self.zap_path = self.locate_program(self.ZAP_NAME) if self.zap_path is None: raise Exception("Cannot find %s in PATH" % self.ZAP_NAME) # Validate the configuration if self.configuration.get('target') is None or len(self.configuration['target']) == 0: raise Exception("Missing or invalid target in configuration") def do_process_ended(self, status): logging.debug("ZAPPlugin.do_process_ended") self.callbacks.report_finish() def do_start(self): logging.debug("ZAPPlugin.do_start") # Start ZAP in daemon mode self.zap_port = self._random_port() args = ['-daemon', '-port', str(self.zap_port), '-dir', self.work_directory] self.spawn(self.zap_path, args) self.report_artifacts("ZAP Output", ["zap.log"]) # Start the main code in a thread return deferToThread(self._blocking_zap_main) def _random_port(self): return random.randint(8192, 16384) def _blocking_zap_main(self): logging.debug("ZAPPlugin._blocking_zap_main") self.report_progress(15, 'Starting ZAP') try: self.zap = ZAP(proxies={'http': 'http://127.0.0.1:%d' % self.zap_port, 'https': 'http://127.0.0.1:%d' % self.zap_port}) target = self.configuration['target'] time.sleep(5) logging.info('Accessing target %s' % target) while (True): try: self.zap.urlopen(target) break except IOError as e: time.sleep(2) # Give the sites tree a chance to get updated time.sleep(2) logging.info('Spidering target %s' % target) self.report_progress(34, 'Spidering target') self.zap.start_spider(target) # Give the Spider a chance to start time.sleep(2) while True: spider_progress = int(self.zap.spider_status[0]) logging.debug('Spider progress %d' % spider_progress) progress = 34 + (spider_progress / 3) self.report_progress(progress, 'Spidering target') if spider_progress == 100: break time.sleep(5) logging.debug('Spider completed') self.report_progress(67, 'Scanning target') if self.configuration.get('scan'): # Give the passive scanner a chance to finish time.sleep(5) logging.debug('Scanning target %s' % target) self.zap.start_scan(target) time.sleep(5) while True: scan_progress = int(self.zap.spider_status[0]) logging.debug('Scan progress %d' % scan_progress) progress = 67 + (scan_progress / 3) self.report_progress(progress, 'Scanning target') if scan_progress == 100: break time.sleep(5) self.report_progress(100, 'Completing scan') logging.debug('Scan completed? %s' % self.zap.scan_status[0]) self.report_issues(self.get_results()) logging.info('Scan completed, shutting down') self.zap.shutdown() self.report_finish() except Exception as e: logging.exception("Error while executing zap plugin") def get_results(self): alerts = self.zap.alerts issues = [] for alert in alerts: found = False for issue in issues: # TODO should test other values here as well if alert.get('alert') == issue['Summary']: if len(issue['URLs']) < 25: issue['URLs'].append(alert.get('url')) found = True break if found: break if not found: issues.append({ "Summary" : alert.get('alert'), "Description" : alert.get('description'), "Further-Info" : alert.get('other'), "Severity" : alert.get('risk'), "Confidence" : alert.get('reliability'), "Solution" : alert.get('solution'), "URLs" : [alert.get('url')]}); return issues