示例#1
0
def scan(scan_id):

    try:

        #
        # See if the scan exists.
        #

        scan = get_scan(cfg['api']['url'], scan_id)
        if not scan:
            logger.error("Cannot load scan %s" % scan_id)
            return

        #
        # Is the scan in the right state to be started?
        #

        if scan['state'] != 'QUEUED':
            logger.error("Scan %s has invalid state. Expected QUEUED but got %s" % (scan_id, scan['state']))
            return

        #
        # Move the scan to the STARTED state
        #

        scan['state'] = 'STARTED'
        send_task("minion.backend.tasks.scan_start",
                  [scan_id, time.time()],
                  queue='state').get()

        #
        # Check this site against the access control lists
        #

        if not scannable(scan['configuration']['target'],
                         scan_config().get('whitelist', []),
                         scan_config().get('blacklist', [])):
            failure = {"hostname": socket.gethostname(),
                       "reason": "target-blacklisted",
                       "message": "The target cannot be scanned by Minion because its (IPv4) address has been blacklisted."}
            return set_finished(scan_id, 'ABORTED', failure=failure)

        #
        # Verify ownership prior to running scan
        #

        target = scan['configuration']['target']
        site = get_site_info(cfg['api']['url'], target)
        if not site:
            return set_finished(scan_id, 'ABORTED')

        if site.get('verification') and site['verification']['enabled']:
            verified = ownership.verify(target, site['verification']['value'])
            if not verified:
                failure = {"hostname": socket.gethostname(),
                           "reason": "target-ownership-verification-failed",
                           "message": "The target cannot be scanned because the ownership verification failed."}
                return set_finished(scan_id, 'ABORTED', failure=failure)

        #
        # Run each plugin session
        #

        for session in scan['sessions']:

            #
            # Mark the session as QUEUED
            #

            session['state'] = 'QUEUED'
            #scans.update({"id": scan['id'], "sessions.id": session['id']}, {"$set": {"sessions.$.state": "QUEUED", "sessions.$.queued": datetime.datetime.utcnow()}})
            send_task("minion.backend.tasks.session_queue",
                      [scan['id'], session['id'], time.time()],
                      queue='state').get()

            #
            # Execute the plugin. The plugin worker will set the session state and issues.
            #

            logger.info("Scan %s running plugin %s" % (scan['id'], session['plugin']['class']))

            queue = queue_for_session(session, cfg)
            result = send_task("minion.backend.tasks.run_plugin",
                               [scan_id, session['id']],
                               queue=queue)

            #scans.update({"id": scan_id, "sessions.id": session['id']}, {"$set": {"sessions.$._task": result.id}})
            send_task("minion.backend.tasks.session_set_task_id",
                      [scan_id, session['id'], result.id],
                      queue='state').get()

            try:
                plugin_result = result.get()
            except TaskRevokedError as e:
                plugin_result = "STOPPED"

            session['state'] = plugin_result

            #
            # If the user stopped the workflow or if the plugin aborted then stop the whole scan
            #

            if plugin_result in ('ABORTED', 'STOPPED'):
                # Mark the scan as failed
                #scans.update({"id": scan_id}, {"$set": {"state": plugin_result, "finished": datetime.datetime.utcnow()}})
                send_task("minion.backend.tasks.scan_finish",
                          [scan_id, plugin_result, time.time()],
                          queue='state').get()
                # Mark all remaining sessions as cancelled
                for s in scan['sessions']:
                    if s['state'] == 'CREATED':
                        s['state'] = 'CANCELLED'
                        #scans.update({"id": scan['id'], "sessions.id": s['id']}, {"$set": {"sessions.$.state": "CANCELLED", "sessions.$.finished": datetime.datetime.utcnow()}})
                        send_task("minion.backend.tasks.session_finish",
                                  [scan['id'], s['id'], "CANCELLED", time.time()],
                                  queue='state').get()
                # We are done with this scan
                return

        #
        # Move the scan to the FINISHED state
        #

        scan['state'] = 'FINISHED'
        #scans.update({"id": scan_id}, {"$set": {"state": "FINISHED", "finished": datetime.datetime.utcnow()}})
        send_task("minion.backend.tasks.scan_finish",
                  [scan_id, "FINISHED", time.time()],
                  queue='state').get()

    except Exception as e:

        #
        # Our exception strategy is simple: if anything was thrown above that we did not explicitly catch then
        # we assume there was a non recoverable error that made the scan fail. We mark it as such and
        # record the exception.
        #

        logger.exception("Error while running scan. Marking scan FAILED.")

        try:
            failure = { "hostname": socket.gethostname(),
                        "reason": "backend-exception",
                        "message": str(e),
                        "exception": traceback.format_exc() }
            send_task("minion.backend.tasks.scan_finish",
                      [scan_id, "FAILED", time.time(), failure],
                      queue='state').get()
        except Exception as e:
            logger.exception("Error when marking scan as FAILED")
示例#2
0
def scan(scan_id):

    try:

        #
        # See if the scan exists.
        #

        scan = get_scan(cfg['api']['url'], scan_id)
        if not scan:
            logger.error("Cannot load scan %s" % scan_id)
            return

        #
        # Is the scan in the right state to be started?
        #

        if scan['state'] != 'QUEUED':
            logger.error(
                "Scan %s has invalid state. Expected QUEUED but got %s" %
                (scan_id, scan['state']))
            return

        #
        # Move the scan to the STARTED state
        #

        scan['state'] = 'STARTED'
        send_task("minion.backend.tasks.scan_start",
                  [scan_id, time.time()],
                  queue='state').get()

        #
        # Check this site against the access control lists
        #

        if not scannable(scan['configuration']['target'],
                         scan_config().get('whitelist', []),
                         scan_config().get('blacklist', [])):
            failure = {
                "hostname":
                socket.gethostname(),
                "reason":
                "target-blacklisted",
                "message":
                "The target cannot be scanned by Minion because its IP address or hostname has been blacklisted."
            }
            return set_finished(scan_id, 'ABORTED', failure=failure)

        #
        # Verify ownership prior to running scan
        #

        target = scan['configuration']['target']
        site = get_site_info(cfg['api']['url'], target)
        if not site:
            return set_finished(scan_id, 'ABORTED')

        if site.get('verification') and site['verification']['enabled']:
            verified = ownership.verify(target, site['verification']['value'])
            if not verified:
                failure = {
                    "hostname":
                    socket.gethostname(),
                    "reason":
                    "target-ownership-verification-failed",
                    "message":
                    "The target cannot be scanned because the ownership verification failed."
                }
                return set_finished(scan_id, 'ABORTED', failure=failure)

        #
        # Run each plugin session
        #

        for session in scan['sessions']:

            #
            # Mark the session as QUEUED
            #

            session['state'] = 'QUEUED'
            #scans.update({"id": scan['id'], "sessions.id": session['id']}, {"$set": {"sessions.$.state": "QUEUED", "sessions.$.queued": datetime.datetime.utcnow()}})
            send_task("minion.backend.tasks.session_queue",
                      [scan['id'], session['id'],
                       time.time()],
                      queue='state').get()

            #
            # Execute the plugin. The plugin worker will set the session state and issues.
            #

            logger.info("Scan %s running plugin %s" %
                        (scan['id'], session['plugin']['class']))

            queue = queue_for_session(session, cfg)
            result = send_task("minion.backend.tasks.run_plugin",
                               [scan_id, session['id']],
                               queue=queue)

            #scans.update({"id": scan_id, "sessions.id": session['id']}, {"$set": {"sessions.$._task": result.id}})
            send_task("minion.backend.tasks.session_set_task_id",
                      [scan_id, session['id'], result.id],
                      queue='state').get()

            try:
                plugin_result = result.get()
            except TaskRevokedError as e:
                plugin_result = "STOPPED"

            session['state'] = plugin_result

            #
            # If the user stopped the workflow or if the plugin aborted then stop the whole scan
            #

            if plugin_result in ('ABORTED', 'STOPPED'):
                # Mark the scan as failed
                #scans.update({"id": scan_id}, {"$set": {"state": plugin_result, "finished": datetime.datetime.utcnow()}})
                send_task("minion.backend.tasks.scan_finish",
                          [scan_id, plugin_result,
                           time.time()],
                          queue='state').get()
                # Mark all remaining sessions as cancelled
                for s in scan['sessions']:
                    if s['state'] == 'CREATED':
                        s['state'] = 'CANCELLED'
                        #scans.update({"id": scan['id'], "sessions.id": s['id']}, {"$set": {"sessions.$.state": "CANCELLED", "sessions.$.finished": datetime.datetime.utcnow()}})
                        send_task(
                            "minion.backend.tasks.session_finish",
                            [scan['id'], s['id'], "CANCELLED",
                             time.time()],
                            queue='state').get()
                # We are done with this scan
                return

        #
        # Move the scan to the FINISHED state
        #

        scan['state'] = 'FINISHED'

        #
        # If one of the plugin has failed then marked the scan as failed
        #
        for session in scan['sessions']:
            if session['state'] == 'FAILED':
                scan['state'] = 'FAILED'

        #scans.update({"id": scan_id}, {"$set": {"state": "FINISHED", "finished": datetime.datetime.utcnow()}})
        send_task("minion.backend.tasks.scan_finish",
                  [scan_id, scan['state'], time.time()],
                  queue='state').get()

    except Exception as e:

        #
        # Our exception strategy is simple: if anything was thrown above that we did not explicitly catch then
        # we assume there was a non recoverable error that made the scan fail. We mark it as such and
        # record the exception.
        #

        logger.exception("Error while running scan. Marking scan FAILED.")

        try:
            failure = {
                "hostname": socket.gethostname(),
                "reason": "backend-exception",
                "message": str(e),
                "exception": traceback.format_exc()
            }
            send_task(
                "minion.backend.tasks.scan_finish",
                [scan_id, "FAILED", time.time(), failure],
                queue='state').get()
        except Exception as e:
            logger.exception("Error when marking scan as FAILED")
示例#3
0
 def test_regular_targets(self):
     for target in self.regular_targets:
         self.assertTrue(scannable(target, self.whitelist, self.blacklist),
                         "Target is " + target)
示例#4
0
 def test_blacklisted_targets(self):
     for target in self.blacklisted_targets:
         self.assertFalse(scannable(target, self.whitelist, self.blacklist),
                          "Target is " + target)
 def test_regular_targets(self):
     for target in self.regular_targets:
         self.assertTrue(scannable(target, self.whitelist, self.blacklist),
                         "Target is " + target)
 def test_blacklisted_targets(self):
     for target in self.blacklisted_targets:
         self.assertFalse(scannable(target, self.whitelist, self.blacklist),
                          "Target is " + target)