audit-labs/audit-tools

A collection of scripts, queries, and other goodies you can use in an audit. audit automation compliance evidence scripts

Commit 10729070f7

10729070f793f6c8521d803bd2c56e25fa94b9b4

parent: 1e60e2ba9f

Unsigned

cmc <hello@cleberg.net> · 2025-12-15 02:18 UTC

add aws s3 bucket testing

Layout: unified · split

applications/aws/README.md +37
@@ -204,4 +204,41 @@ Rule#,Policy‑Item,Expected,Actual,Result
2042048,Maximum password age (days),90,90,PASS
2052059,Prevent password reuse (last N),4,4,PASS
20620610,Hard expiry (no grace period),false,false,PASS
207```
208
209# `aws_s3_buckets.sh`
210
211This script requires one non-interactive step. Simply run the script:
212
213``` bash
214chmod +x aws_s3_buckets.sh
215./aws_s3_buckets.sh
216```
217
218The shell will show you each bucket discovered during the scanning process, as well as the final result. This final result is a combination of the bucket's Public Access Block (PAB), Policy Status (IsPublic), and ACLs (AllUsers Group).
219
220``` text
221Starting FULL S3 Public Access Audit for the CURRENT account...
222---
2231. Retrieving all bucket names...
224Processing bucket: 13bf5920-a09f-47bc-a75a-394a09f18d6a
225 Region determined: eu-west-1
226 Final Status: FALSE
227Processing bucket: c67fa6bd-2fd5-4bc5-825d-587fb535bf2e
228 Region determined: eu-west-1
229 Final Status: FALSE
230---
231✅ Audit Complete.
232Final report saved to **s3_full_public_access_audit.csv**
233BucketName,Region,PAB_FullyRestricted,Policy_IsPublic,ACL_AllUsersRead,ACL_AllUsersWrite,OverallPublicStatus
23413bf5920-a09f-47bc-a75a-394a09f18d6a,eu-west-1,FALSE-VULNERABLE,No Policy,FALSE,FALSE,"FALSE"
235c67fa6bd-2fd5-4bc5-825d-587fb535bf2e,eu-west-1,TRUE,No Policy,FALSE,FALSE,"FALSE"
236```
237
238It will also save the results shown above to the `s3_full_public_access_audit.csv` file:
239
240``` csv
241BucketName,Region,PAB_FullyRestricted,Policy_IsPublic,ACL_AllUsersRead,ACL_AllUsersWrite,OverallPublicStatus
24213bf5920-a09f-47bc-a75a-394a09f18d6a,eu-west-1,FALSE-VULNERABLE,No Policy,FALSE,FALSE,"FALSE"
243c67fa6bd-2fd5-4bc5-825d-587fb535bf2e,eu-west-1,TRUE,No Policy,FALSE,FALSE,"FALSE"
207244```
\ No newline at end of file
applications/aws/aws_s3_buckets.sh added +131
@@ -0,0 +1,131 @@
1#!/bin/bash
2
3# --- Configuration ---
4# File to store the final report
5REPORT_FILE="s3_full_public_access_audit.csv"
6# The region to use for the initial global list-buckets call (e.g., 'us-east-1')
7MASTER_REGION="us-east-1"
8
9# AWS Regions to check for bucket location. Add more regions if your organization uses them.
10AWS_REGIONS="us-east-1 us-west-2 eu-central-1 ap-southeast-2"
11
12# --- Initialization ---
13echo "BucketName,Region,PAB_FullyRestricted,Policy_IsPublic,ACL_AllUsersRead,ACL_AllUsersWrite,OverallPublicStatus" > "$REPORT_FILE"
14echo "Starting FULL S3 Public Access Audit for the CURRENT account..."
15echo "---"
16
17# 1. Retrieve all bucket names
18echo "1. Retrieving all bucket names..."
19BUCKET_LIST=$(aws s3api list-buckets --region "$MASTER_REGION" --query 'Buckets[].Name' --output text)
20
21if [ -z "$BUCKET_LIST" ]; then
22 echo "✅ No S3 buckets found in this account."
23 exit 0
24fi
25
26# 2. & 3. Iterate through each bucket to find location and run checks
27for BUCKET_NAME in $BUCKET_LIST; do
28
29 echo "Processing bucket: $BUCKET_NAME"
30 BUCKET_REGION=""
31
32 # 2. Find the bucket region
33 for REGION in $AWS_REGIONS; do
34 BUCKET_LOCATION_RESPONSE=$(aws s3api get-bucket-location --bucket "$BUCKET_NAME" --region "$REGION" 2>/dev/null)
35 if [ $? -eq 0 ]; then
36 LOCATION_CONSTRAINT=$(echo "$BUCKET_LOCATION_RESPONSE" | jq -r '.LocationConstraint')
37 BUCKET_REGION=${LOCATION_CONSTRAINT:-"us-east-1"}
38 break
39 fi
40 done
41
42 if [ -z "$BUCKET_REGION" ]; then
43 echo " ⚠️ WARNING: Could not determine region for $BUCKET_NAME. Skipping all checks."
44 echo "$BUCKET_NAME,UNKNOWN,N/A,N/A,N/A,N/A,UNKNOWN" >> "$REPORT_FILE"
45 continue
46 fi
47
48 echo " Region determined: $BUCKET_REGION"
49
50 # --- Variables for the three checks ---
51 PAB_FULLY_RESTRICTED="UNKNOWN"
52 POLICY_IS_PUBLIC="UNKNOWN"
53 ACL_ALL_USERS_READ="FALSE"
54 ACL_ALL_USERS_WRITE="FALSE"
55 OVERALL_PUBLIC_STATUS="FALSE" # Assume safe until proven otherwise
56
57 # --- CHECK A: Public Access Block (PAB) ---
58 PAB_STATUS=$(aws s3api get-public-access-block --bucket "$BUCKET_NAME" --region "$BUCKET_REGION" 2>/dev/null)
59
60 if [ $? -ne 0 ]; then
61 # PAB Missing is the highest risk state.
62 PAB_FULLY_RESTRICTED="CRITICAL-MISSING"
63 OVERALL_PUBLIC_STATUS="TRUE - PAB Missing"
64 else
65 # Check if ALL four PAB flags are true
66 PAB_CONFIG=$(echo "$PAB_STATUS" | jq -r '.PublicAccessBlockConfiguration')
67 if [ "$(echo "$PAB_CONFIG" | jq -r '.BlockPublicAcls and .IgnorePublicAcls and .BlockPublicPolicy and .RestrictPublicBuckets')" = "true" ]; then
68 PAB_FULLY_RESTRICTED="TRUE"
69 else
70 PAB_FULLY_RESTRICTED="FALSE-VULNERABLE"
71 fi
72 fi
73
74 # --- CHECK B: Bucket Policy Status (If S3 service thinks it's public) ---
75 POLICY_STATUS=$(aws s3api get-bucket-policy-status --bucket "$BUCKET_NAME" --region "$BUCKET_REGION" 2>/dev/null)
76
77 if [ $? -eq 0 ]; then
78 POLICY_IS_PUBLIC=$(echo "$POLICY_STATUS" | jq -r '.PolicyStatus.IsPublic')
79 if [ "$POLICY_IS_PUBLIC" = "true" ]; then
80 OVERALL_PUBLIC_STATUS="TRUE - Policy"
81 fi
82 else
83 # Expected error if no bucket policy exists, treat as NOT public via policy.
84 POLICY_IS_PUBLIC="No Policy"
85 fi
86
87 # --- CHECK C: Bucket ACLs (for AllUsers group) ---
88 ACL_RESPONSE=$(aws s3api get-bucket-acl --bucket "$BUCKET_NAME" --region "$BUCKET_REGION" 2>/dev/null)
89
90 if [ $? -eq 0 ]; then
91 # Find if any grant to 'http://acs.amazonaws.com/groups/global/AllUsers' exists
92
93 # Check for READ access
94 if echo "$ACL_RESPONSE" | jq -e '.Grants[] | select(.Grantee.URI=="http://acs.amazonaws.com/groups/global/AllUsers") | select(.Permission | test("READ|FULL_CONTROL"))' >/dev/null; then
95 ACL_ALL_USERS_READ="TRUE"
96 if [ "$OVERALL_PUBLIC_STATUS" = "FALSE" ]; then
97 OVERALL_PUBLIC_STATUS="TRUE - ACL Read"
98 fi
99 fi
100
101 # Check for WRITE access (often less common for public, but still public exposure)
102 if echo "$ACL_RESPONSE" | jq -e '.Grants[] | select(.Grantee.URI=="http://acs.amazonaws.com/groups/global/AllUsers") | select(.Permission | test("WRITE|FULL_CONTROL"))' >/dev/null; then
103 ACL_ALL_USERS_WRITE="TRUE"
104 if [ "$OVERALL_PUBLIC_STATUS" = "FALSE" ]; then
105 OVERALL_PUBLIC_STATUS="TRUE - ACL Write"
106 fi
107 fi
108 else
109 ACL_ALL_USERS_READ="ACL Check Failed"
110 ACL_ALL_USERS_WRITE="ACL Check Failed"
111 fi
112
113 # Final check for PAB failure (PAB is the highest authority)
114 if [ "$PAB_FULLY_RESTRICTED" = "CRITICAL-MISSING" ]; then
115 OVERALL_PUBLIC_STATUS="TRUE - PAB Missing (CRITICAL)"
116 elif [ "$OVERALL_PUBLIC_STATUS" != "FALSE" ] && [ "$PAB_FULLY_RESTRICTED" != "TRUE" ]; then
117 # If the bucket is found public by Policy or ACL AND PAB isn't fully set, confirm it's public
118 : # Status already set by Policy or ACL check above
119 fi
120
121
122 # --- Save the output as CSV ---
123 echo "$BUCKET_NAME,$BUCKET_REGION,$PAB_FULLY_RESTRICTED,$POLICY_IS_PUBLIC,$ACL_ALL_USERS_READ,$ACL_ALL_USERS_WRITE,\"$OVERALL_PUBLIC_STATUS\"" >> "$REPORT_FILE"
124 echo " Final Status: $OVERALL_PUBLIC_STATUS"
125
126done
127
128echo "---"
129echo "✅ Audit Complete."
130echo "Final report saved to **$REPORT_FILE**"
131cat "$REPORT_FILE"
\ No newline at end of file