示例#1
0
    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)
示例#2
0
    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)
示例#3
0
 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()
示例#4
0
 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()
示例#5
0
 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()
示例#6
0
 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
示例#7
0
    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
示例#8
0
    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)