def interrupt(self, sig=None, frame=None): '''Interrupt sequence''' log.error("Interrupting...") # If called inside ThreadPoolExecutor, raise Exeception if not isinstance(threading.current_thread(), threading._MainThread): raise InterruptedError() # Cancel all scans self.cancel_pending_futures() # future scans # Wait all scans finished self.scanner.cancel_scans() # running scans # Give a 5 seconds timeout to buggy WPScan jobs to finish or ignore them try: timeout(5, self.executor.shutdown, kwargs=dict(wait=True)) except TimeoutError: pass # Recover reports from futures results new_reports = [] for f in self.futures: if f.done(): try: new_reports.append(f.result()) except Exception: pass # Display results and quit self.print_scanned_sites_results(new_reports) log.info("Scans interrupted.") sys.exit(-1)
def interrupt(self, sig=None, frame=None) -> None: # type: ignore [no-untyped-def] """Interrupt the program and exit. """ log.error("Interrupting...") # If called inside ThreadPoolExecutor, raise Exeception if not isinstance( threading.current_thread(), threading._MainThread): # type: ignore [attr-defined] raise InterruptedError() self.interrupt_scans() # Give a 5 seconds timeout to buggy WPScan jobs to finish or ignore them try: timeout(5, self._executor.shutdown, kwargs=dict(wait=True)) except TimeoutError: pass # Display results log.info(repr(self.new_reports)) log.info("Scans interrupted.") # and quit sys.exit(-1)
def interrupt(self) -> None: "Send SIGTERM to all currently running WPScan processes. Unlock api wait. " self._interrupting = True self._api_wait.set() for p in self.processes: p.terminate() # Wait for all processes to finish , kill after timeout try: timeout(INTERRUPT_TIMEOUT, self._wait_all_wpscan_process) except TimeoutError: for p in self.processes: p.kill()
def cancel_scans(self): self.interrupting = True # Send ^C to all WPScan not finished for p in self.wpscan.processes: p.send_signal(signal.SIGINT) # Wait for all processes to finish , kill after timeout try: timeout(INTERRUPT_TIMEOUT, self.wait_all_wpscan_process) except TimeoutError: log.error("Interrupt timeout reached, killing WPScan processes") for p in self.wpscan.processes: p.kill() # Unlock api wait self.api_wait.set()
def cancel_scans(self): ''' Send ^C to all WPScan processes. Escape api limit wait if the program is sleeping. ''' self.interrupting=True # Send ^C to all WPScan not finished for p in self.wpscan.processes: p.terminate() # Wait for all processes to finish , kill after timeout try: timeout(INTERRUPT_TIMEOUT, self.wait_all_wpscan_process) except TimeoutError: for p in self.wpscan.processes: p.kill() # Unlock api wait self.api_wait.set()
def wpscan_site(self, wp_site, wp_report): '''Timeout wrapper arround `WPWatcherScanner._wpscan_site()` Launch WPScan. Returns filled wp_report or None ''' try: wp_report_new= timeout(self.scan_timeout.total_seconds(), self._wpscan_site, args=(wp_site, wp_report) ) if wp_report_new: wp_report.update(wp_report_new) else : return None except TimeoutError: wp_report['error']+="Timeout scanning site after %s seconds.\nSetup scan_timeout in config file to allow more time"%self.scan_timeout.total_seconds() log.error("Timeout scanning site %s after %s seconds. Setup scan_timeout in config file to allow more time"%(wp_site['url'], self.scan_timeout.total_seconds())) # Kill process for p in self.wpscan.processes: if ( wp_site['url'] in p.args ) and not p.returncode: log.info('Killing WPScan process %s'%(safe_log_wpscan_args(p.args))) p.kill() self.check_fail_fast() return wp_report
def wpscan_site(self, wp_site, wp_report): # Launch WPScan try: wp_report_new = timeout(self.scan_timeout.total_seconds(), self._wpscan_site, args=(wp_site, wp_report)) if wp_report_new: wp_report.update(wp_report_new) else: return None except TimeoutError: wp_report['errors'].append( "Timeout scanning site after %s seconds" % self.scan_timeout.total_seconds()) log.error("Timeout scanning site %s after %s seconds." % (wp_site['url'], self.scan_timeout.total_seconds())) # Terminate self.terminate_scan(wp_site, wp_report) self.check_fail_fast() return wp_report
def _wpscan( self, *args: str ) -> subprocess.CompletedProcess: # type: ignore [type-arg] # WPScan arguments arguments = list(args) if arguments[0] == 'wpscan': arguments.pop(0) cmd = self._wpscan_path + arguments # Log wpscan command without api token log.debug( f"Running WPScan command: {' '.join(safe_log_wpscan_args(cmd))}") # Run wpscan process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Append process to current process list and launch self.processes.append(process) if self._scan_timeout: try: stdout, stderr = timeout(self._scan_timeout.total_seconds(), process.communicate) except TimeoutError as err: process.kill() # Raise error err_str = f"WPScan process '{safe_log_wpscan_args(cmd)}' timed out after {self._scan_timeout.total_seconds()} seconds. Setup 'scan_timeout' to allow more time. " raise RuntimeError(err_str) from err else: stdout, stderr = process.communicate() self.processes.remove(process) try: out_decoded = stdout.decode("utf-8") err_decoded = stderr.decode("utf-8") except UnicodeDecodeError: out_decoded = stdout.decode("latin1", errors="replace") err_decoded = stderr.decode("latin1", errors="replace") finally: return subprocess.CompletedProcess(args=cmd, returncode=process.returncode, stdout=out_decoded, stderr=err_decoded)