def main(args=None): if not HAS_NEO_MODULE: print( 'neo4j python module not found! Please install the module neo4j-driver first (pip install neo4j-driver)' ) return if args is None: parser = argparse.ArgumentParser( add_help=True, description='ROADrecon policies to HTML plugin', formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( '-d', '--database', action='store', help= 'Database file. Can be the local database name for SQLite, or an SQLAlchemy compatible URL such as postgresql+psycopg2://dirkjan@/roadtools', default='roadrecon.db') add_args(parser) args = parser.parse_args() db_url = database.parse_db_argument(args.database) if args.database_password is None: args.database_user, args.database_password = BloodHoundPlugin.detect_db_config( ) if args.database_password is None: print( 'Error: Could not autodetect the Neo4j database credentials from your BloodHound config. Please specify them manually' ) return session = database.get_session(database.init(dburl=db_url)) plugin = BloodHoundPlugin(session, args.neodatabase, args.database_user, args.database_password) plugin.main()
def main(args=None): if args is None: parser = argparse.ArgumentParser( add_help=True, description='ROADrecon policies to HTML plugin', formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( '-d', '--database', action='store', help= 'Database file. Can be the local database name for SQLite, or an SQLAlchemy compatible URL such as postgresql+psycopg2://dirkjan@/roadtools', default='roadrecon.db') add_args(parser) args = parser.parse_args() db_url = database.parse_db_argument(args.database) session = database.get_session(database.init(dburl=db_url)) plugin = AccessPoliciesPlugin(session, args.file) plugin.main(args.print)
def main(args=None): if args is None: parser = create_args_parser() args = parser.parse_args() db_url = database.parse_db_argument(args.database) session = database.get_session(database.init(dburl=db_url)) filename, file_extension = os.path.splitext(args.file) if not file_extension: file_extension = '.xlsx' if file_extension not in SUPPORTED_EXTENSIONS: print("%s is not a supported extention. Only %s are supported" % (file_extension, ', '.join(SUPPORTED_EXTENSIONS))) return plugin = ExportToFilePlugin(session, filename + file_extension, verbose=args.verbose) plugin.main() print("Data have been exported to the %s%s file" % (filename, file_extension))
async def run(args, dburl): global token, expiretime, headers if 'tenantId' in token: tenantid = token['tenantId'] elif args.tenant: tenantid = args.tenant else: tenantid = 'myorganisation' expiretime = time.mktime( time.strptime(token['expiresOn'].split('.')[0], '%Y-%m-%d %H:%M:%S')) headers = { 'Authorization': '%s %s' % (token['tokenType'], token['accessToken']) } if not checktoken(): return # Recreate DB engine = database.init(True, dburl=dburl) dumper = DataDumper(tenantid, '1.61-internal', engine=engine) async with aiohttp.ClientSession() as ahsession: print('Starting data gathering phase 1 of 2 (collecting objects)') dumper.ahsession = ahsession tasks = [] tasks.append(dumper.dump_object('users', User)) tasks.append(dumper.dump_object('tenantDetails', TenantDetail)) tasks.append(dumper.dump_object('policies', Policy)) tasks.append(dumper.dump_object('servicePrincipals', ServicePrincipal)) tasks.append(dumper.dump_object('groups', Group)) tasks.append(dumper.dump_object('applications', Application)) tasks.append(dumper.dump_object('devices', Device)) # tasks.append(dumper.dump_object('domains', Domain)) tasks.append(dumper.dump_object('directoryRoles', DirectoryRole)) tasks.append(dumper.dump_object('roleDefinitions', RoleDefinition)) # tasks.append(dumper.dump_object('roleAssignments', RoleAssignment)) tasks.append(dumper.dump_object('contacts', Contact)) # tasks.append(dumper.dump_object('getAvailableExtensionProperties', ExtensionProperty, method=ahsession.post)) tasks.append( dumper.dump_object('oauth2PermissionGrants', OAuth2PermissionGrant)) await asyncio.gather(*tasks) Session = sessionmaker(bind=engine) dbsession = Session() # Mapping object, mapping type returned to Table and link name group_mapping = { 'Microsoft.DirectoryServices.User': (User, 'memberUsers'), 'Microsoft.DirectoryServices.Group': (Group, 'memberGroups'), 'Microsoft.DirectoryServices.Contact': (Contact, 'memberContacts'), 'Microsoft.DirectoryServices.Device': (Device, 'memberDevices'), } owner_mapping = { 'Microsoft.DirectoryServices.User': (User, 'ownerUsers'), 'Microsoft.DirectoryServices.ServicePrincipal': (ServicePrincipal, 'ownerServicePrincipals'), } tasks = [] dumper.session = dbsession async with aiohttp.ClientSession() as ahsession: print( 'Starting data gathering phase 2 of 2 (collecting properties and relationships)' ) dumper.ahsession = ahsession tasks.append( dumper.dump_links('groups', 'members', Group, mapping=group_mapping)) role_mapping = { 'Microsoft.DirectoryServices.User': (User, 'memberUsers'), 'Microsoft.DirectoryServices.ServicePrincipal': (ServicePrincipal, 'memberServicePrincipals'), } tasks.append( dumper.dump_links('directoryRoles', 'members', DirectoryRole, mapping=role_mapping)) tasks.append( dumper.dump_linked_objects('servicePrincipals', 'appRoleAssignedTo', ServicePrincipal, AppRoleAssignment, ignore_duplicates=True)) tasks.append( dumper.dump_linked_objects('servicePrincipals', 'appRoleAssignments', ServicePrincipal, AppRoleAssignment, ignore_duplicates=True)) tasks.append( dumper.dump_object_expansion('servicePrincipals', ServicePrincipal, 'owners', 'owner', User, mapping=owner_mapping)) tasks.append( dumper.dump_object_expansion('devices', Device, 'registeredOwners', 'owner', User)) tasks.append( dumper.dump_object_expansion('applications', Application, 'owners', 'owner', User, mapping=owner_mapping)) tasks.append(dumper.dump_custom_role_members(RoleAssignment)) if args.mfa: tasks.append(dumper.dump_mfa('users', User, method=ahsession.get)) tasks.append( dumper.dump_each(ServicePrincipal, 'applicationRefs', ApplicationRef)) await asyncio.gather(*tasks) dbsession.close()
async def run(args, dburl): global token, expiretime, headers if 'tenantId' in token: tenantid = token['tenantId'] elif args.tenant: tenantid = args.tenant else: tenantid = 'myorganization' expiretime = time.mktime( time.strptime(token['expiresOn'].split('.')[0], '%Y-%m-%d %H:%M:%S')) headers = { 'Authorization': '%s %s' % (token['tokenType'], token['accessToken']) } if not checktoken(): return # Recreate DB engine = database.init(True, dburl=dburl) dumper = DataDumper(tenantid, '1.61-internal', engine=engine) async with aiohttp.ClientSession() as ahsession: print('Starting data gathering phase 1 of 2 (collecting objects)') dumper.ahsession = ahsession tasks = [] tasks.append(dumper.dump_object('users', User)) tasks.append(dumper.dump_object('tenantDetails', TenantDetail)) tasks.append(dumper.dump_object('policies', Policy)) tasks.append(dumper.dump_object('servicePrincipals', ServicePrincipal)) tasks.append(dumper.dump_object('groups', Group)) tasks.append(dumper.dump_object('applications', Application)) tasks.append(dumper.dump_object('devices', Device)) # tasks.append(dumper.dump_object('domains', Domain)) tasks.append(dumper.dump_object('directoryRoles', DirectoryRole)) tasks.append(dumper.dump_object('roleDefinitions', RoleDefinition)) # tasks.append(dumper.dump_object('roleAssignments', RoleAssignment)) tasks.append(dumper.dump_object('contacts', Contact)) # tasks.append(dumper.dump_object('getAvailableExtensionProperties', ExtensionProperty, method=ahsession.post)) tasks.append( dumper.dump_object('oauth2PermissionGrants', OAuth2PermissionGrant)) await asyncio.gather(*tasks) Session = sessionmaker(bind=engine) dbsession = Session() # Mapping object, mapping type returned to Table and link name group_mapping = { 'Microsoft.DirectoryServices.User': (User, 'memberUsers'), 'Microsoft.DirectoryServices.Group': (Group, 'memberGroups'), 'Microsoft.DirectoryServices.Contact': (Contact, 'memberContacts'), 'Microsoft.DirectoryServices.Device': (Device, 'memberDevices'), 'Microsoft.DirectoryServices.ServicePrincipal': (ServicePrincipal, 'memberServicePrincipals'), } owner_mapping = { 'Microsoft.DirectoryServices.User': (User, 'ownerUsers'), 'Microsoft.DirectoryServices.ServicePrincipal': (ServicePrincipal, 'ownerServicePrincipals'), } role_mapping = { 'Microsoft.DirectoryServices.User': (User, 'memberUsers'), 'Microsoft.DirectoryServices.ServicePrincipal': (ServicePrincipal, 'memberServicePrincipals'), 'Microsoft.DirectoryServices.Group': (Group, 'memberGroups'), } tasks = [] dumper.session = dbsession num_groups = dbsession.query(func.count(Group.objectId)).scalar() if num_groups > MAX_GROUPS: print( 'Gathered {0} groups, switching to 3-phase approach for efficiency' .format(num_groups)) async with aiohttp.ClientSession() as ahsession: if num_groups > MAX_GROUPS: print( 'Starting data gathering phase 2 of 3 (collecting properties and relationships)' ) else: print( 'Starting data gathering phase 2 of 2 (collecting properties and relationships)' ) dumper.ahsession = ahsession # If we have a lot of groups, dump them separately if num_groups <= MAX_GROUPS: tasks.append( dumper.dump_links('groups', 'members', Group, mapping=group_mapping)) tasks.append( dumper.dump_object_expansion('devices', Device, 'registeredOwners', 'owner', User)) tasks.append( dumper.dump_links('directoryRoles', 'members', DirectoryRole, mapping=role_mapping)) tasks.append( dumper.dump_linked_objects('servicePrincipals', 'appRoleAssignedTo', ServicePrincipal, AppRoleAssignment, ignore_duplicates=True)) tasks.append( dumper.dump_linked_objects('servicePrincipals', 'appRoleAssignments', ServicePrincipal, AppRoleAssignment, ignore_duplicates=True)) tasks.append( dumper.dump_object_expansion('servicePrincipals', ServicePrincipal, 'owners', 'owner', User, mapping=owner_mapping)) tasks.append( dumper.dump_object_expansion('applications', Application, 'owners', 'owner', User, mapping=owner_mapping)) tasks.append(dumper.dump_custom_role_members(RoleAssignment)) if args.mfa: tasks.append(dumper.dump_mfa('users', User, method=ahsession.get)) tasks.append( dumper.dump_each(ServicePrincipal, 'applicationRefs', ApplicationRef)) await asyncio.gather(*tasks) tasks = [] if num_groups > MAX_GROUPS: print( 'Starting data gathering phase 3 of 3 (collecting group memberships and device owners)' ) async with aiohttp.ClientSession() as ahsession: dumper.ahsession = ahsession queue = asyncio.Queue(maxsize=100) # Start the workers workers = [] for i in range(100): workers.append(asyncio.ensure_future(queue_processor(queue))) tasks.append( dumper.dump_links_with_queue(queue, 'devices', 'registeredOwners', Device, linkname="owner", childtbl=User)) tasks.append( dumper.dump_links_with_queue(queue, 'groups', 'members', Group, mapping=group_mapping)) await asyncio.gather(*tasks) await queue.join() for worker_task in workers: worker_task.cancel() dbsession.close()