diff --git a/clouds/aws/README.md b/clouds/aws/README.md index 0c25a9f..617142f 100644 --- a/clouds/aws/README.md +++ b/clouds/aws/README.md @@ -93,6 +93,8 @@ Afterwards, one should see following logs in CloudWatch traces for planted Lambd [*] Following S3 object could be removed: (Bucket=90112981864022885796153088027941100000000000000000000000, Key=cloudtrail/AWSLogs/712800000000/CloudTrail/us-west-2/2019/03/20/712800000000_CloudTrail_us-west-2_20190320T1000Z_oxxxxxxxxxxxxc.json.gz) ``` +- **`evaluate-iam-role.sh`** - Enumerates attached IAM Role policies, goes through all of granted permissions and lists those that are known for Privilege Escalation risks. Based on [Rhino Security Labs work](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/). [gist](https://gist.github.com/mgeeky/14685d94af7848e64afefe6fd2341a18) + - **`exfiltrateLambdaTasksDirectory.py`** - Script that creates an in-memory ZIP file from the entire directory `$LAMBDA_TASK_ROOT` (typically `/var/task`) and sends it out in a form of HTTP(S) POST request, within an `exfil` parameter. To be used for exfiltrating AWS Lambda's entire source code. - **`get-session-creds-in-config-format.sh`** - Calls `aws sts assume-role` using MFA token in order to then retrieve session credentials and reformat it into `~/.aws/credentials` file format. Having that it's easy to copy-and-paste that script's output into credentials file. Then tools such as _s3tk_ that are unable to process MFA tokens may just use preconfigured profile creds. diff --git a/clouds/aws/evaluate-iam-role.sh b/clouds/aws/evaluate-iam-role.sh new file mode 100755 index 0000000..723ca0d --- /dev/null +++ b/clouds/aws/evaluate-iam-role.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +if [ $# -ne 2 ]; then + echo "Usage: evaluate-iam-role.sh " + exit 1 +fi + +PROFILE=$1 +ROLE_NAME=$2 + +known_dangerous_permissions=( + "iam:CreatePolicyVersion" + "iam:SetDefaultPolicyVersion" + "iam:PassRole" + "ec2:RunInstances" + "iam:CreateAccessKey" + "iam:CreateLoginProfile" + "iam:UpdateLoginProfile" + "iam:AttachUserPolicy" + "iam:AttachGroupPolicy" + "iam:AttachRolePolicy" + "iam:PutUserPolicy" + "iam:PutGroupPolicy" + "iam:PutRolePolicy" + "iam:AddUserToGroup" + "iam:UpdateAssumeRolePolicy" + "sts:AssumeRole" + "iam:PassRole" + "lambda:CreateFunction" + "lambda:InvokeFunction" + "lambda:CreateEventSourceMapping" + "lambda:UpdateFunctionCode" + "glue:CreateDevEndpoint" + "glue:UpdateDevEndpoint" + "cloudformation:CreateStack" + "datapipeline:CreatePipeline" + "datapipeline:PutPipelineDefinition" +) + +role_policy=$(aws --profile $PROFILE iam get-role --role-name $ROLE_NAME) + +echo -e "=============== Role: $ROLE_NAME ===============" +echo "$role_policy" + +IFS=$'\n' +attached_role_policies=($(aws --profile $PROFILE iam list-attached-role-policies --role-name $ROLE_NAME | jq -r '.AttachedPolicies[].PolicyArn')) + +dangerous_permissions=() + +for policy in "${attached_role_policies[@]}" ; do + echo -e "\n=============== Attached Policy Arn: $policy ===============" + + version_id=$(aws --profile $PROFILE iam get-policy --policy-arn $policy | jq -r '.Policy.DefaultVersionId') + + policy_version=$(aws --profile $PROFILE iam get-policy-version --policy-arn $policy --version-id $version_id) + echo "$policy_version" + + permissions=($(echo "$policy_version" | jq -r '.PolicyVersion.Document.Statement[].Action | if type=="string" then [.] else . end | .[]')) + effect=$(echo "$policy_version" | jq -r '.PolicyVersion.Document.Statement[].Effect' ) + + if [[ "$effect" == "Allow" ]]; then + for perm in "${permissions[@]}" ; do + for dangperm in "${known_dangerous_permissions[@]}"; do + if echo "$dangperm" | grep -iq $perm ; then + dangerous_permissions+=("$perm") + fi + done + done + fi +done + +if [[ ${#dangerous_permissions[@]} -gt 0 ]]; then + echo -e "\n\n=============== Detected dangerous permissions granted ===============" + for dangperm in "${dangerous_permissions[@]}"; do + echo -e "\t$dangperm" + done +else + echo -e "\nNo dangerous permissions were found to be granted." +fi