def cloudtrail_mfa_policy_abuse_attempt(rec):
    """
    author:           Scott Piper of Summit Route in collaboration with Duo Security
    description:      Alert on potential attacks performed by users that are supposed to have
                        MFA enforced. May indicate leaked access keys and an attempt to abuse
                        a flawed MFA enforcement policy.
    playbook:         (a) Identify whether or not the attempt was a mistake.
                      (b) Begin IR: Roll access keys, investigate past CloudTrail logs for
                      other actions performed, investigate how the keys were leaked in the
                      first place.
    """

    # Depending on the practices you follow with AWS today, you may wish to simply alert
    # on any errors at all in AWS, possibly with some focus on IAM actions,
    # and possibly with some exemptions to ignore things like failed login attempts.
    # Another option would be to just alert on any AccessDenied's when MFA is not used.
    # This rule attempts to reduce the false positives.

    # Get the value for whether the user is MFA authenticated.
    # If this doesn't exist, assume not MFA authenticated.
    try:
        mfa_authenticated = rec['userIdentity']['sessionContext'][
            'attributes']['mfaAuthenticated']
    except KeyError:
        mfa_authenticated = 'false'

    # If the user is MFA authenticated, then any issues are not due to just a compromised
    # access key, so ignore it.
    if mfa_authenticated == 'true':
        return False

    # If the user tries to remove their MFA device without being MFA authenticated,
    # it could be an attacker trying to take advantage of an issue with an older AWS policy.
    if rec['eventName'] == 'DeactivateMFADevice':
        return True

    # Similarly, the attacker could try some other IAM actions under the assumption that the user
    # is an admin with the flawed policy. There are a lot of actions they could try, which should
    # be blocked by your policy anyway now, but these should detect most of the actions an attacker
    # would try.
    iam_actions = {
        'CreateUser', 'CreateAccessKey', 'DetachUserPolicy',
        'DetachGroupPolicy', 'RemoveUserFromGroup', 'DeleteUserPolicy',
        'PutGroupPolicy', 'PutUserPolicy'
    }
    if in_set(rec['eventName'], iam_actions):
        return True

    # If the user tries to create or enable an MFA device, but they are unable to, it could mean
    # they are attempting to exploit a race condition where they wait for the user to one day
    # swap MFA devices.
    # This will have an errorCode of:
    # - 'AccessDenied'
    # - 'EntityAlreadyExists': Can't create another MFA device with the same name.
    # - 'LimitExceeded': Can't enable a second MFA device for the same user.
    if ('errorCode' in rec and in_set(
            rec['eventName'], {'CreateVirtualMFADevice', 'EnableMFADevice'})):
        return True

    return False
예제 #2
0
def cloudtrail_critical_api_calls(rec):
    """
    author:           airbnb_csirt
    description:      Alert on AWS API calls that stop or delete security/infrastructure logs.
                      Additionally, alert on AWS API calls that delete critical resources
                      (VPCs, Subnets, DB's, ...)
    reference:        https://medium.com/@robwitoff/
                          proactive-cloud-security-w-aws-organizations-d58695bcae16#.tx2e6iju0
    playbook:         (a) identify the AWS account in the log
                      (b) identify what resource(s) are impacted by the API call
                      (c) determine if the intent is valid, malicious or accidental
    """
    critical_events = {
        # VPC Flow Logs (~netflow)
        'DeleteFlowLogs',
        # Critical, large resources
        'DeleteSubnet',
        'DeleteVpc',
        'DeleteDBCluster',
        'DeleteCluster',
        # CloudTrail
        'DeleteTrail',
        'UpdateTrail',
        'StopLogging',
        # AWS Config
        'DeleteDeliveryChannel',
        'StopConfigurationRecorder',
        # CloudWatch
        'DeleteRule',
        'DisableRule'
    }

    return in_set(rec['eventName'], critical_events)
예제 #3
0
def test_in_set():
    """Helpers - In Set"""
    # basic example
    test_list = ['this', 'is', 'a9', 'test']
    data = 'test'
    result = base.in_set(data, test_list)
    assert_equal(result, True)

    # with globbing
    host_patterns = {'myhost*', 'yourhost*', 'ahost*'}
    myhost = 'myhost1232312321'
    yourhost = 'yourhost134931'
    ahost = 'ahost12321-test'

    result = all(base.in_set(host, host_patterns) for host in (myhost, yourhost, ahost))
    assert_equal(result, True)
예제 #4
0
def cloudtrail_put_object_acl_public(rec):
    """
    author:         @mimeframe
    description:    Identifies a change to an S3 object ACL that grants access
                    to AllUsers (anyone on the internet) or AuthenticatedUsers
                    (any user with an AWS account).
    reference:      http://amzn.to/2yfRxzp
    playbook:       (a) Verify if the object should be publicly accessible
                    (b) If not, modify the object ACL
    """
    public_acls = {
        'http://acs.amazonaws.com/groups/global/AuthenticatedUsers',
        'http://acs.amazonaws.com/groups/global/AllUsers'
    }

    # s3 buckets that are expected to have public objects
    public_buckets = {
        'example-bucket-to-ignore'
    }

    request_params = rec['detail']['requestParameters']
    return (
        rec['detail']['eventName'] == 'PutObjectAcl' and
        # note: substring is used because it can exist as:
        # "http://acs.amazonaws.com/groups/global/AllUsers" or
        # "uri=http://acs.amazonaws.com/groups/global/AllUsers"
        data_has_value_from_substring_list(request_params, public_acls) and
        not in_set(request_params.get('bucketName'), public_buckets)
    )
예제 #5
0
def sample_cloudtrail_rule(rec):
    """Non Lambda/Kinesis service AssumedRole"""
    whitelist_services = {
        'lambda.amazonaws.com',
        'kinesis.amazonaws.com'
    }

    return (
        rec['eventName'] == 'AssumeRole' and
        rec['awsRegion'] == 'us-east-1' and
        not in_set(rec['userIdentity']['invokedBy'], whitelist_services)
    )
def github_disable_required_pull_request_reviews(rec):
    """
    author:       @mimeframe
    description:  Setting 'Require pull request reviews before merging' was disabled.
                  When enabled, all commits must be made to a non-protected branch
                  and submitted via a pull request with at least one approved review
                  and no changes requested before it can be merged into master.
    repro_steps:  (a) Visit /<org>/<repo>/settings/branches/<branch>
                  (b) Uncheck 'Require pull request reviews before merging'
                  (c) Click 'Save Changes'
    reference:    https://help.github.com/articles/enabling-required-reviews-for-pull-requests/
    """
    actor_ignorelist = {}
    return (rec['action']
            == 'protected_branch.dismissal_restricted_users_teams'
            and rec['data'].get('authorized_actors_only') is True
            and not in_set(rec['actor'], actor_ignorelist))