Commit fa25287458
Unregistered key
Layout: unified · split
content/blog/2026-02-21-auditing-aws-passwords.org +26 −22
| @@ -29,11 +29,12 @@ testing. | |||
| 29 | 29 | ||
| 30 | The process runs in two steps: | 30 | The process runs in two steps: |
| 31 | 1. ~gather_policy.sh~ calls the AWS CLI to fetch the current IAM password policy, | 31 | 1. ~gather_policy.sh~ calls the AWS CLI to fetch the current IAM password policy, |
| 32 | captures metadata (timestamp, AWS account, region, caller identity), and writes | 32 | captures metadata (timestamp, AWS account, region, caller identity), and |
| 33 | everything to a JSON file. This file is evidence of the policy's current state. | 33 | writes everything to a JSON file. This file is evidence of the policy's |
| 34 | 2. ~evaluate_policy.py~ reads that JSON file, prompts you for the expected value of | 34 | current state. |
| 35 | each setting, and exports a CSV report with a value of ~PASS~ or ~FAIL~ for each | 35 | 2. ~evaluate_policy.py~ reads that JSON file, prompts you for the expected value |
| 36 | rule. | 36 | of each setting, and exports a CSV report with a value of ~PASS~ or ~FAIL~ for |
| 37 | each rule. | ||
| 37 | 38 | ||
| 38 | * Prerequisites | 39 | * Prerequisites |
| 39 | 40 | ||
| @@ -182,32 +183,35 @@ allows you to prove that the data was not modified after the script was run. | |||
| 182 | * Common Exceptions and False Positives | 183 | * Common Exceptions and False Positives |
| 183 | 184 | ||
| 184 | - *No policy defined*: If ~gather_policy.sh~ exits with a ~NoSuchEntity~ error, the | 185 | - *No policy defined*: If ~gather_policy.sh~ exits with a ~NoSuchEntity~ error, the |
| 185 | account has no IAM password policy configured. If you were expecting a password | 186 | account has no IAM password policy configured. If you were expecting a |
| 186 | policy, document it as a missing control. | 187 | password policy, document it as a missing control. |
| 187 | - *HardExpiry: false*: This setting controls whether users are locked out | 188 | - *HardExpiry: false*: This setting controls whether users are locked out |
| 188 | immediately when their password expires or given a grace period to change it. | 189 | immediately when their password expires or given a grace period to change it. |
| 189 | ~false~ is often intentional to avoid lockouts. Check the organization's policy | 190 | ~false~ is often intentional to avoid lockouts. Check the organization's policy |
| 190 | before calling it a finding. Additionally, check if the organization has | 191 | before calling it a finding. Additionally, check if the organization has |
| 191 | security exceptions in place before noting a deficiency. | 192 | security exceptions in place before noting a deficiency. |
| 192 | - *MaxPasswordAge and forced rotation*: A 90-day rotation requirement is common in | 193 | - *MaxPasswordAge and forced rotation*: A 90-day rotation requirement is common in |
| 193 | older policies and frameworks like CIS. NIST 800-63B no longer recommends forced | 194 | older policies and frameworks like CIS. NIST 800-63B no longer recommends |
| 194 | rotation unless there's evidence of compromise. Know which framework you're | 195 | forced rotation unless there's evidence of compromise. Know which framework |
| 195 | auditing against before writing up a finding for this setting. Confirm with the | 196 | you're auditing against before writing up a finding for this setting. Confirm |
| 196 | organization to understand which framework they used to write their policy. | 197 | with the organization to understand which framework they used to write their |
| 197 | - *PasswordReusePrevention*: AWS allows a maximum of 24 previous passwords. If your | 198 | policy. |
| 198 | organization's policy requires a higher number than AWS supports, document the | 199 | - *PasswordReusePrevention*: AWS allows a maximum of 24 previous passwords. If |
| 199 | platform limitation rather than raising it as a deficiency. | 200 | your organization's policy requires a higher number than AWS supports, |
| 201 | document the platform limitation rather than raising it as a deficiency. | ||
| 200 | 202 | ||
| 201 | * How to Write Up the Finding | 203 | * How to Write Up the Finding |
| 202 | 204 | ||
| 203 | If a setting fails, here's how to frame it: | 205 | If a setting fails, here's how to frame it: |
| 204 | - *Deficiency:* The ~MinimumPasswordLength~ setting in the AWS IAM password policy is | 206 | |
| 205 | configured to ~6~, which is below the organization's requirement of ~8~ characters. | 207 | - *Deficiency:* The ~MinimumPasswordLength~ setting in the AWS IAM password policy |
| 208 | is configured to ~6~, which is below the organization's requirement of ~8~ | ||
| 209 | characters. | ||
| 206 | - *Root Cause:* Due to {{ root cause }}, the policy was configured to enforce a | 210 | - *Root Cause:* Due to {{ root cause }}, the policy was configured to enforce a |
| 207 | ~MinimumPasswordLength~ of ~6~. | 211 | ~MinimumPasswordLength~ of ~6~. |
| 208 | - *Risk:* Shorter passwords are more susceptible to brute-force and credential | 212 | - *Risk:* Shorter passwords are more susceptible to brute-force and credential |
| 209 | stuffing attacks, increasing the likelihood of unauthorized access to the AWS | 213 | stuffing attacks, increasing the likelihood of unauthorized access to the AWS |
| 210 | console. | 214 | console. |
| 211 | - *Evidence:* Refer to ~policy_audit_<timestamp>.csv~ for documentation of testing. | 215 | - *Evidence:* Refer to ~policy_audit_<timestamp>.csv~ for documentation of testing. |
| 212 | 216 | ||
| 213 | The same structure applies to any other failing rule. For boolean settings, the | 217 | The same structure applies to any other failing rule. For boolean settings, the |