def test_sort_credentials_target(self, test_client, second_workspace): host = HostFactory(workspace=second_workspace, ip="192.168.1.1") service = ServiceFactory(name="http", workspace=second_workspace, host=host) host2 = HostFactory(workspace=second_workspace, ip="192.168.1.2") service2 = ServiceFactory(name="ssh", workspace=second_workspace, host=host2) credential = self.factory.create(service=service, host=None, workspace=second_workspace) credential2 = self.factory.create(service=None, host=host2, workspace=second_workspace) credential3 = self.factory.create(service=None, host=host, workspace=second_workspace) credential4 = self.factory.create(service=service2, host=None, workspace=second_workspace) credentials_target = [ "{}/{}".format(credential.service.host.ip, credential.service.name), "{}".format(credential2.host.ip), "{}".format(credential3.host.ip), "{}/{}".format(credential4.service.host.ip, credential4.service.name), ] # Desc order response = test_client.get(self.url(workspace=second_workspace) + "?sort=target&sort_dir=desc") assert response.status_code == 200 assert sorted(credentials_target, reverse=True) == [ v['value']['target'] for v in response.json['rows']] # Asc order response = test_client.get(self.url(workspace=second_workspace) + "?sort=target&sort_dir=asc") assert response.status_code == 200 assert sorted(credentials_target) == [v['value']['target'] for v in response.json['rows']]
def test_bulk_delete_hosts_from_another_workspace(self, test_client, session): workspace_1 = WorkspaceFactory.create(name='workspace_1') host_of_ws_1 = HostFactory.create(workspace=workspace_1) workspace_2 = WorkspaceFactory.create(name='workspace_2') host_of_ws_2 = HostFactory.create(workspace=workspace_2) session.commit() # Try to delete workspace_2's host from workspace_1 request_data = {'hosts_ids': [host_of_ws_2.id]} url = f'/v2/ws/{workspace_1.name}/hosts/bulk_delete/' delete_response = test_client.delete(url, data=request_data) assert delete_response.json['deleted_hosts'] == 0
def test_add_ref_to_duplicated_vuln(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace) vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', name='Duplicated Vuln', host=host, service=None) duplicated_vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', name='Duplicated Vuln 2', host=host, service=None) session.add(workspace) session.add(vuln) session.add(duplicated_vuln) session.add(host) session.commit() first_vuln_id = vuln.id searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'ADD_REFS_DUPLICATED_VULNS', 'model': 'Vulnerability', 'fields': ['name'], 'object': "severity=low --old", # Without --old param Searcher deletes all duplicated objects 'conditions': ['severity=low'], 'actions': ["--UPDATE:refs=REF_TEST"] }] vulns_count = session.query(Vulnerability).filter_by(workspace=workspace).count() assert vulns_count == 2 searcher.process(rules) vuln1 = session.query(Vulnerability).get(first_vuln_id) assert len(vuln1.references) > 0 assert list(vuln1.references)[0] == 'REF_TEST'
def test_remove_duplicated_by_name(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace) vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', name='Duplicated Vuln', host=host, service=None) duplicated_vuln = VulnerabilityFactory.create(workspace=workspace, severity='low', name='Duplicated Vuln 2', host=host, service=None) session.add(workspace) session.add(vuln) session.add(duplicated_vuln) session.add(host) session.commit() searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'REMOVE_DUPLICATED_VULNS', 'model': 'Vulnerability', 'fields': ['name'], 'object': "severity=low --old", # Without --old param Searcher deletes all duplicated objects 'actions': ["--DELETE:"] }] vulns_count = session.query(Vulnerability).filter_by(workspace=workspace).count() assert vulns_count == 2 searcher.process(rules) vulns_count = session.query(Vulnerability).filter_by(workspace=workspace).count() assert vulns_count == 1
def test_update_with_parent_of_other_workspace(self, parent_type, parent_factory, test_client, session, second_workspace, credential_factory): parent = parent_factory.create(workspace=second_workspace) if parent_type == 'Host': credential = credential_factory.create( host=HostFactory.create(workspace=self.workspace), service=None, workspace=self.workspace) else: credential = credential_factory.create( host=None, service=ServiceFactory.create(workspace=self.workspace), workspace=self.workspace) session.commit() assert parent.workspace_id != self.workspace.id data = { "username": "******", "password": "******", "name": "test", "parent_type": parent_type, "parent": parent.id } res = test_client.put(self.url(credential), data=data) assert res.status_code == 400 assert b'Parent id not found' in res.data
def test_delete_objects_preserve_history(self, session, test_client): command = EmptyCommandFactory(command='test', tool='test', workspace=self.workspace) host = HostFactory.create(workspace=self.workspace) session.add(host) session.commit() CommandObjectFactory.create(command=command, object_type='host', object_id=host.id, workspace=self.workspace) session.commit() res = test_client.get(u'/v2/ws/{0}/hosts/{1}/'.format( host.workspace.name, host.id)) assert res.status_code == 200 res = test_client.delete(u'/v2/ws/{0}/hosts/{1}/'.format( host.workspace.name, host.id)) assert res.status_code == 204 res = test_client.get( self.url(workspace=command.workspace) + 'activity_feed/') assert res.status_code == 200 command_history = list( filter(lambda hist: hist['_id'] == command.id, res.json)) assert len(command_history) command_history = command_history[0] assert command_history['hosts_count'] == 1 assert command_history['tool'] == 'test'
def test_update_host_with_all_fields(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace, os='Unix', ip="10.25.86.39", owned=False, description='HDesc', mac='MAC') session.add(workspace) session.add(host) session.commit() assert host.owned is False assert host.os == 'Unix' assert host.ip == "10.25.86.39" assert host.description == 'HDesc' assert host.mac == 'MAC' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'UPDATE_HOST', 'model': 'Host', 'object': "ip=10.25.86.39 owned=False os=Unix", 'actions': ["--UPDATE:description=HDescUp", "--UPDATE:mac=MAC2"] }] searcher.process(rules) host = session.query(Host).filter_by(workspace=workspace).first() assert host.description == 'HDescUp' assert host.mac == 'MAC2'
def test_update_severity_by_creator(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace) user = UserFactory.create() vuln = VulnerabilityFactory.create(workspace=workspace, tool='Nessus', severity='low', host=host, creator=user, service=None) session.add(workspace) session.add(vuln) session.add(host) session.commit() vuln_id = vuln.id assert vuln.severity == 'low' searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CHANGE_SEVERITY_INSIDE_HOST', 'model': 'Vulnerability', 'object': f'creator={user.username}', # Without --old param Searcher deletes all duplicated objects 'conditions': ['tool=Nessus'], 'actions': ["--UPDATE:severity=info"] }] searcher.process(rules) vuln = session.query(Vulnerability).get(vuln_id) assert vuln.severity == 'informational'
def test_bulk_delete_hosts_wrong_content_type(self, test_client, session): ws = WorkspaceFactory.create(name="abc") host_1 = HostFactory.create(workspace=ws) host_2 = HostFactory.create(workspace=ws) session.commit() hosts_ids = [host_1.id, host_2.id] request_data = {'hosts_ids': hosts_ids} headers = [('content-type', 'text/xml')] delete_response = test_client.delete( f'/v2/ws/{ws.name}/hosts/bulk_delete/', data=request_data, headers=headers) assert delete_response.status_code == 400
def test_child_parent_verification_event_succeds_update(session, workspace): host = HostFactory.build(workspace=workspace) service = ServiceFactory.build(host=host, workspace=workspace) session.commit() service.workspace = workspace session.add(service) session.commit()
def test_child_parent_verification_event_succeeds(session, workspace): """ Asserts that no exception will be raised when workspace are the same. """ host = HostFactory.build(workspace=workspace) ServiceFactory.build(host=host, workspace=workspace) session.commit()
def test_verify_created_vulns_with_host_and_service_verification( self, session, test_client): workspace = WorkspaceFactory.create() command = EmptyCommandFactory.create(workspace=workspace) host = HostFactory.create(workspace=workspace) service = ServiceFactory.create(workspace=workspace) vuln = VulnerabilityFactory.create(severity='critical', workspace=workspace, host=host, service=None) vuln_med = VulnerabilityFactory.create(severity='medium', workspace=workspace, service=service, host=None) session.flush() CommandObjectFactory.create(command=command, object_type='host', object_id=host.id, workspace=workspace) CommandObjectFactory.create(command=command, object_type='vulnerability', object_id=vuln.id, workspace=workspace) CommandObjectFactory.create(command=command, object_type='service', object_id=service.id, workspace=workspace) CommandObjectFactory.create(command=command, object_type='vulnerability', object_id=vuln_med.id, workspace=workspace) session.commit() res = test_client.get( self.url(workspace=command.workspace) + 'activity_feed/') assert res.status_code == 200 assert res.json == [{ u'_id': command.id, u'command': command.command, u'import_source': u'shell', u'tool': command.tool, u'user': command.user, u'date': time.mktime(command.start_date.timetuple()) * 1000, u'params': command.params, u'hosts_count': 1, u'services_count': 1, u'vulnerabilities_count': 2, u'criticalIssue': 1 }]
def test_update_cant_change_id(self, test_client, session): service = self.factory() host = HostFactory.create() session.commit() raw_data = self._raw_put_data(service.id) res = test_client.put(self.url(service, workspace=service.workspace), data=raw_data) assert res.status_code == 200 assert res.json['id'] == service.id
def populate_workspace(workspace): host = HostFactory.create(workspace=workspace) service = ServiceFactory.create(workspace=workspace, host=host) code = SourceCodeFactory.create(workspace=workspace) # Create non confirmed vulnerabilities # Create standard vulns VulnerabilityFactory.create_batch(NC_STANDARD_VULN_COUNT[0], workspace=workspace, host=host, service=None, confirmed=False) VulnerabilityFactory.create_batch(NC_STANDARD_VULN_COUNT[1], workspace=workspace, service=service, host=None, confirmed=False) # Create web vulns VulnerabilityWebFactory.create_batch(NC_WEB_VULN_COUNT, workspace=workspace, service=service, confirmed=False) # Create source code vulns VulnerabilityCodeFactory.create_batch(NC_SOURCE_CODE_VULN_COUNT, workspace=workspace, source_code=code, confirmed=False) # Create confirmed vulnerabilities # Create standard vulns VulnerabilityFactory.create_batch(C_STANDARD_VULN_COUNT[0], workspace=workspace, host=host, service=None, confirmed=True) VulnerabilityFactory.create_batch(C_STANDARD_VULN_COUNT[1], workspace=workspace, service=service, host=None, confirmed=True) # Create web vulns VulnerabilityWebFactory.create_batch(C_WEB_VULN_COUNT, workspace=workspace, service=service, confirmed=True) # Create source code vulns VulnerabilityCodeFactory.create_batch(C_SOURCE_CODE_VULN_COUNT, workspace=workspace, source_code=code, confirmed=True) db.session.commit()
def test_bulk_delete_hosts(self, test_client, session): ws = WorkspaceFactory.create(name="abc") host_1 = HostFactory.create(workspace=ws) host_2 = HostFactory.create(workspace=ws) session.commit() hosts_ids = [host_1.id, host_2.id] request_data = {'hosts_ids': hosts_ids} delete_response = test_client.delete(f'/v2/ws/{ws.name}/hosts/bulk_delete/', data=request_data) deleted_hosts = delete_response.json['deleted_hosts'] host_count_after_delete = db.session.query(Host).filter( Host.id.in_(hosts_ids), Host.workspace_id == ws.id).count() assert delete_response.status_code == 200 assert deleted_hosts == len(hosts_ids) assert host_count_after_delete == 0
def test_hosts_ordered_by_vulns_severity(self, session, test_client, service_factory, vulnerability_factory, vulnerability_web_factory): ws = WorkspaceFactory.create() session.add(ws) hosts_list = [] for i in range(0, 10): host = HostFactory.create(workspace=ws) session.add(host) service = service_factory.create(workspace=ws, host=host) session.add(service) hosts_list.append(host) session.commit() severities = ['critical', 'high', 'medium', 'low', 'informational', 'unclassified'] # Vulns counter by severity in host vulns_by_severity = {host.id: [0, 0, 0, 0, 0, 0] for host in hosts_list} for host in hosts_list: # Each host has 10 vulns for i in range(0, 10): vuln_web = choice([True, False]) severity = choice(severities) if vuln_web: vuln = vulnerability_web_factory.create( workspace=ws, service=host.services[0], severity=severity ) else: vuln = vulnerability_factory.create( host=None, service=host.services[0], workspace=host.workspace, severity=severity ) session.add(vuln) # Increase 1 to number of vulns by severity in the host vulns_by_severity[host.id][severities.index(severity)] += 1 session.commit() # Sort vulns_by_severity by number of vulns by severity in every host sorted_hosts = sorted( vulns_by_severity.items(), key=lambda host: [vuln_count for vuln_count in host[1]], reverse=True ) res = test_client.get(self.url(workspace=ws)) assert res.status_code == 200 response_hosts = res.json['rows'] for host in response_hosts: # sorted_hosts and response_hosts have the same order so the index # of host in sorted_host is the same as the # index of host in response_hosts index_in_sorted_host = [host_tuple[0] for host_tuple in sorted_hosts].index(host['id']) index_in_response_hosts = response_hosts.index(host) assert index_in_sorted_host == index_in_response_hosts
def test_child_parent_verification_event_fails_update(session, workspace, second_workspace): host = HostFactory.build(workspace=workspace) service = ServiceFactory.build(host=host, workspace=workspace) session.commit() service.workspace = second_workspace session.add(service) with pytest.raises(AssertionError): session.commit()
def test_update_cant_change_parent(self, test_client, session): service = self.factory() host = HostFactory.create() session.commit() raw_data = self._raw_put_data(service.id, parent=host.id) res = test_client.put(self.url(service, workspace=service.workspace), data=raw_data) assert res.status_code == 400 assert b'Can\'t change service parent.' in res.data updated_service = Service.query.filter_by(id=service.id).first() assert updated_service.name == service.name
def test_child_parent_verification_event_fails(session, workspace, second_workspace): host = HostFactory.build(workspace=workspace) ServiceFactory.build(host=host, workspace=second_workspace) with pytest.raises(AssertionError): session.commit() session.rollback() assert session.query(Host).filter( Workspace.id == workspace.id).first() == None
async def hosts(num_hosts, is_host_secure): _hosts = HostFactory.create_batch(num_hosts, is_secure=is_host_secure) await asyncio.gather( *[_host.get_network().listen(LISTEN_MADDR) for _host in _hosts]) try: yield _hosts finally: # TODO: It's possible that `close` raises exceptions currently, # due to the connection reset things. Though we don't care much about that when # cleaning up the tasks, it is probably better to handle the exceptions properly. await asyncio.gather(*[_host.close() for _host in _hosts], return_exceptions=True)
def test_load_ports_with_negative_value(self, test_client, session): host = HostFactory.create(workspace=self.workspace) session.commit() data = { "name": "ports", "description": "testing ports load", "owned": False, "ports": [-1], "protocol": "tcp", "status": "open", "parent": host.id } res = test_client.post(self.url(), data=data) assert res.status_code == 400
def test_child_parent_verification_event_changing_id_fails(session, workspace, second_workspace): session.add(workspace) session.add(second_workspace) session.commit() host = HostFactory.build(workspace=workspace) session.add(host) session.commit() service = ServiceFactory.build(host=host, workspace_id=second_workspace.id) session.add(service) with pytest.raises(AssertionError): session.commit()
def test_update_severity_inside_one_host(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace) vuln1 = VulnerabilityFactory.create(workspace=workspace, severity='low', host=host, service=None) vuln2 = VulnerabilityFactory.create(workspace=workspace, severity='low', host=host, service=None) session.add(workspace) session.add(vuln1) session.add(vuln2) session.add(host) session.commit() parent_id = host.id first_vuln_id = vuln1.id second_vuln_id = vuln2.id assert vuln1.severity == 'low' assert vuln2.severity == 'low' assert vuln1.parent.id == parent_id assert vuln2.parent.id == parent_id searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'CHANGE_SEVERITY_INSIDE_HOST', 'model': 'Vulnerability', 'parent': parent_id, 'object': "severity=low", # Without --old param Searcher deletes all duplicated objects 'conditions': ['severity=low'], 'actions': ["--UPDATE:severity=info"] }] searcher.process(rules) vuln1 = session.query(Vulnerability).get(first_vuln_id) vuln2 = session.query(Vulnerability).get(second_vuln_id) assert vuln1.severity == 'informational' assert vuln2.severity == 'informational'
def test_verify_created_critical_vulns_is_correctly_showing_sum_values(self, session, test_client): workspace = WorkspaceFactory.create() command = EmptyCommandFactory.create(workspace=workspace) host = HostFactory.create(workspace=workspace) vuln = VulnerabilityFactory.create(severity='critical', workspace=workspace, host=host, service=None) vuln_med = VulnerabilityFactory.create(severity='medium', workspace=workspace, host=host, service=None) session.flush() CommandObjectFactory.create( command=command, object_type='host', object_id=host.id, workspace=workspace ) CommandObjectFactory.create( command=command, object_type='vulnerability', object_id=vuln.id, workspace=workspace ) CommandObjectFactory.create( command=command, object_type='vulnerability', object_id=vuln_med.id, workspace=workspace ) session.commit() res = test_client.get(urljoin(self.url(workspace=command.workspace), 'activity_feed')) assert res.status_code == 200 assert res.json == [ {'_id': command.id, 'command': command.command, 'import_source': 'shell', 'tool': command.tool, 'user': command.user, 'date': time.mktime(command.start_date.timetuple()) * 1000, 'params': command.params, 'hosts_count': 1, 'services_count': 0, 'vulnerabilities_count': 2, 'criticalIssue': 1} ]
def test_update_host(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace, ip="10.25.86.39", owned=False) session.add(workspace) session.add(host) session.commit() assert host.owned is False searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'UPDATE_HOST', 'model': 'Host', 'object': "ip=10.25.86.39", 'actions': ["--UPDATE:owned=True"] }] searcher.process(rules) host = session.query(Host).filter_by(workspace=workspace).first() assert host.owned is True
def test_update_hostname(self, session, test_client): host = HostFactory.create() session.add(host) session.commit() data = { "description":"", "default_gateway":"", "ip":"127.0.0.1", "owned":False, "name":"127.0.0.1", "mac":"", "hostnames":["dasdas"], "owner":"faraday", "os":"Unknown", } res = test_client.put(f'v2/ws/{host.workspace.name}/hosts/{host.id}/', data=data) assert res.status_code == 200 assert session.query(Hostname).filter_by(host=host).count() == 1 assert session.query(Hostname).all()[0].name == 'dasdas'
def test_create_service_from_command(self, test_client, session): host = HostFactory.create(workspace=self.workspace) command = EmptyCommandFactory.create(workspace=self.workspace) session.commit() assert len(command.command_objects) == 0 url = self.url(workspace=command.workspace) + '?' + urlencode({'command_id': command.id}) raw_data = { "name": "SSH", "description": "SSH service", "owned": False, "ports": [22], "protocol": "tcp", "status": "open", "parent": host.id } res = test_client.post(url, data=raw_data) assert res.status_code == 201 assert len(command.command_objects) == 1 cmd_obj = command.command_objects[0] assert cmd_obj.object_type == 'service' assert cmd_obj.object_id == res.json['id']
def test_delete_host(self, api, session, test_client): workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace, ip="10.25.86.39") session.add(workspace) session.add(host) session.commit() searcher = Searcher(api(workspace, test_client, session)) rules = [{ 'id': 'DELETE_HOST', 'model': 'Host', 'object': "ip=10.25.86.39", 'actions': ["--DELETE:"] }] host_count = session.query(Host).filter_by(workspace=workspace).count() assert host_count == 1 searcher.process(rules) host_count = session.query(Host).filter_by(workspace=workspace).count() assert host_count == 0
def test_hosts_order_without_vulns(self, session, test_client): # If a host has no vulns, it should be ordered by IP in ascending order ws = WorkspaceFactory.create() session.add(ws) hosts_ids = [] for i in range(0, 10): host = HostFactory.create(workspace=ws, ip=f'127.0.0.{i}') session.add(host) session.commit() hosts_ids.append(host.id) res = test_client.get(self.url(workspace=ws)) assert res.status_code == 200 response_hosts = res.json['rows'] for host in response_hosts: # hosts_ids and response_hosts have the same order so the index # of host in hosts_ids is the same as the # index of host in response_hosts index_in_hosts_ids = hosts_ids.index(host['id']) index_in_response_hosts = response_hosts.index(host) assert index_in_hosts_ids == index_in_response_hosts
def test_multiple_commands_executed_with_same_objects_found( self, session, test_client): """ This text verifies that multiple command does not affect activity feed counters. """ workspace = WorkspaceFactory.create() host = HostFactory.create(workspace=workspace) vuln = VulnerabilityFactory.create(severity='low', workspace=workspace, host=host, service=None) service = ServiceFactory.create(workspace=workspace) commands = [] in_the_middle_commands = [] first_command = None for index in range(0, 10): command = EmptyCommandFactory.create(workspace=workspace) commands.append(command) if index > 0: # in the middle commands should not affect counters (should be at 0) in_the_middle_commands.append(command) else: first_command = command session.flush() CommandObjectFactory.create(command=command, object_type='host', object_id=host.id, workspace=workspace) CommandObjectFactory.create(command=command, object_type='vulnerability', object_id=vuln.id, workspace=workspace) # This command will change activity feed counters vuln_med = VulnerabilityFactory.create(severity='medium', workspace=workspace, service=service, host=None) session.flush() last_command = EmptyCommandFactory.create(workspace=workspace) CommandObjectFactory.create(command=last_command, object_type='service', object_id=service.id, workspace=workspace) CommandObjectFactory.create(command=last_command, object_type='vulnerability', object_id=vuln_med.id, workspace=workspace) session.commit() res = test_client.get( self.url(workspace=command.workspace) + 'activity_feed/') assert res.status_code == 200 raw_first_command = list( filter(lambda comm: comm['_id'] == commands[0].id, res.json)) assert raw_first_command.pop() == { u'_id': first_command.id, u'command': first_command.command, u'import_source': u'shell', u'user': first_command.user, u'date': time.mktime(first_command.start_date.timetuple()) * 1000, u'params': first_command.params, u'hosts_count': 1, u'services_count': 0, u'vulnerabilities_count': 1, u'tool': first_command.tool, u'criticalIssue': 0 } for in_the_middle_command in in_the_middle_commands: raw_in_the_middle_command = list( filter(lambda comm: comm['_id'] == in_the_middle_command.id, res.json)) assert raw_in_the_middle_command.pop() == { u'_id': in_the_middle_command.id, u'command': in_the_middle_command.command, u'import_source': u'shell', u'user': in_the_middle_command.user, u'date': time.mktime(in_the_middle_command.start_date.timetuple()) * 1000, u'params': in_the_middle_command.params, u'hosts_count': 0, u'tool': in_the_middle_command.tool, u'services_count': 0, u'vulnerabilities_count': 0, u'criticalIssue': 0 } # new command must create new service and vuln raw_last_command = list( filter(lambda comm: comm['_id'] == last_command.id, res.json)) assert raw_last_command.pop() == { u'_id': last_command.id, u'command': last_command.command, u'import_source': u'shell', u'user': last_command.user, u'date': time.mktime(last_command.start_date.timetuple()) * 1000, u'params': last_command.params, u'hosts_count': 0, u'tool': last_command.tool, u'services_count': 1, u'vulnerabilities_count': 1, u'criticalIssue': 0 }