Ejemplo n.º 1
0
from pacu import Main

module_info = {
    'name':
    'cloudtrail__download_event_history',
    'author':
    'Spencer Gietzen of Rhino Security Labs',
    'category':
    'EVADE',
    'one_liner':
    'Downloads CloudTrail event history to JSON files.',
    'description':
    strip_lines('''
        This module will download the CloudTrail event history for each specified region in both JSON format to 
        ~/.local/share/pacu/sessions/[current_session_name]/downloads/cloudtrail_[region]_event_history_[timestamp].json.
        Warning: This module can take a very long time to complete because the maximum events per API call is 50, when 
        there could be tens or hundreds of thousands or more total events to download. A rough estimate is about 10000
        events retrieved per five minutes.
    '''),
    'services': ['CloudTrail'],
    'prerequisite_modules': [],
    'arguments_to_autocomplete': ['--regions'],
}

parser = argparse.ArgumentParser(add_help=False,
                                 description=module_info['description'])

parser.add_argument(
    '--regions',
    required=False,
    default=None,
Ejemplo n.º 2
0
from pacu.core.lib import strip_lines, save
from pacu import Main

module_info = {
    'name':
    'elb__enum_logging',
    'author':
    'Spencer Gietzen of Rhino Security Labs',
    'category':
    'EVADE',
    'one_liner':
    'Collects a list of Elastic Load Balancers without access logging.',
    'description':
    strip_lines('''
        This module will enumerate all EC2 Elastic Load Balancers and save their data to the current session, as well as
        write a list of ELBs with logging disabled to
        ~/.local/share/pacu/sessions/[current_session_name]/downloads/elbs_no_logs_[timestamp].csv.
    '''),
    'services': ['ElasticLoadBalancing'],
    'prerequisite_modules': [],
    'arguments_to_autocomplete': ['--regions'],
}

parser = argparse.ArgumentParser(add_help=False,
                                 description=module_info['description'])

parser.add_argument('--regions',
                    required=False,
                    default=None,
                    help=strip_lines('''
    One or more (comma separated) AWS regions in the format "us-east-1". Defaults to all session regions.
Ejemplo n.º 3
0
from copy import deepcopy
import os

from botocore.exceptions import ClientError

from pacu.core.lib import strip_lines

module_info = {
    # Name of the module (should be the same as the filename)
    'name': 's3__download_bucket',
    'author': 'Spencer Gietzen of Rhino Security Labs',
    'category': 'EXFIL',
    'one_liner': 'Enumerate and dumps files from S3 buckets.',
    'description': strip_lines('''
        This module scans the current account for AWS buckets and prints/stores as much data as it can about each one. 
        With no arguments, this module will enumerate all buckets the account has access to, then prompt you to download
        all files in the bucket or not. Use --names-only or --dl-names to change that. The files will be downloaded to
        ~/.local/share/pacu/sessions/[current_session_name]/downloads/s3__download_bucket/.
    '''),
    'services': ['S3'],
    'prerequisite_modules': [],
    'arguments_to_autocomplete': ['--dl-all', '--names-only', '--dl-names'],
}

parser = argparse.ArgumentParser(add_help=False, description=module_info['description'])


parser.add_argument('--dl-all', required=False, action='store_true', help=strip_lines('''
    If specified, automatically download all files from buckets that are allowed instead of asking for each one.
    WARNING: This could mean you could potentially be downloading terrabytes of data! It is suggested to user
    --names-only and then --dl-names to download specific files.
'''))
Ejemplo n.º 4
0
from pacu import Main

module_info = {
    'name': 'ecs__enum_task_def',
    'author': 'Nicholas Spagnola of Rhino Security Labs',
    'category': 'ENUM',
    'one_liner': 'Parses task definitions from ECS tasks',
    'description': 'This module will pull task definitions for ECS clusters.',
    'services': ['ECS'],
    'prerequisite_modules': ['ecs__enum'],
    'arguments_to_autocomplete': ['--task_definitions'],
}

parser = argparse.ArgumentParser(add_help=False, description=module_info['description'])
parser.add_argument('--task_definitions', required=False, default=None, help=strip_lines('''
    A comma separated list of ECS task defintion ARNs 
    (arn:aws:ecs:us-east-1:273486424706:task-definition/first-run-task-definition:latest)
'''))


def main(args, pacu_main: 'Main'):
    session = session = pacu_main.get_active_session()

    ###### Don't modify these. They can be removed if you are not using the function.
    args = parser.parse_args(args)
    print = pacu_main.print

    fetch_data = pacu_main.fetch_data
    ######

    task_definitions = []
    summary_data = {"task_definitions": 0}
Ejemplo n.º 5
0
from pacu.core.lib import strip_lines, save, downloads_dir
from pacu import Main

module_info = {
    'name':
    'inspector__get_reports',
    'author':
    'Alexander Morgenstern',
    'category':
    'ENUM',
    'one_liner':
    'Captures vulnerabilities found when running a preconfigured inspector report.',
    'description':
    strip_lines('''
        This module captures findings for reports in regions that support AWS Inspector. The optional argument
        --download-reports will automatically download any reports found into the session downloads directory under a
        folder named after the run id of the inspector report.
    '''),
    'services': ['Inspector'],
    'prerequisite_modules': [],
    'external_dependencies': [],
    'arguments_to_autocomplete': ['--download-reports'],
}

parser = argparse.ArgumentParser(add_help=False,
                                 description=module_info['description'])

parser.add_argument(
    '--download-reports',
    required=False,
    default=False,
Ejemplo n.º 6
0
from pacu import Main

module_info = {
    'name':
    'cloudwatch__download_logs',
    'author':
    'Alexander Morgenstern [email protected]',
    'category':
    'EVADE',
    'one_liner':
    'Captures CloudWatch logs and downloads them to the session downloads folder',
    'description':
    strip_lines('''
        This module examines all logs for all regions and saves them as CSV files. By default, only events that were
        logged in the past 24 hours will be captured. Otherwise, they will be captured based on the passed time
        arguments. The files will be downloaded in a similar format to
        ~/.local/share/pacu/sessions/{session}/downloads/cloud_watch_logs/{timestamp}, with session being the active session, and
        timestamp being the start of this module's execution.
    '''),
    'services': ['logs'],
    'external_dependencies': [],
    'arguments_to_autocomplete': ['--from-time', '--to-time'],
}
DEFAULT_FROM_TIME = datetime.datetime.today().replace(
    tzinfo=datetime.timezone.utc) - datetime.timedelta(days=1)

parser = argparse.ArgumentParser(add_help=False,
                                 description=module_info['description'])
parser.add_argument(
    '--from-time',
    required=False,
Ejemplo n.º 7
0
    'Enumerates and dumps secrets from AWS Secrets Manager and AWS parameter store',
    'description':
    'This module will enumerate secrets in AWS Secrets Manager and AWS Systems manager parameter store.',
    'services': ['SecretsManager', 'SSM'],
    'prerequisite_modules': [],
    'external_dependencies': [],
    'arguments_to_autocomplete':
    ['--regions', '--secrets-manager', '--parameter-store'],
}

parser = argparse.ArgumentParser(add_help=False,
                                 description=module_info['description'])
parser.add_argument('--regions',
                    required=False,
                    help=strip_lines('''
    One or more (comma separated) AWS regions in the format "us-east-1". Defaults to all session regions.
'''))
parser.add_argument('--secrets-manager',
                    required=False,
                    action="store_true",
                    help="Enumerate secrets manager")
parser.add_argument('--parameter-store',
                    required=False,
                    action="store_true",
                    help="Enumerate Systems Manager parameter store")


def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()

    args = parser.parse_args(args)
Ejemplo n.º 8
0
from pacu.core.lib import strip_lines, save, downloads_dir
from pacu import Main

module_info = {
    'name':
    'iam__enum_permissions',
    'author':
    'Spencer Gietzen of Rhino Security Labs',
    'category':
    'ENUM',
    'one_liner':
    'Tries to get a confirmed list of permissions for the current (or all) user(s).',
    'description':
    strip_lines('''
        This module will attempt to use IAM APIs to enumerate a confirmed list of IAM permissions for users/roles in the
        account. By default, the owner of the active set of keys is targeted. This is done by checking attached and
        inline policies for the user and the groups they are in.
    '''),
    'services': ['IAM'],
    'prerequisite_modules': ['iam__enum_users_roles_policies_groups'],
    'arguments_to_autocomplete': ['--all-users', '--user-name']
}

parser = argparse.ArgumentParser(add_help=False,
                                 description=module_info['description'])

parser.add_argument('--all-users',
                    required=False,
                    default=False,
                    action='store_true',
                    help=strip_lines('''
Ejemplo n.º 9
0
from pacu.core.secretfinder.utils import regex_checker, Color
from pacu import Main

module_info = {
    'name':
    'ec2__download_userdata',
    'author':
    'Spencer Gietzen of Rhino Security Labs',
    'category':
    'ENUM',
    'one_liner':
    'Downloads User Data from EC2 instances/launch templates.',
    'description':
    strip_lines('''
        This module will take a list of EC2 instance IDs and/or EC2 launch template IDs and request then download the
        User Data associated with each instance/template. All of the data will be saved to
        ~/.local/share/pacu/sessions/[session_name]/downloads/ec2_user_data/.
    '''),
    'services': ['EC2'],
    'prerequisite_modules': ['ec2__enum'],
    'arguments_to_autocomplete':
    ['--instance-ids', '--template-ids', '--filter'],
}

parser = argparse.ArgumentParser(add_help=True,
                                 description=module_info['description'])

parser.add_argument('--instance-ids',
                    required=False,
                    default=None,
                    help=strip_lines('''
Ejemplo n.º 10
0
def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()

    ###### Don't modify these. They can be removed if you are not using the function.
    args = parser.parse_args(args)
    print = pacu_main.print
    input = pacu_main.input

    key_info = pacu_main.key_info
    get_regions = pacu_main.get_regions
    ######

    if args.snaps is False and args.vols is False:
        args.snaps = args.vols = True

    ec2_data = deepcopy(session.EC2)
    if 'Volumes' not in ec2_data.keys():
        ec2_data['Volumes'] = []
    if 'Snapshots' not in ec2_data.keys():
        ec2_data['Snapshots'] = []
    session.update(pacu_main.database, EC2=ec2_data)

    if args.regions is None:
        regions = get_regions('ec2')
        if regions is None or regions == [] or regions == '' or regions == {}:
            print(
                'This module is not supported in any regions specified in the current sessions region set. Exiting...'
            )
            return
    else:
        regions = args.regions.split(',')

    account_ids = []

    if args.account_ids is None and args.snaps is True:
        user = key_info()

        if 'AccountId' in user and user['AccountId'] is not None:
            account_ids = [user['AccountId']]
        else:
            current_account = input(
                strip_lines('''
                No account IDs were passed in as arguments and the account ID for the current user has not been stored 
                in this session yet. An account ID is required to get valid results from the snapshot enumeration 
                portion of this module. If you know the current users account ID then enter it now, otherwise, enter 
                y to try and fetch it, or enter n to skip EBS snapshot enumeration. ([account_id]/y/n)
            '''))

            if current_account is None or current_account == '' or current_account.lower(
            ) == 'n':
                account_ids = []

            elif current_account == 'y':
                try:
                    client = pacu_main.get_boto3_client('sts')

                    identity = client.get_caller_identity()

                    account_ids = [identity['Account']]

                    # Might as well fill current key data while it is here
                    session_aws_key = session.get_active_aws_key(
                        pacu_main.database)
                    session_aws_key.update(
                        pacu_main.database,
                        account_id=identity['Account'],
                        arn=identity['Arn'],
                        user_id=identity['UserId'],
                    )
                except Exception as error:
                    print(
                        'Error running sts.get_caller_identity. It is possible that the account ID has been returned '
                        'in this error: {}'.format(error))
                    current_account = input(
                        'If the AWS account ID was returned in the previous error, enter it now to '
                        'continue, or enter n to skip EBS snapshot enumeration. ([account_id]/n) '
                    )
                    if current_account == 'n':
                        account_ids = []
                    else:
                        account_ids = [current_account]

            else:
                account_ids = [current_account]

    elif args.snaps is True:
        account_ids = args.account_ids.split(',')

    else:
        pass  # Ignore args.account_ids if args.snaps is False

    client = pacu_main.get_boto3_client('ec2', random.choice(regions))

    now = time.time()

    all_vols = []
    all_snaps = []
    volumes_csv_data = []
    snapshots_csv_data = []
    snapshot_permissions = {'Public': [], 'Shared': {}, 'Private': []}
    for region in regions:
        print(
            'Starting region {} (this may take a while if there are thousands of EBS volumes/snapshots)...'
            .format(region))
        client = pacu_main.get_boto3_client('ec2', region)

        if args.vols is True:
            # Start EBS Volumes in this region
            count = 0
            response = None
            next_token = False

            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_volumes(
                            MaxResults=
                            500  # Using this as AWS can timeout the connection if there are too many volumes to return in one
                        )
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to DescribeVolumes.')
                        else:
                            print('  ' + code)
                        print('Skipping volume enumeration...')
                        break
                else:
                    response = client.describe_volumes(MaxResults=500,
                                                       NextToken=next_token)

                if 'NextToken' in response:
                    next_token = response['NextToken']

                for volume in response['Volumes']:
                    volume['Region'] = region
                    all_vols.append(volume)
                    if volume['Encrypted'] is False:
                        name = ''
                        if 'Tags' in volume:
                            for tag in volume['Tags']:
                                if tag['Key'] == 'Name':
                                    name = tag['Value']
                                    break
                        volumes_csv_data.append('{},{},{}\n'.format(
                            name, volume['VolumeId'], region))

                count += len(response['Volumes'])

            print('    {} volume(s) found'.format(count))

        if args.snaps is True and not account_ids == []:
            # Start EBS Snapshots in this region
            count = 0
            response = None
            next_token = False

            while (response is None or 'NextToken' in response):
                if next_token is False:
                    try:
                        response = client.describe_snapshots(
                            OwnerIds=account_ids,
                            MaxResults=
                            1000  # Using this as AWS can timeout the connection if there are too many snapshots to return in one
                        )
                    except ClientError as error:
                        code = error.response['Error']['Code']
                        print('FAILURE: ')
                        if code == 'UnauthorizedOperation':
                            print('  Access denied to DescribeSnapshots.')
                        else:
                            print('  ' + code)
                        print('Skipping snapshot enumeration...')
                        break
                else:
                    response = client.describe_snapshots(OwnerIds=account_ids,
                                                         NextToken=next_token,
                                                         MaxResults=1000)

                if 'NextToken' in response:
                    next_token = response['NextToken']

                for snapshot in response['Snapshots']:
                    snapshot['Region'] = region

                    if args.snapshot_permissions:
                        print(
                            '    Starting enumeration for Snapshot Permissions...'
                        )
                        snapshot[
                            'CreateVolumePermissions'] = client.describe_snapshot_attribute(
                                Attribute='createVolumePermission',
                                SnapshotId=snapshot['SnapshotId']
                            )['CreateVolumePermissions']

                        if not snapshot['CreateVolumePermissions']:
                            snapshot_permissions['Private'].append(
                                snapshot['SnapshotId'])
                        elif 'UserId' in snapshot['CreateVolumePermissions'][
                                0]:
                            snapshot_permissions['Shared'][
                                snapshot['SnapshotId']] = [
                                    entry['UserId'] for entry in
                                    snapshot['CreateVolumePermissions']
                                ]
                        elif 'Group' in snapshot['CreateVolumePermissions'][0]:
                            snapshot_permissions['Public'].append(
                                snapshot['SnapshotId'])

                    all_snaps.append(snapshot)
                    if snapshot['Encrypted'] is False:
                        name = ''
                        if 'Tags' in snapshot:
                            for tag in snapshot['Tags']:
                                if tag['Key'] == 'Name':
                                    name = tag['Value']
                                    break
                        snapshots_csv_data.append('{},{},{}\n'.format(
                            name, snapshot['SnapshotId'], region))

                count += len(response['Snapshots'])

            print('    {} snapshot(s) found'.format(count))

    summary_data = {'snapshot_permissions': args.snapshot_permissions}
    if args.vols:
        ec2_data['Volumes'] = all_vols
        summary_data['volumes'] = len(ec2_data['Volumes'])
        p = 'unencrypted_ebs_volumes_{}.csv'.format(now)
        with save(p) as f:
            f.write('Volume Name,Volume ID,Region\n')
            print('  Writing data for {} volumes...'.format(
                len(volumes_csv_data)))
            for line in volumes_csv_data:
                f.write(line)
        summary_data['volumes_csv_path'] = p

    if args.snaps:
        ec2_data['Snapshots'] = all_snaps
        summary_data['snapshots'] = len(ec2_data['Snapshots'])
        path = 'unencrypted_ebs_snapshots_{}.csv'.format(now)
        with save(path) as f:
            f.write('Snapshot Name,Snapshot ID,Region\n')
            print('  Writing data for {} snapshots...'.format(
                len(snapshots_csv_data)))
            for line in snapshots_csv_data:
                f.write(line)
        summary_data['snapshots_csv_path'] = path

    if args.snapshot_permissions:
        permission_data = {
            'Public': len(snapshot_permissions['Public']),
            'Shared': len(snapshot_permissions['Shared']),
            'Private': len(snapshot_permissions['Private']),
        }
        temp = permission_data.copy()
        summary_data.update(temp)
        path = 'snapshot_permissions_' + str(now) + '.txt'
        with save(path) as f:
            f.write('Public:\n')
            for public in snapshot_permissions['Public']:
                f.write('    {}'.format(public))
            f.write('Shared:\n')
            for snap in snapshot_permissions['Shared']:
                f.write('    {}\n'.format(snap))
                for aws_id in snapshot_permissions['Shared'][snap]:
                    f.write('        {}\n'.format(aws_id))
            f.write('Private:\n')
            for private in snapshot_permissions['Private']:
                f.write('    {}\n'.format(private))
            summary_data['snapshot-permissions-path'] = path
    session.update(pacu_main.database, EC2=ec2_data)

    return summary_data
Ejemplo n.º 11
0
from pacu import Main

module_info = {
    'name':
    'ebs__enum_volumes_snapshots',
    'author':
    'Spencer Gietzen of Rhino Security Labs',
    'category':
    'ENUM',
    'one_liner':
    'Enumerates EBS volumes and snapshots and logs any without encryption.',
    'description':
    strip_lines('''
        This module will enumerate all of the Elastic Block Store volumes, snapshots, and snapshot permissions in the
        account and save the data to the current session. It will also note whether or not each volume/snapshot is
        encrypted, then write a list of the unencrypted volumes to
        ~/.local/share/pacu/sessions/[current_session_name]/downloads/unencrypted_ebs_volumes_[timestamp].csv and 
        unencrypted snapshots to ~/.local/share/pacu/sessions/[current_session_name]/downloads/unencrypted_ebs_snapshots_[timestamp].csv
        in .CSV format.
    '''),
    'services': ['EC2'],
    'prerequisite_modules': [],
    'arguments_to_autocomplete': [
        '--regions', '--vols', '--snaps', '--account-ids',
        '--snapshot-permissions'
    ],
}

parser = argparse.ArgumentParser(add_help=False,
                                 description=module_info['description'])

parser.add_argument(
Ejemplo n.º 12
0
from pacu.core.lib import strip_lines, save
from pacu import Main

module_info = {
    'name':
    'iam__get_credential_report',
    'author':
    'Spencer Gietzen of Rhino Security Labs',
    'category':
    'ENUM',
    'one_liner':
    'Generates and downloads an IAM credential report.',
    'description':
    strip_lines('''
        This module tries to download a credential report for the AWS account, giving a lot of authentication
        history/info for users in the account. If it does not find a report, it will prompt you to generate one. The
        report is saved in ~/.local/share/sessions/[current_session_name]/downloads/get_credential_report_[current_time].csv
    '''),
    'services': ['IAM'],
    'prerequisite_modules': [],
    'arguments_to_autocomplete': [],
}

parser = argparse.ArgumentParser(add_help=False,
                                 description=module_info['description'])


def main(args, pacu_main: 'Main'):
    session = pacu_main.get_active_session()

    ###### Don't modify these. They can be removed if you are not using the function.
Ejemplo n.º 13
0
from pacu.core.lib import downloads_dir, strip_lines
from pacu.core.secretfinder.utils import regex_checker, Color

module_info = {
    'name':
    'cloudformation__download_data',
    'author':
    'David Yesland',
    'category':
    'ENUM',
    'one_liner':
    'Downloads all templates, parameters, and exports from CloudFormation Stacks.',
    'description':
    strip_lines('''
        Downloads all templates, parameters, and exports from CloudFormation Stacks. Looks for secrets in all and saves data
        to files.
    '''),
    'services': ['cloudformation'],
    'prerequisite_modules': [],
    'external_dependencies': [],
    'arguments_to_autocomplete': []
}

parser = argparse.ArgumentParser(add_help=False,
                                 description=(module_info['description']))

parser.add_argument(
    '--regions',
    required=False,
    default=None,
    help='One or more (comma separated) AWS regions in the format '