Example #1
0
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()
Example #2
0
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)
Example #3
0
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))
Example #4
0
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()
Example #5
0
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()