def test_wrong_object(self):
        target = Target("192.167.1.1")
        assert target.name == "192.167.1.1"

        with pytest.raises(AssertionError):
            assert Target(None)
            assert Target(1)
    def test_patterns(self):
        target = Target("192.167.1.1")
        assert target.name == "192.167.1.1"

        with pytest.raises(AssertionError):
            assert Target("169.254.169.254")
            assert Target("127.0.0.1")
            assert Target("http://github.com")
    def test_resolves_validity(self):
        target = Target("ssh.mozilla.com")
        assert target.name == "ssh.mozilla.com"
        target = Target(u'ssh.mozilla.com')
        assert target.name == u'ssh.mozilla.com'
        target = Target("github.com")
        assert target.name == "github.com"

        with pytest.raises(AssertionError):
            assert Target("notarealdomainname.mozilla.com")
    def test_private_addresses(self):
        target = Target("192.167.1.1")
        assert target.name == "192.167.1.1"

        target = Target("192.169.1.1")
        assert target.name == "192.169.1.1"

        with pytest.raises(AssertionError):
            assert Target("192.168.1.1")
            assert Target("10.0.0.0.1")
            assert Target("172.16.0.0.1")
    def queue(self, event, context):
        # print("Event: {}, context: {}".format(event, context.invoked_function_arn))
        source_event = Event(event, context)
        data = source_event.parse()
        if data:
            target = Target(data.get('target'))
            if not target:
                self.logger.error("Target validation failed of: {}".format(target.name))
                return Response({
                    "statusCode": 400,
                    "body": json.dumps({'error': 'Target was not valid or missing'})
                }).with_security_headers()

            scan_uuid = str(uuid.uuid4())

            self.sqs_client.send_message(
                QueueUrl=self.queueURL,
                MessageBody="portscan|" + target.name
                + "|" + scan_uuid
            )
            # Use a UUID for the scan type and return it
            return Response({
                "statusCode": 200,
                "body": json.dumps({'uuid': scan_uuid})
            }).with_security_headers()
        else:
            self.logger.error("Unrecognized payload: {}".format(data))
            return Response({
                "statusCode": 400,
                "body": json.dumps({'error': 'Unrecognized payload'})
            }).with_security_headers()
    def formatForSNS(self, event, context):
        # This is a step function called from a state machine
        # Event type will always be "step-function"
        source_event = Event(event, context)
        data = source_event.parse()

        if data:
            target = Target(data.get('target'))
            if not target:
                self.logger.error("Target validation failed of: {}".format(
                    target.name))
                return False

            # Extract the dictionary here and signed URL
            output_tracker = event['responses']['Generatedownloadlink'][
                'output']
            signed_url = event['responses']['Generatedownloadlink']['url']
            contents = (target.name, output_tracker, signed_url)
            formatter = Formatter(self.logger)
            subject, body = formatter.formatForEmail(contents)

            return {'subject': subject, 'body': body}

        else:
            self.logger.error("Unrecognized payload: {}".format(data))
            return False
Esempio n. 7
0
    def generateDownloadLink(self, event, context):
        # This is a step function called from a state machine
        # Event type will always be "step-function"
        source_event = Event(event, context)
        data = source_event.parse()

        if data:
            target = Target(data.get('target'))
            if not target:
                self.logger.error("Target validation failed of: {}".format(
                    target.name))
                return False

            results = Results(target.name, self.s3_client, self.bucket,
                              self.base_results_path)
            status, output, download_url = results.generateURL()
            if download_url:
                return {
                    'status': status,
                    'output': output,
                    'url': download_url
                }
            else:
                if status == 404:
                    message = 'No results found for target'
                else:
                    message = 'Unknown error'
                return {'status': status, 'message': message}
        else:
            self.logger.error("Unrecognized payload: {}".format(data))
            return False
    def pollScanResults(self, event, context):
        # This function will take a Tenable.io scan ID, and
        # query Tenable.io API for the status of that scan, and
        # if completed, return the results a JSON object

        source_event = Event(event, context)
        data = source_event.parse()

        if data:
            target = Target(data.get('target'))
            if not target:
                self.logger.error("Target validation failed of: {}".format(
                    target.name))
                return False

            scanID = event['responses']['Tenablescan']['id']
            scanner = TIOScanner(logger=self.logger)
            json_result = scanner.scanResult(scanID, result_format="json")
            html_result = scanner.scanResult(scanID, result_format="html")
            if json_result and html_result:
                send_to_s3(target.name + "_tenablescan",
                           json_result,
                           client=self.s3_client,
                           bucket=self.s3_bucket)
                send_to_s3(target.name + "_tenablescan",
                           html_result,
                           client=self.s3_client,
                           bucket=self.s3_bucket)
                return {'statusCode': 200}
        else:
            self.logger.error("Unrecognized payload: {}".format(data))
            return False
Esempio n. 9
0
    def downloadResults(self, event, context):
        # This is a lambda function called from API GW
        # Event type will always be "api-gw"
        source_event = Event(event, context)
        data = source_event.parse()

        if data:
            target = Target(data.get('target'))
            if not target:
                self.logger.error("Target validation failed of: {}".format(
                    target.name))
                return Response({
                    "statusCode":
                    400,
                    "body":
                    json.dumps({'error': 'Target was not valid or missing'})
                }).with_security_headers()

            results = Results(target.name, self.s3_client, self.bucket,
                              self.base_results_path)
            # Always use the download route
            scan_results, status = results.download()
            if scan_results:
                return Response({
                    "statusCode":
                    status,
                    "headers": {
                        "Content-Type":
                        "application/gzip",
                        "Content-Disposition":
                        "attachment; filename={}.tgz".format(target.name)
                    },
                    "body":
                    base64.b64encode(scan_results.getvalue()).decode("utf-8"),
                    "isBase64Encoded":
                    True
                }).with_security_headers()
            else:
                if status == 404:
                    resp_body = 'No results found for target'
                elif status == 500:
                    resp_body = 'Unable to download scan results'
                else:
                    resp_body = 'Unknown error'
                return Response({
                    "statusCode": status,
                    "body": json.dumps({'error': resp_body})
                }).with_security_headers()
        else:
            self.logger.error("Unrecognized payload: {}".format(data))
            return Response({
                "statusCode":
                400,
                "body":
                json.dumps({'error': 'Unrecognized payload'})
            }).with_security_headers()
Esempio n. 10
0
def putInQueue(event, context):
    # For demo purposes, this function is invoked manually
    # Also for demo purposes, we will use a static list here
    # We need to figure out a way to put stuff in the queue regularly
    target_list = [
        "www.mozilla.org",
        "infosec.mozilla.org",
    ]
    hosts = Hosts(target_list)
    target = Target(hosts.next())
    SQS_CLIENT.send_message(QueueUrl=os.getenv('SQS_URL'),
                            MessageBody="manual|" + target.name)
Esempio n. 11
0
    def read_and_process_image(self, stream):
        start_time = time.time()
        original_img = stream.read()
        if original_img is None:
            return None

        filter = (60, 87, 120, 255, 50, 255)
        img = filters.apply_hsv_filter(original_img, filter)
        img = filters.erode(img, 1)
        img = filters.dilate(img, 1)

        target = Target(self.robot, img, original_img, self)
        target.acquire_target()
        if target.acquired == False:
            self.comms.send_no_target_message(start_time)
        else:
            self.comms.send_target_info_message(target, start_time)
        if self.width != self.output_width or self.height != self.output_height:
            target.annotated_image = cv2.resize(
                target.annotated_image,
                (self.output_width, self.output_height))
        return target.annotated_image
    def runFromStepFunction(self, event, context):
        source_event = Event(event, context)
        data = source_event.parse()

        if data:
            target = Target(data.get('target'))
            if not target:
                self.logger.error("Target validation failed of: {}".format(
                    target.name))
                return False

            # Run the scan here and return the ScanRef object
            scanner = TIOScanner(logger=self.logger)
            scanner_ref = scanner.scan(target.name)
            if scanner_ref:
                scanner_ref.launch(wait=False)
                return {'id': scanner_ref.id}
            else:
                return False
        else:
            self.logger.error("Unrecognized payload: {}".format(data))
            return False
Esempio n. 13
0
def test_assert_valid_function_call(call, result):
    assert Target.assert_valid_function_call(call) == result
Esempio n. 14
0
def test_parse_func_call(func_call, func_name, func_args):
    name, args = Target._parse_func_call(func_call)
    assert name == func_name
    assert args == func_args
Esempio n. 15
0
def test_parse_port():
    port = Target._parse_port('abc:123')
    assert port == 123
Esempio n. 16
0
    def getResults(self, event, context):
        # print("Event: {}, context: {}".format(event, context))
        source_event = Event(event, context)
        data = source_event.parse()
        print(source_event.type)

        if data:
            target = Target(data.get('target'))
            if not target:
                self.logger.error("Target validation failed of: {}".format(
                    target.name))
                return Response({
                    "statusCode":
                    400,
                    "body":
                    json.dumps({'error': 'Target was not valid or missing'})
                }).with_security_headers()

            results = Results(target.name, self.s3_client, self.bucket,
                              self.base_results_path)
            if source_event.type == "step-function":
                # Use generateURL route
                download_url, status = results.generateDownloadURL()
                if download_url:
                    return Response({
                        "statusCode": status,
                        "body": json.dumps({'url': download_url})
                    }).with_security_headers()
                else:
                    if status == 404:
                        resp_body = 'No results found for target'
                    else:
                        resp_body = 'Unknown error'
                    return Response({
                        "statusCode": status,
                        "body": json.dumps({'error': resp_body})
                    }).with_security_headers()
            else:
                # Use download route
                scan_results, status = results.download()
                if scan_results:
                    return Response({
                        "statusCode":
                        status,
                        "headers": {
                            "Content-Type":
                            "application/gzip",
                            "Content-Disposition":
                            "attachment; filename={}.tgz".format(target.name)
                        },
                        "body":
                        base64.b64encode(
                            scan_results.getvalue()).decode("utf-8"),
                        "isBase64Encoded":
                        True
                    }).with_security_headers()
                else:
                    if status == 404:
                        resp_body = 'No results found for target'
                    elif status == 500:
                        resp_body = 'Unable to download scan results'
                    else:
                        resp_body = 'Unknown error'
                    return Response({
                        "statusCode": status,
                        "body": json.dumps({'error': resp_body})
                    }).with_security_headers()

        else:
            self.logger.error("Unrecognized payload: {}".format(data))
            return Response({
                "statusCode":
                400,
                "body":
                json.dumps({'error': 'Unrecognized payload'})
            }).with_security_headers()
        sys.exit(-1)

# Establish a session with that profile
session = boto3.Session(profile_name=AWS_PROFILE)
# Programmatically obtain the API GW URL, and the REST API key
apigw_client = session.client('apigateway')
aws_response = apigw_client.get_api_keys(
    nameQuery='vautomator-serverless',
    includeValues=True)['items'][0]
rest_api_id, stage_name = "".join(aws_response['stageKeys']).split('/')
gwapi_key = aws_response['value']
API_GW_URL = "https://{}.execute-api.{}.amazonaws.com/".format(rest_api_id, session.region_name)

fqdn = input("Provide the FQDN (Fully Qualified Domain Name) you want to scan: ")
try:
    target = Target(fqdn)
except AssertionError:
    logging.error("Target validation failed: target must be an FQDN or IPv4 only.")
    sys.exit(-2)

portscan_url = API_GW_URL + "{}/ondemand/portscan".format(stage_name)
httpobs_scan_url = API_GW_URL + "{}/ondemand/httpobservatory".format(stage_name)
tlsobs_scan_url = API_GW_URL + "{}/ondemand/tlsobservatory".format(stage_name)
sshobs_scan_url = API_GW_URL + "{}/ondemand/sshobservatory".format(stage_name)
tenableio_scan_url = API_GW_URL + "{}/ondemand/tenablescan".format(stage_name)
direnum_scan_url = API_GW_URL + "{}/ondemand/direnum".format(stage_name)
websearch_url = API_GW_URL + "{}/ondemand/websearch".format(stage_name)

scan_types = {
    'port': portscan_url,
    'httpobservatory': httpobs_scan_url,
Esempio n. 18
0
                stats[hop]['total'] += 1
            stats[hop]['skipped'] += len(cands) == 0
    return stats


if __name__ == '__main__':
    H = range(1, 7)

    network = Network('./data/dataset_1000a.txt')

    isolated_nodes = [n for n, d in network.graph.degree() if d == 1]
    edges = [edge for edge in network.edges if edge[0] not in isolated_nodes and edge[1] not in isolated_nodes]

    num_targets = math.ceil(len(edges)/2)
    num_attackers = math.ceil(len(network.nodes)/2)
    targets = [Target(edge, network.graph, H)
               for edge in tqdm(random.sample(edges, num_targets))]
    attackers = random.sample(network.nodes, num_attackers)

    with Pool() as p:
        stats = p.map(attack, [(target, attackers) for target in targets])

    stats_h = {h: reduce(lambda x, y: Counter(x, **y),
                            [stat[h] for stat in stats])
                  for h in H}

    for h, stat in stats_h.items():
        print(f'Hop: {h}, Total: {stat["total"]}, Passed: {stat["passed"]}, Ratio: {stat["total"] and stat["passed"]/stat["total"]}')

    with open('stats.pkl', 'wb') as f:
        pickle.dump(stats_h, f)
parser.add_argument("-x", "--extract", help="Auto extract results", action="store_true")
parser.add_argument("--results", help="Specify a results directory", default=os.path.join(os.getcwd(), "results/"))
args = parser.parse_args()

# Establish a session with that profile if given
session = boto3.Session(profile_name=args.profile, region_name=args.region)
# Programmatically obtain the REST API key
apigw_client = session.client("apigateway")
aws_response = apigw_client.get_api_keys(nameQuery="vautomator-serverless", includeValues=True)["items"][0]
rest_api_id, stage_name = "".join(aws_response["stageKeys"]).split("/")
gwapi_key = aws_response["value"]
# We are now using a custom domain to host the API
custom_domain = "vautomator.security.allizom.org"

try:
    target = Target(args.fqdn)
except AssertionError:
    logging.error("Target validation failed: target must be an FQDN or IPv4 only.")
    sys.exit(127)

download_url = "https://{}".format(custom_domain) + "/api/results"
session = requests.Session()
session.headers.update({"X-Api-Key": gwapi_key, "Accept": "application/gzip", "Content-Type": "application/json"})

logging.info("Sending POST to {}".format(download_url))
response = session.post(download_url, data='{"target":"' + target.name + '"}', stream=True)
if (
    response.status_code == 200
    or response.status_code == 202
    and response.headers["Content-Type"] == "application/gzip"
):
Esempio n. 20
0
 def _start_debug_session_wrapper(self, *args):
     func_call = args[0]
     target = Target(self.database.dsn)
     proxy = Proxy(self.database.dsn)
     self._start_debug_session(func_call, target, proxy)