# Exercise: Monitoring AWS for security issues

This guide will walk you through the process of testing for common security issues that may expose an AWS account to unwanted risks

## Prerequisites

- The AWS CLI should be installed
- Admin-level access to an AWS account

## 1. Identify Public S3 Buckets

- We are going to compare two existing S3 buckets:

  - nsrc-noc
  - nsrc-temp

  List the first bucket:

      aws s3api get-public-access-block --bucket nsrc-noc --query 'PublicAccessBlockConfiguration'

  Now list the second bucket:

      aws s3api get-public-access-block --bucket nsrc-temp --query 'PublicAccessBlockConfiguration'

  Do you notice any difference?

- Let’s see what happens when an S3 bucket is publicly accessible

      aws s3 ls s3://nsrc-temp

  Is there a file in the bucket?

  Now let’s see if we can see the content of the file via a browser. Open the following URL in your browser:

      https://nsrc-temp.s3-ap-southeast-1.amazonaws.com/index.html

  Any surprises?

  Let’s see why we can see the content of that file without any authentication. Run this command:

      aws s3api get-bucket-policy --bucket nsrc-temp --query "Policy" --output text| jq

  Note: if you have not installed the utility ‘jq’ just run:

      aws s3api get-bucket-policy --bucket nsrc-temp --query "Policy" --output text

  What did we learn in regards to publicly accessible S3 buckets? How would you monitor your AWS account to verify doesn’t have publicly accessible buckets?

  Note:

  There is a way to provide temporary access to files in an AWS bucket without an AWS account. It is done using “pre-signed” URLs. It allows the person or application in possession of URL to access a file for a limited time.

  Here is a link to the AWS dcoumentation if interested:

  https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html

## 2. Check for IAM Users Without MFA

- List all IAM users

      aws iam list-users

- List MFA devices for a given user

      aws iam list-mfa-devices --user-name <user>

- If we combine the above commands it makes it a bit easier to run through all users in the environment and spot those not protected by MFA

      users=""
      users=$(aws iam list-users --query "Users[*].UserName" --output text)

      for user in $users
      do
          mfa=$(aws iam list-mfa-devices --user-name "$user" --query "MFADevices[].SerialNumber" --output text)
          echo "User: $user MFA: $mfa"
      done

## 3. Check permissions granted by user-defined (“Local”) IAM policies

IAM policies may grant excessive privileges. The definition of “excessive” is specific to each organization. However being aware of the risk and having the ability to list such permissions allow cloud administrators to verify.

- List all user-defined policies

      aws iam list-policies --scope Local --query "Policies[*].[PolicyName,Arn]"

  The output will show the user-defined policy names and their resource locator (ARN). We will need the policy ARN to show the permissions tied to the policy

      aws iam get-policy-version --policy-arn arn:aws:iam::058264411872:policy/BillingCostCategoriesReadWriteGroup --version-id v1 --query "PolicyVersion.Document" --output json

  What permissions do you observe? (Try to guess what they do)

  Now let’s take a look at the next policy:

      aws iam get-policy-version --policy-arn arn:aws:iam::058264411872:policy/service-role/s3crr_for_nsrc-noc_80e96a --version-id v1 --query "PolicyVersion.Document" --output json

  Hint: we will use this policy in future exercises this week to do S3 buckets backups :)

## 4. Identify Security Groups with very permissive settings

- Rationale: In AWS EC2 service, security groups act like a firewall. Remember when you created your EC2 instance? You had to create a security group for your EC2 server to run into. The security group rules define what protocols and ports are reachable for incoming and outgoing traffic. Typically, unless your application requires very restrictive outgoing traffic, you allow all traffic out (a.k.a. “egress”)

- First, let’s list all security groups

      aws ec2 describe-security-groups --query "SecurityGroups[*].{GroupName:GroupName,GroupId:GroupId}"

- Now let’s determine if any security group allows open access (0.0.0.0/0) That means we are letting access from everywhere to the security group. We will get more granular information as we progress

  First let’s see if we have any group with open access

      aws ec2 describe-security-groups --query "SecurityGroups[?IpPermissions[?contains(IpRanges[].CidrIp, '0.0.0.0/0') ]].GroupId"

  What are we doing here? We are taking advantage of the AWS CLI ability to search using “query” statements. We are basically saying: “Please show me the GroupId of any security group which has an IpPermission (rule) allowing traffic from every where (0.0.0.0/0)”

  Do you see any group in the output?

  - Now let’s pick one of the groups in our list, and inspect which ports are exposed, and the level of exposure

  - Replace in the command with one of the groups from the listing:

      aws ec2 describe-security-groups --query "SecurityGroups[?GroupId=='<SG_GROUP>'].{GroupId:GroupId,Inbound:IpPermissions[*]}"

  Can you describe the output in terms of which ports are open to what traffic?

  Feel free to inspect more security groups, you can list all the existing groups with:

      aws ec2 describe-security-groups --query "SecurityGroups[].GroupId"

  - Bonus questions:
    - Why do we have in the workshop so many ports exposed to 0.0.0.0/0?
    - Can you think of a way to reduce the exposure of the SSH port to 0.0.0.0/0? What information would you need to reduce the exposure and how would you do it?

## 5. Generate IAM credentials report and analyze it

- Generate credentials report A credentials report is a “batch” job, meaning a report is generated in the background, and as the report becomes available one can collect information on user activity and extract useful information. If a report has not been generated in the last 4 hours, AWS generates an updated one. Otherwise it uses the one currently available.

      aws iam generate-credential-report

  if no report available:

      {
        "State": "STARTED",
        "Description": "No report exists. Starting a new report generation task"
      }

  Otherwise:

      {
         "State": "COMPLETE"
      }

- Now let’s review what information is available

      aws iam get-credential-report --query "Content" --output text | base64 --decode

  This will generate a comma-delimited file that details credentials activity per user. You could save the report to a CSV file for further processing like this:

      aws iam get-credential-report --query "Content" --output text | base64 --decode > report.csv

  You could open the file in a spreadsheet processing application. If you look at the first line (the headers) describe the meaning of each column. If we use a Linux command that parses text files we can show some details (the command name is “awk” )

  Let’s show when users were created:

      cat report.csv | awk -F, '{print $1" "$3}'

  When were the user passwords last used, and last changed?

      cat report.csv | awk -F, '{print $1" "$5" "$6}'

  Bonus: Who can show us the MFA status for all users?

## 6. Let’s build a security check script

- There are several other recommended settings to improve the security posture of your AWS installation. For example:

  - logging events using Cloudtrail to help with forensic analysis if needed
  - setup EC2 instance metadata access (IMDS) via version 2 instead of version 1 (vulnerable)
  - disable AWS regions that would not be used by the organization (not all regions can be disabled though)

To complete the exercise, let’s put together a shell script using the AWS CLI to help us automate some of the security checks we played with during the lab

- Copy the content of the security script in the lab

- Edit file (copy/paste content)

      nano aws_security_check.sh

- Make the shell script executable

      chmod u+x aws_security_check.sh

  Lets run the script, be patient! It takes a while:

      ./aws_security_check.sh

## END