Merge branch 'master' into master

This commit is contained in:
Toni de la Fuente
2020-12-18 10:24:25 +01:00
committed by GitHub
73 changed files with 626 additions and 156 deletions

View File

@@ -10,7 +10,7 @@
- [Advanced Usage](#advanced-usage)
- [Security Hub integration](#security-hub-integration)
- [CodeBuild deployment](#codebuild-deployment)
- [Whitelist/allowlist or remove FAIL from resources](whitelist-allowlist-or-remove-fail-from-resources)
- [Whitelist/allowlist or remove FAIL from resources](#whitelist-or-allowlist-or-remove-a-fail-from-resources)
- [Fix](#how-to-fix-every-fail)
- [Troubleshooting](#troubleshooting)
- [Extras](#extras)
@@ -54,6 +54,7 @@ Read more about [CIS Amazon Web Services Foundations Benchmark v1.2.0 - 05-23-20
- EKS-CIS
- FFIEC
- SOC2
- ENS (Esquema Nacional de Seguridad of Spain)
With Prowler you can:
@@ -296,9 +297,9 @@ or with a given External ID:
If you want to run Prowler or just a check or a group across all accounts of AWS Organizations you can do this:
First get a list of accounts:
First get a list of accounts that are not suspended:
```
ACCOUNTS_IN_ORGS=$(aws organizations list-accounts --query Accounts[*].Id --output text)
ACCOUNTS_IN_ORGS=$(aws organizations list-accounts --query Accounts[?Status==`ACTIVE`].Id --output text)
```
Then run Prowler to assume a role (same in all members) per each account, in this example it is just running one particular check:
```
@@ -647,4 +648,4 @@ Prowler is licensed as Apache License 2.0 as specified in each file. You may obt
**I'm not related anyhow with CIS organization, I just write and maintain Prowler to help companies over the world to make their cloud infrastructure more secure.**
If you want to contact me visit <https://blyx.com/contact> or follow me on Twitter <https://twitter.com/toniblyx> my DMs are open.
If you want to contact me visit <https://blyx.com/contact> or follow me on Twitter <https://twitter.com/toniblyx> my DMs are open.

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check116="Low"
CHECK_ASFF_TYPE_check116="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check116="AwsIamUser"
CHECK_ALTERNATE_check116="check116"
CHECK_ASFF_COMPLIANCE_TYPE_check116="ens-op.acc.3.aws.iam.1"
check116(){
# "Ensure IAM policies are attached only to groups or roles (Scored)"

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check12="High"
CHECK_ASFF_TYPE_check12="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check12="AwsIamUser"
CHECK_ALTERNATE_check102="check12"
CHECK_ASFF_COMPLIANCE_TYPE_check12="ens-op.acc.5.aws.iam.1"
check12(){
# "Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)"

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check120="Medium"
CHECK_ASFF_TYPE_check120="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check120="AwsIamRole"
CHECK_ALTERNATE_check120="check120"
CHECK_ASFF_COMPLIANCE_TYPE_check120="ens-op.acc.1.aws.iam.4"
check120(){
# "Ensure a support role has been created to manage incidents with AWS Support (Scored)"

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check121="Medium"
CHECK_ASFF_TYPE_check121="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check121="AwsIamUser"
CHECK_ALTERNATE_check121="check121"
CHECK_ASFF_COMPLIANCE_TYPE_check121="ens-op.acc.1.aws.iam.5"
check121(){
# "Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)"

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check13="Medium"
CHECK_ASFF_TYPE_check13="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check13="AwsIamUser"
CHECK_ALTERNATE_check103="check13"
CHECK_ASFF_COMPLIANCE_TYPE_check13="ens-op.acc.1.aws.iam.3,ens-op.acc.5.aws.iam.4"
check13(){
check_creds_used_in_last_days 90

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check14="Medium"
CHECK_ASFF_TYPE_check14="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check14="AwsIamUser"
CHECK_ALTERNATE_check104="check14"
CHECK_ASFF_COMPLIANCE_TYPE_check14="ens-op.acc.1.aws.iam.4,ens-op.acc.5.aws.iam.3"
check14(){
# "Ensure access keys are rotated every 90 days or less (Scored)" # also checked by Security Monkey

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check21="High"
CHECK_ASFF_TYPE_check21="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check21="AwsCloudTrailTrail"
CHECK_ALTERNATE_check201="check21"
CHECK_ASFF_COMPLIANCE_TYPE_check21="ens-op.acc.7.aws.iam.1,ens-op.mon.1.aws.trail.1"
check21(){
trail_count=0

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check22="Medium"
CHECK_ASFF_TYPE_check22="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check22="AwsCloudTrailTrail"
CHECK_ALTERNATE_check202="check22"
CHECK_ASFF_COMPLIANCE_TYPE_check22="ens-op.exp.10.aws.trail.1"
check22(){
# "Ensure CloudTrail log file validation is enabled (Scored)"

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check23="Critical"
CHECK_ASFF_TYPE_check23="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check23="AwsS3Bucket"
CHECK_ALTERNATE_check203="check23"
CHECK_ASFF_COMPLIANCE_TYPE_check23="ens-op.exp.10.aws.trail.3,ens-op.exp.10.aws.trail.4"
check23(){
# "Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)"

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check24="Low"
CHECK_ASFF_TYPE_check24="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check24="AwsCloudTrailTrail"
CHECK_ALTERNATE_check204="check24"
CHECK_ASFF_COMPLIANCE_TYPE_check24="ens-op.exp.8.aws.cw.1"
check24(){
# "Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)"

View File

@@ -15,6 +15,7 @@ CHECK_TYPE_check25="LEVEL1"
CHECK_SEVERITY_check25="Medium"
CHECK_ASFF_TYPE_check25="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ALTERNATE_check205="check25"
CHECK_ASFF_COMPLIANCE_TYPE_check25="ens-op.exp.1.aws.cfg.1"
check25(){
# "Ensure AWS Config is enabled in all regions (Scored)"

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check27="Medium"
CHECK_ASFF_TYPE_check27="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check27="AwsCloudTrailTrail"
CHECK_ALTERNATE_check207="check27"
CHECK_ASFF_COMPLIANCE_TYPE_check27="ens-op.exp.10.aws.trail.5"
check27(){
# "Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)"

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check29="Medium"
CHECK_ASFF_TYPE_check29="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check29="AwsEc2Vpc"
CHECK_ALTERNATE_check209="check29"
CHECK_ASFF_COMPLIANCE_TYPE_check29="ens-op.mon.1.aws.flow.1"
check29(){
# "Ensure VPC Flow Logging is Enabled in all VPCs (Scored)"

View File

@@ -41,6 +41,7 @@ CHECK_SEVERITY_check31="Medium"
CHECK_ASFF_TYPE_check31="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check31="AwsCloudTrailTrail"
CHECK_ALTERNATE_check301="check31"
CHECK_ASFF_COMPLIANCE_TYPE_check31="ens-op.exp.8.aws.trail.2"
check31(){
check3x '\$\.errorCode\s*=\s*"\*UnauthorizedOperation".+\$\.errorCode\s*=\s*"AccessDenied\*"'

View File

@@ -41,6 +41,7 @@ CHECK_SEVERITY_check32="Medium"
CHECK_ASFF_TYPE_check32="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check32="AwsCloudTrailTrail"
CHECK_ALTERNATE_check302="check32"
CHECK_ASFF_COMPLIANCE_TYPE_check32="ens-op.exp.8.aws.trail.4"
check32(){
check3x '\$\.eventName\s*=\s*"ConsoleLogin".+\$\.additionalEventData\.MFAUsed\s*!=\s*"Yes"'

View File

@@ -41,6 +41,7 @@ CHECK_SEVERITY_check33="Medium"
CHECK_ASFF_TYPE_check33="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check33="AwsCloudTrailTrail"
CHECK_ALTERNATE_check303="check33"
CHECK_ASFF_COMPLIANCE_TYPE_check33="ens-op.exp.8.aws.trail.5"
check33(){
check3x '\$\.userIdentity\.type\s*=\s*"Root".+\$\.userIdentity\.invokedBy NOT EXISTS.+\$\.eventType\s*!=\s*"AwsServiceEvent"'

View File

@@ -41,6 +41,7 @@ CHECK_SEVERITY_check34="Medium"
CHECK_ASFF_TYPE_check34="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check34="AwsCloudTrailTrail"
CHECK_ALTERNATE_check304="check34"
CHECK_ASFF_COMPLIANCE_TYPE_check34="ens-op.exp.8.aws.trail.6"
check34(){
check3x '\$\.eventName\s*=\s*DeleteGroupPolicy.+\$\.eventName\s*=\s*DeleteRolePolicy.+\$\.eventName\s*=\s*DeleteUserPolicy.+\$\.eventName\s*=\s*PutGroupPolicy.+\$\.eventName\s*=\s*PutRolePolicy.+\$\.eventName\s*=\s*PutUserPolicy.+\$\.eventName\s*=\s*CreatePolicy.+\$\.eventName\s*=\s*DeletePolicy.+\$\.eventName\s*=\s*CreatePolicyVersion.+\$\.eventName\s*=\s*DeletePolicyVersion.+\$\.eventName\s*=\s*AttachRolePolicy.+\$\.eventName\s*=\s*DetachRolePolicy.+\$\.eventName\s*=\s*AttachUserPolicy.+\$\.eventName\s*=\s*DetachUserPolicy.+\$\.eventName\s*=\s*AttachGroupPolicy.+\$\.eventName\s*=\s*DetachGroupPolicy'

View File

@@ -41,6 +41,7 @@ CHECK_SEVERITY_check35="Medium"
CHECK_ASFF_TYPE_check35="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check35="AwsCloudTrailTrail"
CHECK_ALTERNATE_check305="check35"
CHECK_ASFF_COMPLIANCE_TYPE_check35="ens-op.exp.8.aws.trail.1"
check35(){
check3x '\$\.eventName\s*=\s*CreateTrail.+\$\.eventName\s*=\s*UpdateTrail.+\$\.eventName\s*=\s*DeleteTrail.+\$\.eventName\s*=\s*StartLogging.+\$\.eventName\s*=\s*StopLogging'

View File

@@ -41,6 +41,7 @@ CHECK_SEVERITY_check36="Medium"
CHECK_ASFF_TYPE_check36="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check36="AwsCloudTrailTrail"
CHECK_ALTERNATE_check306="check36"
CHECK_ASFF_COMPLIANCE_TYPE_check36="ens-op.exp.8.aws.trail.3"
check36(){
check3x '\$\.eventName\s*=\s*ConsoleLogin.+\$\.errorMessage\s*=\s*"Failed authentication"'

View File

@@ -41,6 +41,7 @@ CHECK_SEVERITY_check37="Medium"
CHECK_ASFF_TYPE_check37="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check37="AwsCloudTrailTrail"
CHECK_ALTERNATE_check307="check37"
CHECK_ASFF_COMPLIANCE_TYPE_check37="ens-op.exp.11.aws.kms.1"
check37(){
check3x '\$\.eventSource\s*=\s*kms.amazonaws.com.+\$\.eventName\s*=\s*DisableKey.+\$\.eventName\s*=\s*ScheduleKeyDeletion'

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check41="High"
CHECK_ASFF_TYPE_check41="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check41="AwsEc2SecurityGroup"
CHECK_ALTERNATE_check401="check41"
CHECK_ASFF_COMPLIANCE_TYPE_check41="ens-mp.com.4.aws.sg.4"
check41(){
# "Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to port 22 (Scored)"

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check42="High"
CHECK_ASFF_TYPE_check42="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check42="AwsEc2SecurityGroup"
CHECK_ALTERNATE_check402="check42"
CHECK_ASFF_COMPLIANCE_TYPE_check42="ens-mp.com.4.aws.sg.5"
check42(){
# "Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to port 3389 (Scored)"

View File

@@ -16,6 +16,7 @@ CHECK_SEVERITY_check43="Medium"
CHECK_ASFF_TYPE_check43="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_check43="AwsEc2SecurityGroup"
CHECK_ALTERNATE_check403="check43"
CHECK_ASFF_COMPLIANCE_TYPE_check43="ens-mp.com.4.aws.sg.1"
check43(){
# "Ensure the default security group of every VPC restricts all traffic (Scored)"

View File

@@ -19,6 +19,7 @@ CHECK_ASFF_RESOURCE_TYPE_extra71="AwsIamUser"
CHECK_ALTERNATE_extra701="extra71"
CHECK_ALTERNATE_check71="extra71"
CHECK_ALTERNATE_check701="extra71"
CHECK_ASFF_COMPLIANCE_TYPE_extra71="ens-op.exp.10.aws.trail.2"
extra71(){
# "Ensure users of groups with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)"

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra710="EXTRA"
CHECK_SEVERITY_extra710="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra710="AwsEc2Instance"
CHECK_ALTERNATE_check710="extra710"
CHECK_ASFF_COMPLIANCE_TYPE_extra710="ens-mp.com.4.aws.vpc.1"
extra710(){
# "Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)"

View File

@@ -21,6 +21,7 @@ CHECK_TYPE_extra7100="EXTRA"
CHECK_SEVERITY_extra7100="Critical"
CHECK_ASFF_RESOURCE_TYPE_extra7100="AwsIamPolicy"
CHECK_ALTERNATE_check7100="extra7100"
CHECK_ASFF_COMPLIANCE_TYPE_extra7100="ens-op.acc.2.aws.iam.1"
extra7100(){
# "Ensure that no custom policies exist which permit assuming any role (e.g. sts:AssumeRole on *)"

View File

@@ -22,21 +22,22 @@ CHECK_ALTERNATE_check7102="extra7102"
# your IP will be banned by Shodan
# This is the right way to do so
# curl -ks https://api.shodan.io/shodan/host/{ip}?key={YOUR_API_KEY}
# curl -ks https://api.shodan.io/shodan/host/{ip}?key={YOUR_API_KEY}
# Each finding will be saved in prowler/output folder for further review.
SHODAN_API_KEY=""
extra7102(){
if [[ ! $SHODAN_API_KEY ]]; then
textInfo "[extra7102] Requires a Shodan API key to work. Edit checks/check_extra7102 first"
textInfo "[extra7102] Requires a Shodan API key to work. Use -N <shodan_api_key>"
else
for regx in $REGIONS; do
LIST_OF_EIP=$($AWSCLI $PROFILE_OPT --region $regx ec2 describe-addresses --query 'Addresses[*].PublicIp' --output text)
if [[ $LIST_OF_EIP ]]; then
for ip in $LIST_OF_EIP;do
SHODAN_QUERY=$(curl -ks https://api.shodan.io/shodan/host/$ip?key=$SHODAN_API_KEY)
# Shodan has a request rate limit of 1 request/second.
sleep 1
if [[ $SHODAN_QUERY == *"No information available for that IP"* ]]; then
textPass "$regx: IP $ip is not listed in Shodan" "$regx"
else

33
checks/check_extra7123 Normal file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7123="7.123"
CHECK_TITLE_extra7123="[extra7123] Check if IAM users have two active access keys"
CHECK_SCORED_extra7123="NOT_SCORED"
CHECK_TYPE_extra7123="EXTRA"
CHECK_SEVERITY_extra7123="Medium"
CHECK_ASFF_TYPE_extra7123="Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"
CHECK_ASFF_RESOURCE_TYPE_extra7123="AwsIamUser"
CHECK_ALTERNATE_check7123="extra7123"
CHECK_ASFF_COMPLIANCE_TYPE_extra7123="ens-op.acc.1.aws.iam.2"
extra7123(){
LIST_OF_USERS_WITH_2ACCESS_KEYS=$(cat $TEMP_REPORT_FILE| awk -F, '{ print $1, $9, $14 }' |grep "\ true\ true" | awk '{ print $1 }')
if [[ $LIST_OF_USERS_WITH_2ACCESS_KEYS ]]; then
# textFail "Users with access key 1 older than 90 days:"
for user in $LIST_OF_USERS_WITH_2ACCESS_KEYS; do
textFail "User $user has 2 active access keys"
done
else
textPass "No users with 2 active access keys"
fi
}

43
checks/check_extra7124 Normal file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7124="7.124"
CHECK_TITLE_extra7124="[extra7124] Check if EC2 instances are managed by Systems Manager."
CHECK_SCORED_extra7124="NOT_SCORED"
CHECK_TYPE_extra7124="EXTRA"
CHECK_SEVERITY_extra7124="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7124="AwsEc2Instance"
CHECK_ALTERNATE_check7124="extra7124"
CHECK_ASFF_COMPLIANCE_TYPE_extra7124="ens-op.exp.1.aws.sys.1,ens-op.acc.4.aws.sys.1"
extra7124(){
for regx in $REGIONS; do
# Filters running instances only
LIST_EC2_INSTANCES=$($AWSCLI ec2 describe-instances $PROFILE_OPT --query 'Reservations[*].Instances[*].[InstanceId]' --filters Name=instance-state-name,Values=running --region $regx --output text)
if [[ $LIST_EC2_INSTANCES ]]; then
LIST_SSM_MANAGED_INSTANCES=$($AWSCLI ssm describe-instance-information $PROFILE_OPT --query "InstanceInformationList[].InstanceId" --region $regx | jq -r '.[]')
LIST_EC2_UNMANAGED=$(echo ${LIST_SSM_MANAGED_INSTANCES[@]} ${LIST_EC2_INSTANCES[@]} | tr ' ' '\n' | sort | uniq -u)
if [[ $LIST_EC2_UNMANAGED ]]; then
for instance in $LIST_EC2_UNMANAGED; do
textFail "$regx: EC2 instance $instance is not managed by Systems Manager" "$regx"
done
fi
if [[ $LIST_SSM_MANAGED_INSTANCES ]]; then
for instance in $LIST_SSM_MANAGED_INSTANCES; do
textPass "$regx: EC2 instance $instance is managed by Systems Manager" "$regx"
done
fi
else
textInfo "$regx: No EC2 instances running found" "$regx"
fi
done
}

40
checks/check_extra7125 Normal file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7125="7.125"
CHECK_TITLE_extra7125="[extra7125] Check if IAM users have Hardware MFA enabled."
CHECK_SCORED_extra7125="NOT_SCORED"
CHECK_TYPE_extra7125="EXTRA"
CHECK_SEVERITY_extra7125="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7125="AwsIamUser"
CHECK_ALTERNATE_check7125="extra7125"
CHECK_ASFF_COMPLIANCE_TYPE_extra7125="ens-op.acc.5.aws.iam.2"
extra7125(){
LIST_USERS=$($AWSCLI iam list-users --query 'Users[*].UserName' --output text $PROFILE_OPT --region $REGION)
if [[ $LIST_USERS ]]; then
# textFail "Users with access key 1 older than 90 days:"
for user in $LIST_USERS; do
# Would be virtual if sms-mfa or mfa, hardware is u2f or different.
MFA_TYPE=$($AWSCLI iam list-mfa-devices --user-name $user $PROFILE_OPT --region $REGION --query MFADevices[].SerialNumber --output text | awk -F':' '{ print $6 }'| awk -F'/' '{ print $1 }')
if [[ $MFA_TYPE == "mfa" || $MFA_TYPE == "sms-mfa" ]]; then
textInfo "User $user has virtual MFA enabled"
elif [[ $MFA_TYPE == "" ]]; then
textFail "User $user has not hardware MFA enabled"
else
textPass "User $user has hardware MFA enabled"
fi
done
else
textPass "No users found"
fi
}

40
checks/check_extra7126 Normal file
View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7126="7.126"
CHECK_TITLE_extra7126="[extra7126] Check if there are CMK KMS keys not used"
CHECK_SCORED_extra7126="NOT_SCORED"
CHECK_TYPE_extra7126="EXTRA"
CHECK_SEVERITY_extra7126="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7126="AwsKmsKey"
CHECK_ALTERNATE_check7126="extra7126"
CHECK_ASFF_COMPLIANCE_TYPE_extra7126="op.exp.11.aws.kms.2"
extra7126(){
for regx in $REGIONS; do
LIST_OF_CUSTOMER_KMS_KEYS=$($AWSCLI kms list-aliases $PROFILE_OPT --region $regx --output text |grep -v :alias/aws/ |awk '{ print $4 }')
if [[ $LIST_OF_CUSTOMER_KMS_KEYS ]];then
for key in $LIST_OF_CUSTOMER_KMS_KEYS; do
CHECK_STATUS=$($AWSCLI kms describe-key --key-id $key $PROFILE_OPT --region $regx --output json | jq -r '.KeyMetadata.KeyState')
if [[ $CHECK_STATUS == "PendingDeletion" ]]; then
textInfo "$regx: KMS key $key is pending deletion" "$regx"
elif [[ $CHECK_STATUS == "Disabled" ]]; then
textInfo "$regx: KMS key $key is disabled" "$regx"
else
textPass "$regx: KMS key $key is not disabled or pending deletion" "$regx"
fi
done
else
textInfo "$regx: No KMS keys found" "$regx"
fi
done
}

43
checks/check_extra7127 Normal file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7127="7.127"
CHECK_TITLE_extra7127="[extra7127] Check if EC2 instances managed by Systems Manager are compliant with patching requirements"
CHECK_SCORED_extra7127="NOT_SCORED"
CHECK_TYPE_extra7127="EXTRA"
CHECK_SEVERITY_extra7127="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7127="AwsEc2Instance"
CHECK_ASFF_TYPE_extra7127="Software and Configuration Checks/ENS op.exp.4.aws.sys.1"
CHECK_ALTERNATE_check7127="extra7127"
CHECK_ASFF_COMPLIANCE_TYPE_extra7127="ens-op.exp.1.aws.sys.1,ens-op.exp.4.aws.sys.1"
extra7127(){
for regx in $REGIONS; do
NON_COMPLIANT_SSM_MANAGED_INSTANCES=$($AWSCLI ssm list-resource-compliance-summaries $PROFILE_OPT --region $regx --filters Key=Status,Values=NON_COMPLIANT --query ResourceComplianceSummaryItems[].ResourceId --output text)
COMPLIANT_SSM_MANAGED_INSTANCES=$($AWSCLI ssm list-resource-compliance-summaries $PROFILE_OPT --region $regx --filters Key=Status,Values=COMPLIANT --query ResourceComplianceSummaryItems[].ResourceId --output text)
if [[ $NON_COMPLIANT_SSM_MANAGED_INSTANCES || $COMPLIANT_SSM_MANAGED_INSTANCES ]]; then
if [[ $NON_COMPLIANT_SSM_MANAGED_INSTANCES ]]; then
for instance in $NON_COMPLIANT_SSM_MANAGED_INSTANCES; do
textFail "$regx: EC2 managed instance $instance is non-compliant" "$regx"
done
fi
if [[ $COMPLIANT_SSM_MANAGED_INSTANCES ]]; then
for instance in $COMPLIANT_SSM_MANAGED_INSTANCES; do
textPass "$regx: EC2 managed instance $instance is compliant" "$regx"
done
fi
else
textInfo "$regx: No EC2 managed instances found" "$regx"
fi
done
}

38
checks/check_extra7128 Normal file
View File

@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7128="7.128"
CHECK_TITLE_extra7128="[extra7128] Check if DynamoDB table has encryption at rest enabled using CMK KMS"
CHECK_SCORED_extra7128="NOT_SCORED"
CHECK_TYPE_extra7128="EXTRA"
CHECK_SEVERITY_extra7128="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7128="AwsDynamoDBTable"
CHECK_ALTERNATE_check7128="extra7128"
CHECK_ASFF_COMPLIANCE_TYPE_extra7128="ens-mp.info.3.aws.dyndb.1"
extra7128(){
for regx in $REGIONS; do
DDB_TABLES_LIST=$($AWSCLI dynamodb list-tables $PROFILE_OPT --region $regx --output text --query TableNames)
if [[ $DDB_TABLES_LIST ]]; then
for table in $DDB_TABLES_LIST; do
DDB_TABLE_WITH_KMS=$($AWSCLI dynamodb describe-table --table-name $table $PROFILE_OPT --region $regx --query Table.SSEDescription.SSEType --output text)
if [[ $DDB_TABLE_WITH_KMS == "KMS" ]]; then
textPass "$regx: DynamoDB table $table does have KMS encryption enabled" "$regx"
else
textInfo "$regx: DynamoDB table $table does have DEFAULT encryption enabled" "$regx"
fi
done
else
textInfo "$regx: There are no DynamoDB tables" "$regx"
fi
done
}

52
checks/check_extra7129 Normal file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2018) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7129="7.129"
CHECK_TITLE_extra7129="[extra7129] Check if Application Load Balancer has a WAF ACL attached"
CHECK_SCORED_extra7129="NOT_SCORED"
CHECK_TYPE_extra7129="EXTRA"
CHECK_SEVERITY_extra7129="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra7129="AwsElasticLoadBalancingV2LoadBalancer"
CHECK_ALTERNATE_check7129="extra7129"
CHECK_ASFF_COMPLIANCE_TYPE_extra7129="ens-mp.s.2.aws.waf.3"
extra7129(){
for regx in $REGIONS; do
LIST_OF_ELBSV2=$($AWSCLI elbv2 describe-load-balancers $PROFILE_OPT --region $regx --query 'LoadBalancers[?Scheme == `internet-facing` && Type == `application`].[LoadBalancerName]' --output text)
LIST_OF_WAFV2_WEBACL_ARN=$($AWSCLI wafv2 list-web-acls $PROFILE_OPT --region=$regx --scope=REGIONAL --query WebACLs[*].ARN --output text)
if [[ $LIST_OF_ELBSV2 ]]; then
for alb in $LIST_OF_ELBSV2; do
if [[ $LIST_OF_WAFV2_WEBACL_ARN ]]; then
WAF_PROTECTED_ALBS=()
for wafaclarn in $LIST_OF_WAFV2_WEBACL_ARN; do
ALB_RESOURCES_IN_WEBACL=$($AWSCLI wafv2 list-resources-for-web-acl $PROFILE_OPT --web-acl-arn $wafaclarn --region=$regx --resource-type APPLICATION_LOAD_BALANCER --query ResourceArns --output text | xargs -n1 | awk -F'/' '{ print $3 }'| grep $alb)
if [[ $ALB_RESOURCES_IN_WEBACL ]]; then
WAF_PROTECTED_ALBS+=($wafaclarn)
fi
done
if [[ ${#WAF_PROTECTED_ALBS[@]} -gt 0 ]]; then
for wafaclarn in "${WAF_PROTECTED_ALBS[@]}"; do
WAFV2_WEBACL_ARN_SHORT=$(echo $wafaclarn | awk -F'/' '{ print $3 }')
textPass "$regx: Application Load Balancer $alb is protected by WAFv2 ACL $WAFV2_WEBACL_ARN_SHORT" "$regx"
done
else
textFail "$regx: Application Load Balancer $alb is not protected by WAFv2 ACL" "$regx"
fi
else
textFail "$regx: Application Load Balancer $alb is not protected no WAFv2 ACL found" "$regx"
fi
done
else
textInfo "$regx: No Application Load Balancers found" "$regx"
fi
done
}

View File

@@ -16,6 +16,7 @@ CHECK_SCORED_extra713="NOT_SCORED"
CHECK_TYPE_extra713="EXTRA"
CHECK_SEVERITY_extra713="High"
CHECK_ALTERNATE_check713="extra713"
CHECK_ASFF_COMPLIANCE_TYPE_extra713="ens-op.mon.1.aws.duty.1"
extra713(){
# "Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)"

View File

@@ -18,6 +18,7 @@ CHECK_TYPE_extra728="EXTRA"
CHECK_SEVERITY_extra728="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra728="AwsSqsQueue"
CHECK_ALTERNATE_check728="extra728"
CHECK_ASFF_COMPLIANCE_TYPE_extra728="ens-mp.info.3.sns.1"
extra728(){
for regx in $REGIONS; do

View File

@@ -18,6 +18,7 @@ CHECK_TYPE_extra729="EXTRA"
CHECK_SEVERITY_extra729="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra729="AwsEc2Volume"
CHECK_ALTERNATE_check729="extra729"
CHECK_ASFF_COMPLIANCE_TYPE_extra729="ens-mp.info.3.aws.ebs.1"
extra729(){
# "Ensure there are no EBS Volumes unencrypted (Not Scored) (Not part of CIS benchmark)"

View File

@@ -17,6 +17,7 @@ CHECK_SCORED_extra733="NOT_SCORED"
CHECK_TYPE_extra733="EXTRA"
CHECK_SEVERITY_extra733="Low"
CHECK_ALTERNATE_check733="extra733"
CHECK_ASFF_COMPLIANCE_TYPE_extra733="ens-op.acc.1.aws.iam.1"
extra733(){
LIST_SAML_PROV=$($AWSCLI iam list-saml-providers $PROFILE_OPT --query 'SAMLProviderList[*].Arn' --output text |grep -v ^None)
@@ -26,6 +27,6 @@ extra733(){
textInfo "SAML Provider $PROVIDER_NAME has been found"
done
else
textInfo "No SAML Provider found, add one and use STS"
textInfo "No SAML Provider found. Add one and use STS"
fi
}

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra734="EXTRA"
CHECK_SEVERITY_extra734="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra734="AwsS3Bucket"
CHECK_ALTERNATE_check734="extra734"
CHECK_ASFF_COMPLIANCE_TYPE_extra734="ens-mp.info.3.s3.1"
extra734(){
LIST_OF_BUCKETS=$($AWSCLI s3api list-buckets $PROFILE_OPT --region $REGION --query Buckets[*].Name --output text|xargs -n1)

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra735="EXTRA"
CHECK_SEVERITY_extra735="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra735="AwsRdsDbInstance"
CHECK_ALTERNATE_check735="extra735"
CHECK_ASFF_COMPLIANCE_TYPE_extra735="ens-mp.info.3.aws.rds.1"
extra735(){
textInfo "Looking for RDS Volumes in all regions... "

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra736="EXTRA"
CHECK_SEVERITY_extra736="Critical"
CHECK_ASFF_RESOURCE_TYPE_extra736="AwsKmsKey"
CHECK_ALTERNATE_check736="extra736"
CHECK_ASFF_COMPLIANCE_TYPE_extra736="ens-op.exp.11.aws.kms.2"
extra736(){
textInfo "Looking for KMS keys in all regions... "

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra737="EXTRA"
CHECK_SEVERITY_extra737="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra737="AwsKmsKey"
CHECK_ALTERNATE_check737="extra737"
CHECK_ASFF_COMPLIANCE_TYPE_extra737="ens-op.exp.11.aws.kms.3"
extra737(){
textInfo "Looking for KMS keys in all regions... "

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra738="EXTRA"
CHECK_SEVERITY_extra738="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra738="AwsCloudFrontDistribution"
CHECK_ALTERNATE_check738="extra738"
CHECK_ASFF_COMPLIANCE_TYPE_extra738="ens-mp.com.2.aws.front.1"
extra738(){
LIST_OF_DISTRIBUTIONS=$($AWSCLI cloudfront list-distributions --query 'DistributionList.Items[*].Id' $PROFILE_OPT --output text|grep -v ^None)

View File

@@ -19,6 +19,7 @@ CHECK_ASFF_RESOURCE_TYPE_extra74="AwsEc2SecurityGroup"
CHECK_ALTERNATE_extra704="extra74"
CHECK_ALTERNATE_check74="extra74"
CHECK_ALTERNATE_check704="extra74"
CHECK_ASFF_COMPLIANCE_TYPE_extra74="ens-mp.com.4.aws.sg.2"
extra74(){
# "Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)"

View File

@@ -17,22 +17,67 @@ CHECK_TYPE_extra740="EXTRA"
CHECK_SEVERITY_extra740="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra740="AwsEc2Snapshot"
CHECK_ALTERNATE_check740="extra740"
CHECK_ASFF_COMPLIANCE_TYPE_extra740="ens-mp.info.3.aws.ebs.3"
extra740(){
textInfo "Looking for EBS Snapshots in all regions... "
for regx in $REGIONS; do
LIST_OF_EBS_SNAPSHOTS=$($AWSCLI ec2 describe-snapshots $PROFILE_OPT --region $regx --owner-ids $ACCOUNT_NUM --output text --query 'Snapshots[*].{ID:SnapshotId}' --max-items $MAXITEMS | grep -v None 2> /dev/null)
if [[ $LIST_OF_EBS_SNAPSHOTS ]];then
for snapshot in $LIST_OF_EBS_SNAPSHOTS; do
SNAPSHOT_IS_ENCRYPTED=$($AWSCLI ec2 describe-snapshots $PROFILE_OPT --region $regx --output text --snapshot-id $snapshot --query Snapshots[*].Encrypted|grep False)
if [[ $SNAPSHOT_IS_ENCRYPTED ]];then
textFail "$regx: $snapshot is currently not encrypted!" "$regx"
else
textPass "$regx: $snapshot is encrypted" "$regx"
fi
textInfo "Examining EBS Volume Snapshots ..."
# This does NOT use max-items, which would limit the number of items
# considered. It considers all snapshots, but only reports at most
# max-items passing and max-items failing.
for regx in ${REGIONS}; do
UNENCRYPTED_SNAPSHOTS=$(${AWSCLI} ec2 describe-snapshots ${PROFILE_OPT} \
--region ${regx} --owner-ids ${ACCOUNT_NUM} --output text \
--query 'Snapshots[?Encrypted==`false`]|[*].{Id:SnapshotId}' \
| grep -v None 2> /dev/null)
ENCRYPTED_SNAPSHOTS=$(${AWSCLI} ec2 describe-snapshots ${PROFILE_OPT} \
--region ${regx} --owner-ids ${ACCOUNT_NUM} --output text \
--query 'Snapshots[?Encrypted==`true`]|[*].{Id:SnapshotId}' \
| grep -v None 2> /dev/null)
typeset -i unencrypted
typeset -i encrypted
unencrypted=0
encrypted=0
if [[ ${UNENCRYPTED_SNAPSHOTS} ]]; then
for snapshot in ${UNENCRYPTED_SNAPSHOTS}; do
unencrypted=${unencrypted}+1
if [ "${unencrypted}" -le "${MAXITEMS}" ]; then
textFail "${regx}: ${snapshot} is not encrypted!" "${regx}"
fi
done
fi
if [[ ${ENCRYPTED_SNAPSHOTS} ]]; then
for snapshot in ${ENCRYPTED_SNAPSHOTS}; do
encrypted=${encrypted}+1
if [ "${encrypted}" -le "${MAXITEMS}" ]; then
textPass "${regx}: ${snapshot} is encrypted." "${regx}"
fi
done
fi
if [[ "${encrypted}" = "0" ]] && [[ "${unencrypted}" = "0" ]] ; then
textInfo "${regx}: No EBS volume snapshots" "${regx}"
else
textInfo "$regx: No EBS Snapshots found" "$regx"
typeset -i total
total=${encrypted}+${unencrypted}
if [[ "${unencrypted}" -ge "${MAXITEMS}" ]]; then
textFail "${unencrypted} unencrypted snapshots out of ${total} snapshots found. Only the first ${MAXITEMS} unencrypted snapshots are reported!"
fi
if [[ "${encrypted}" -ge "${MAXITEMS}" ]]; then
textPass "${encrypted} encrypted snapshots out of ${total} snapshots found. Only the first ${MAXITEMS} encrypted snapshots are reported."
fi
# Bit of 'bc' magic to print something like 10.42% or 0.85% or similar. 'bc' has a
# bug where it will never print leading zeros. So 0.5 is output as ".5". This has a
# little extra clause to print a 0 if 0 < x < 1.
ratio=$(echo "scale=2; p=(100*${encrypted}/(${encrypted}+${unencrypted})); if(p<1 && p>0) print 0;print p, \"%\";" | bc 2>/dev/null)
exit=$?
# maybe 'bc' doesn't exist, or it exits with an error
if [[ "${exit}" = "0" ]]
then
textInfo "${regx}: ${ratio} encrypted EBS volumes (${encrypted} out of ${total})" "${regx}"
else
textInfo "${regx}: ${unencrypted} unencrypted EBS volume snapshots out of ${total} total snapshots" "${regx}"
fi
fi
done
}

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra744="EXTRA"
CHECK_SEVERITY_extra744="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra744="AwsApiGatewayRestApi"
CHECK_ALTERNATE_check744="extra744"
CHECK_ASFF_COMPLIANCE_TYPE_extra744="ens-mp.s.2.aws.waf.2"
extra744(){
for regx in $REGIONS; do

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra749="EXTRA"
CHECK_SEVERITY_extra749="High"
CHECK_ASFF_RESOURCE_TYPE_extra749="AwsEc2SecurityGroup"
CHECK_ALTERNATE_check749="extra749"
CHECK_ASFF_COMPLIANCE_TYPE_extra749="ens-mp.com.4.aws.sg.6"
extra749(){
for regx in $REGIONS; do

View File

@@ -19,6 +19,7 @@ CHECK_ASFF_RESOURCE_TYPE_extra75="AwsEc2SecurityGroup"
CHECK_ALTERNATE_extra705="extra75"
CHECK_ALTERNATE_check75="extra75"
CHECK_ALTERNATE_check705="extra75"
CHECK_ASFF_COMPLIANCE_TYPE_extra75="ens-mp.com.4.aws.sg.3"
extra75(){
# "Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)"

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra750="EXTRA"
CHECK_SEVERITY_extra750="High"
CHECK_ASFF_RESOURCE_TYPE_extra750="AwsEc2SecurityGroup"
CHECK_ALTERNATE_check750="extra750"
CHECK_ASFF_COMPLIANCE_TYPE_extra750="ens-mp.com.4.aws.sg.7"
extra750(){
for regx in $REGIONS; do

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra751="EXTRA"
CHECK_SEVERITY_extra751="High"
CHECK_ASFF_RESOURCE_TYPE_extra751="AwsEc2SecurityGroup"
CHECK_ALTERNATE_check751="extra751"
CHECK_ASFF_COMPLIANCE_TYPE_extra751="ens-mp.com.4.aws.sg.8"
extra751(){
for regx in $REGIONS; do

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra752="EXTRA"
CHECK_SEVERITY_extra752="High"
CHECK_ASFF_RESOURCE_TYPE_extra752="AwsEc2SecurityGroup"
CHECK_ALTERNATE_check752="extra752"
CHECK_ASFF_COMPLIANCE_TYPE_extra752="ens-mp.com.4.aws.sg.9"
extra752(){
for regx in $REGIONS; do

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra753="EXTRA"
CHECK_SEVERITY_extra753="High"
CHECK_ASFF_RESOURCE_TYPE_extra753="AwsEc2SecurityGroup"
CHECK_ALTERNATE_check753="extra753"
CHECK_ASFF_COMPLIANCE_TYPE_extra753="ens-mp.com.4.aws.sg.10"
extra753(){
for regx in $REGIONS; do

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra754="EXTRA"
CHECK_SEVERITY_extra754="High"
CHECK_ASFF_RESOURCE_TYPE_extra754="AwsEc2SecurityGroup"
CHECK_ALTERNATE_check754="extra754"
CHECK_ASFF_COMPLIANCE_TYPE_extra754="ens-mp.com.4.aws.sg.11"
extra754(){
for regx in $REGIONS; do

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra755="EXTRA"
CHECK_SEVERITY_extra755="High"
CHECK_ASFF_RESOURCE_TYPE_extra755="AwsEc2SecurityGroup"
CHECK_ALTERNATE_check755="extra755"
CHECK_ASFF_COMPLIANCE_TYPE_extra755="ens-mp.com.4.aws.sg.12"
extra755(){
for regx in $REGIONS; do

View File

@@ -16,6 +16,7 @@ CHECK_SCORED_extra761="NOT_SCORED"
CHECK_TYPE_extra761="EXTRA"
CHECK_SEVERITY_extra761="Medium"
CHECK_ALTERNATE_check761="extra761"
CHECK_ASFF_COMPLIANCE_TYPE_extra761="ens-mp.info.3.aws.ebs.2"
extra761(){
textInfo "Looking for EBS Default Encryption activation in all regions... "

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra764="EXTRA"
CHECK_SEVERITY_extra764="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra764="AwsS3Bucket"
CHECK_ALTERNATE_check764="extra764"
CHECK_ASFF_COMPLIANCE_TYPE_extra764="ens-mp.com.2.aws.s3.1"
extra764(){
LIST_OF_BUCKETS=$($AWSCLI s3api list-buckets $PROFILE_OPT --query Buckets[*].Name --output text --region $REGION|xargs -n1)

View File

@@ -28,6 +28,10 @@ extra77(){
textFail "Access Denied Trying to describe ECR repositories"
continue
fi
if [[ $(echo "$LIST_ECR_REPOS" | grep SubscriptionRequiredException) ]]; then
textFail "Subscription Required Exception trying to describe ECR repositories"
continue
fi
if [[ ! -z "$LIST_ECR_REPOS" ]]; then
for repo in $LIST_ECR_REPOS; do
TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-ecr-repo.policy.XXXXXXXXXX)

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra773="EXTRA"
CHECK_SEVERITY_extra773="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra773="AwsCloudFrontDistribution"
CHECK_ALTERNATE_check773="extra773"
CHECK_ASFF_COMPLIANCE_TYPE_extra773="ens-mp.s.2.aws.waf.1"
extra773(){
# "Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)"

View File

@@ -43,44 +43,46 @@ extra776(){
for repo in $LIST_ECR_REPOS; do
SCAN_ENABLED=$($AWSCLI ecr describe-repositories $PROFILE_OPT --region $region --query "repositories[?repositoryName==\`$repo\`].[imageScanningConfiguration.scanOnPush]" --output text 2>&1)
if [[ "$SCAN_ENABLED" == "True" ]]; then
IMAGE_DIGEST=$($AWSCLI ecr describe-images $PROFILE_OPT --region $region --repository-name "$repo" --query "sort_by(imageDetails,& imagePushedAt)[-1].imageDigest" --output text 2>&1)
IMAGE_TAG=$($AWSCLI ecr describe-images $PROFILE_OPT --region $region --repository-name "$repo" --query "sort_by(imageDetails,& imagePushedAt)[-1].imageTags[0]" --output text 2>&1)
if [[ ! -z "$LIST_ECR_REPOS" ]]; then
IMAGE_SCAN_STATUS=$($AWSCLI ecr describe-image-scan-findings $PROFILE_OPT --region $region --repository-name "$repo" --image-id imageDigest="$IMAGE_DIGEST" --query "imageScanStatus.status" 2>&1)
if [[ $IMAGE_SCAN_STATUS == *"ScanNotFoundException"* ]]; then
textFail "$region: ECR repository $repo has imageTag $IMAGE_TAG without a scan" "$region"
else
if [[ $IMAGE_SCAN_STATUS == *"FAILED"* ]]; then
textFail "$region: ECR repository $repo has imageTag $IMAGE_TAG with scan status $IMAGE_SCAN_STATUS" "$region"
IMAGE_DIGEST=$($AWSCLI ecr describe-images $PROFILE_OPT --region $region --repository-name "$repo" --query "sort_by(imageDetails,& imagePushedAt)[-1].imageDigest" --output text | head -n 1 2>&1)
if [[ $IMAGE_DIGEST != *"None"* ]]; then
IMAGE_TAG=$($AWSCLI ecr describe-images $PROFILE_OPT --region $region --repository-name "$repo" --query "sort_by(imageDetails,& imagePushedAt)[-1].imageTags[0]" --output text 2>&1)
if [[ ! -z "$LIST_ECR_REPOS" ]]; then
IMAGE_SCAN_STATUS=$($AWSCLI ecr describe-image-scan-findings $PROFILE_OPT --region $region --repository-name "$repo" --image-id imageDigest="$IMAGE_DIGEST" --query "imageScanStatus.status" 2>&1)
if [[ $IMAGE_SCAN_STATUS == *"ScanNotFoundException"* ]]; then
textFail "$region: ECR repository $repo has imageTag $IMAGE_TAG without a scan" "$region"
else
FINDINGS_COUNT=$($AWSCLI ecr describe-image-scan-findings $PROFILE_OPT --region $region --repository-name "$repo" --image-id imageDigest="$IMAGE_DIGEST" --query "imageScanFindings.findingSeverityCounts" 2>&1)
if [[ ! -z "$FINDINGS_COUNT" ]]; then
SEVERITY_CRITICAL=$(echo "$FINDINGS_COUNT" | jq -r '.CRITICAL' )
if [[ "$SEVERITY_CRITICAL" != "null" ]]; then
textFail "$region: ECR repository $repo has imageTag $IMAGE_TAG with CRITICAL ($SEVERITY_CRITICAL) findings" "$region"
fi
SEVERITY_HIGH=$(echo "$FINDINGS_COUNT" | jq -r '.HIGH' )
if [[ "$SEVERITY_HIGH" != "null" ]]; then
textFail "$region: ECR repository $repo has imageTag $IMAGE_TAG with HIGH ($SEVERITY_HIGH) findings" "$region"
fi
SEVERITY_MEDIUM=$(echo "$FINDINGS_COUNT" | jq -r '.MEDIUM' )
if [[ "$SEVERITY_MEDIUM" != "null" ]]; then
textFail "$region: ECR repository $repo has imageTag $IMAGE_TAG with MEDIUM ($SEVERITY_MEDIUM) findings" "$region"
fi
SEVERITY_LOW=$(echo "$FINDINGS_COUNT" | jq -r '.LOW' )
if [[ "$SEVERITY_LOW" != "null" ]]; then
textInfo "$region: ECR repository $repo has imageTag $IMAGE_TAG with LOW ($SEVERITY_LOW) findings" "$region"
fi
SEVERITY_INFORMATIONAL=$(echo "$FINDINGS_COUNT" | jq -r '.INFORMATIONAL' )
if [[ "$SEVERITY_INFORMATIONAL" != "null" ]]; then
textInfo "$region: ECR repository $repo has imageTag $IMAGE_TAG with INFORMATIONAL ($SEVERITY_INFORMATIONAL) findings" "$region"
fi
SEVERITY_UNDEFINED=$(echo "$FINDINGS_COUNT" | jq -r '.UNDEFINED' )
if [[ "$SEVERITY_UNDEFINED" != "null" ]]; then
textInfo "$region: ECR repository $repo has imageTag $IMAGE_TAG with UNDEFINED ($SEVERITY_UNDEFINED) findings" "$region"
fi
if [[ $IMAGE_SCAN_STATUS == *"FAILED"* ]]; then
textFail "$region: ECR repository $repo has imageTag $IMAGE_TAG with scan status $IMAGE_SCAN_STATUS" "$region"
else
textPass "$region: ECR repository $repo has imageTag $IMAGE_TAG without findings" "$region"
FINDINGS_COUNT=$($AWSCLI ecr describe-image-scan-findings $PROFILE_OPT --region $region --repository-name "$repo" --image-id imageDigest="$IMAGE_DIGEST" --query "imageScanFindings.findingSeverityCounts" 2>&1)
if [[ ! -z "$FINDINGS_COUNT" ]]; then
SEVERITY_CRITICAL=$(echo "$FINDINGS_COUNT" | jq -r '.CRITICAL' )
if [[ "$SEVERITY_CRITICAL" != "null" ]]; then
textFail "$region: ECR repository $repo has imageTag $IMAGE_TAG with CRITICAL ($SEVERITY_CRITICAL) findings" "$region"
fi
SEVERITY_HIGH=$(echo "$FINDINGS_COUNT" | jq -r '.HIGH' )
if [[ "$SEVERITY_HIGH" != "null" ]]; then
textFail "$region: ECR repository $repo has imageTag $IMAGE_TAG with HIGH ($SEVERITY_HIGH) findings" "$region"
fi
SEVERITY_MEDIUM=$(echo "$FINDINGS_COUNT" | jq -r '.MEDIUM' )
if [[ "$SEVERITY_MEDIUM" != "null" ]]; then
textFail "$region: ECR repository $repo has imageTag $IMAGE_TAG with MEDIUM ($SEVERITY_MEDIUM) findings" "$region"
fi
SEVERITY_LOW=$(echo "$FINDINGS_COUNT" | jq -r '.LOW' )
if [[ "$SEVERITY_LOW" != "null" ]]; then
textInfo "$region: ECR repository $repo has imageTag $IMAGE_TAG with LOW ($SEVERITY_LOW) findings" "$region"
fi
SEVERITY_INFORMATIONAL=$(echo "$FINDINGS_COUNT" | jq -r '.INFORMATIONAL' )
if [[ "$SEVERITY_INFORMATIONAL" != "null" ]]; then
textInfo "$region: ECR repository $repo has imageTag $IMAGE_TAG with INFORMATIONAL ($SEVERITY_INFORMATIONAL) findings" "$region"
fi
SEVERITY_UNDEFINED=$(echo "$FINDINGS_COUNT" | jq -r '.UNDEFINED' )
if [[ "$SEVERITY_UNDEFINED" != "null" ]]; then
textInfo "$region: ECR repository $repo has imageTag $IMAGE_TAG with UNDEFINED ($SEVERITY_UNDEFINED) findings" "$region"
fi
else
textPass "$region: ECR repository $repo has imageTag $IMAGE_TAG without findings" "$region"
fi
fi
fi
fi

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra781="EXTRA"
CHECK_SEVERITY_extra781="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra781="AwsElasticsearchDomain"
CHECK_ALTERNATE_check781="extra781"
CHECK_ASFF_COMPLIANCE_TYPE_extra781="ens-mp.info.3.aws.au.1"
extra781(){
for regx in $REGIONS; do

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra792="EXTRA"
CHECK_SEVERITY_extra792="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra792="AwsElbLoadBalancer"
CHECK_ALTERNATE_check792="extra792"
CHECK_ASFF_COMPLIANCE_TYPE_extra792="ens-mp.com.2.aws.elb.2"
extra792(){
# "Check if Elastic Load Balancers have insecure SSL ciphers (Not Scored) (Not part of CIS benchmark)"

View File

@@ -17,6 +17,7 @@ CHECK_TYPE_extra793="EXTRA"
CHECK_SEVERITY_extra793="Medium"
CHECK_ASFF_RESOURCE_TYPE_extra793="AwsElbLoadBalancer"
CHECK_ALTERNATE_check793="extra793"
CHECK_ASFF_COMPLIANCE_TYPE_extra793="ens-mp.com.2.aws.elb.1"
extra793(){
# "Check if Elastic Load Balancers have encrypted listeners (Not Scored) (Not part of CIS benchmark)"

View File

@@ -15,69 +15,69 @@ GROUP_ID[23]='ens'
GROUP_NUMBER[23]='23.0'
GROUP_TITLE[23]='ENS Esquema Nacional de Seguridad security checks - [ens] *****'
GROUP_RUN_BY_DEFAULT[23]='N' # run it when execute_all is called
GROUP_CHECKS[23]='extra733,check13,check14,check121,extra7100,check120,check116,check12,check14,check13,check21,check25,check35,check24,check31,check36,check32,check33,check34,check22,extra71,check23,check23,check27,check37,extra736,extra737,extra713,check21,check29,extra793,extra792,extra764,extra738,check43,extra74,extra710,extra75,check41,check42,extra749,extra750,extra751,extra752,extra753,extra754,extra755,extra729,extra761,extra740,extra735,extra734,extra728,extra781,extra773,extra744'
GROUP_CHECKS[23]='extra733,extra7123,check13,check14,check121,extra7100,check120,check116,extra7124,check12,extra7125,check14,check13,check21,check25,extra7127,check35,check24,check31,check36,check32,check33,check34,check22,extra71,check23,check23,check27,check37,extra736,extra737,extra713,check21,check29,extra793,extra792,extra764,extra738,check43,extra74,extra710,extra75,check41,check42,extra749,extra750,extra751,extra752,extra753,extra754,extra755,extra7128,extra729,extra761,extra740,extra735,extra734,extra728,extra781,extra773,extra744,extra7126,extra7129'
# ENS Control ID for AWS;Prowler checks that apply
# op.acc.1.aws.iam.1;extra733
# op.acc.1.aws.iam.2;todo
# op.acc.1.aws.iam.3;check13
# op.acc.1.aws.iam.4;check14
# op.acc.1.aws.iam.5;check121
# op.acc.2.aws.iam.1;extra7100
# op.acc.1.aws.iam.4;check120
# op.acc.3.aws.iam.1;check116
# op.acc.4.aws.sys.1;todo ssm session manager
# op.acc.5.aws.iam.1;check12
# op.acc.5.aws.iam.2;todo
# op.acc.5.aws.iam.3;check14
# op.acc.5.aws.iam.4;check13
# op.acc.7.aws.iam.1;check21
# op.exp.1.aws.cfg.1;check25
# op.exp.1.aws.sys.1;todo ssm inventory
# op.exp.4.aws.sys.1;todo ssm compliance
# op.exp.8.aws.trail.1;check35
# op.exp.8.aws.cw.1;check24
# op.exp.8.aws.trail.2;check31
# op.exp.8.aws.trail.3;check36
# op.exp.8.aws.trail.4;check32
# op.exp.8.aws.trail.5;check33
# op.exp.8.aws.trail.6;check34
# op.exp.10.aws.trail.1;check22
# op.exp.10.aws.trail.2;extra71
# op.exp.10.aws.trail.3;check23
# op.exp.10.aws.trail.4;check23
# op.exp.10.aws.trail.5;check27
# op.exp.11.aws.kms.1;check37
# op.exp.11.aws.kms.2;extra736
# op.exp.11.aws.kms.3;extra737
# op.mon.1.aws.duty.1;extra713
# op.mon.1.aws.trail.1;check21
# op.mon.1.aws.flow.1;check29
# mp.com.2.aws.elb.1;extra793
# mp.com.2.aws.elb.2;extra792
# mp.com.2.aws.s3.1;extra764
# mp.com.2.aws.front.1;extra738
# mp.com.4.aws.sg.1;check43
# mp.com.4.aws.sg.2;extra74
# mp.com.4.aws.vpc.1;extra710
# mp.com.4.aws.sg.3;extra75
# mp.com.4.aws.sg.4;check41
# mp.com.4.aws.sg.5;check42
# mp.com.4.aws.sg.6;extra749
# mp.com.4.aws.sg.7;extra750
# mp.com.4.aws.sg.8;extra751
# mp.com.4.aws.sg.9;extra752
# mp.com.4.aws.sg.10;extra753
# mp.com.4.aws.sg.11;extra754
# mp.com.4.aws.sg.12;extra755
# mp.info.3.aws.dyndb.1;todo
# mp.info.3.aws.ebs.1 ;extra729
# mp.info.3.aws.ebs.2;extra761
# mp.info.3.aws.ebs.3;extra740
# mp.info.3.aws.rds.1;extra735
# mp.info.3.s3.1;extra734
# mp.info.3.sns.1;extra728
# mp.info.3.aws.au.1;extra781
# mp.s.2.aws.waf.1;extra773
# mp.s.2.aws.waf.2;extra744
# mp.s.2.aws.waf.3;todo
# ens-op.acc.1.aws.iam.1;extra733
# ens-op.acc.1.aws.iam.2;extra7123
# ens-op.acc.1.aws.iam.3;check13
# ens-op.acc.1.aws.iam.4;check14
# ens-op.acc.1.aws.iam.5;check121
# ens-op.acc.2.aws.iam.1;extra7100
# ens-op.acc.1.aws.iam.4;check120
# ens-op.acc.3.aws.iam.1;check116
# ens-op.acc.4.aws.sys.1;extra7124
# ens-op.acc.5.aws.iam.1;check12
# ens-op.acc.5.aws.iam.2;extra7125
# ens-op.acc.5.aws.iam.3;check14
# ens-op.acc.5.aws.iam.4;check13
# ens-op.acc.7.aws.iam.1;check21
# ens-op.exp.1.aws.cfg.1;check25
# ens-op.exp.1.aws.sys.1;extra7127
# ens-op.exp.4.aws.sys.1;extra7127
# ens-op.exp.8.aws.trail.1;check35
# ens-op.exp.8.aws.cw.1;check24
# ens-op.exp.8.aws.trail.2;check31
# ens-op.exp.8.aws.trail.3;check36
# ens-op.exp.8.aws.trail.4;check32
# ens-op.exp.8.aws.trail.5;check33
# ens-op.exp.8.aws.trail.6;check34
# ens-op.exp.10.aws.trail.1;check22
# ens-op.exp.10.aws.trail.2;extra71
# ens-op.exp.10.aws.trail.3;check23
# ens-op.exp.10.aws.trail.4;check23
# ens-op.exp.10.aws.trail.5;check27
# ens-op.exp.11.aws.kms.1;check37
# ens-op.exp.11.aws.kms.2;extra736*
# ens-op.exp.11.aws.kms.3;extra737
# ens-op.mon.1.aws.duty.1;extra713
# ens-op.mon.1.aws.trail.1;check21
# ens-op.mon.1.aws.flow.1;check29
# ens-mp.com.2.aws.elb.1;extra793
# ens-mp.com.2.aws.elb.2;extra792
# ens-mp.com.2.aws.s3.1;extra764
# ens-mp.com.2.aws.front.1;extra738
# ens-mp.com.4.aws.sg.1;check43
# ens-mp.com.4.aws.sg.2;extra74
# ens-mp.com.4.aws.vpc.1;extra710
# ens-mp.com.4.aws.sg.3;extra75
# ens-mp.com.4.aws.sg.4;check41
# ens-mp.com.4.aws.sg.5;check42
# ens-mp.com.4.aws.sg.6;extra749
# ens-mp.com.4.aws.sg.7;extra750
# ens-mp.com.4.aws.sg.8;extra751
# ens-mp.com.4.aws.sg.9;extra752
# ens-mp.com.4.aws.sg.10;extra753
# ens-mp.com.4.aws.sg.11;extra754
# ens-mp.com.4.aws.sg.12;extra755
# ens-mp.info.3.aws.dyndb.1;extra7128
# ens-mp.info.3.aws.ebs.1;extra729
# ens-mp.info.3.aws.ebs.2;extra761
# ens-mp.info.3.aws.ebs.3;extra740
# ens-mp.info.3.aws.rds.1;extra735
# ens-mp.info.3.s3.1;extra734
# ens-mp.info.3.sns.1;extra728
# ens-mp.info.3.aws.au.1;extra781
# ens-mp.s.2.aws.waf.1;extra773
# ens-mp.s.2.aws.waf.2;extra744
# ens-mp.s.2.aws.waf.3;extra7129

View File

@@ -15,7 +15,7 @@ GROUP_ID[7]='extras'
GROUP_NUMBER[7]='7.0'
GROUP_TITLE[7]='Extras - all non CIS specific checks - [extras] ****************'
GROUP_RUN_BY_DEFAULT[7]='Y' # run it when execute_all is called
GROUP_CHECKS[7]='extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723,extra724,extra725,extra726,extra727,extra728,extra729,extra730,extra731,extra732,extra733,extra734,extra735,extra736,extra737,extra738,extra739,extra740,extra741,extra742,extra743,extra744,extra745,extra746,extra747,extra748,extra749,extra750,extra751,extra752,extra753,extra754,extra755,extra756,extra757,extra758,extra761,extra762,extra763,extra764,extra765,extra767,extra768,extra769,extra770,extra771,extra772,extra773,extra774,extra775,extra776,extra777,extra778,extra779,extra780,extra781,extra782,extra783,extra784,extra785,extra786,extra787,extra788,extra791,extra792,extra793,extra794,extra795,extra796,extra797,extra798,extra799,extra7100,extra7101,extra7102,extra7103,extra7104,extra7105,extra7106,extra7107,extra7108,extra7109,extra7110,extra7111,extra7112,extra7113,extra7114,extra7115,extra7116,extra7117,extra7118,extra7119,extra7120,extra7121,extra7122'
GROUP_CHECKS[7]='extra71,extra72,extra73,extra74,extra75,extra76,extra77,extra78,extra79,extra710,extra711,extra712,extra713,extra714,extra715,extra716,extra717,extra718,extra719,extra720,extra721,extra722,extra723,extra724,extra725,extra726,extra727,extra728,extra729,extra730,extra731,extra732,extra733,extra734,extra735,extra736,extra737,extra738,extra739,extra740,extra741,extra742,extra743,extra744,extra745,extra746,extra747,extra748,extra749,extra750,extra751,extra752,extra753,extra754,extra755,extra756,extra757,extra758,extra761,extra762,extra763,extra764,extra765,extra767,extra768,extra769,extra770,extra771,extra772,extra773,extra774,extra775,extra776,extra777,extra778,extra779,extra780,extra781,extra782,extra783,extra784,extra785,extra786,extra787,extra788,extra791,extra792,extra793,extra794,extra795,extra796,extra797,extra798,extra799,extra7100,extra7101,extra7102,extra7103,extra7104,extra7105,extra7106,extra7107,extra7108,extra7109,extra7110,extra7111,extra7112,extra7113,extra7114,extra7115,extra7116,extra7117,extra7118,extra7119,extra7120,extra7121,extra7122,extra7123,extra7124,extra7125,extra7126,extra7127,extra7128,extra7129'
# Extras 759 and 760 (lambda variables and code secrets finder are not included)
# to run detect-secrets use `./prowler -g secrets`

View File

@@ -31,13 +31,13 @@ assume_role(){
# assume role command
$AWSCLI $PROFILE_OPT sts assume-role --role-arn arn:${AWS_PARTITION}:iam::$ACCOUNT_TO_ASSUME:role/$ROLE_TO_ASSUME \
--role-session-name ProwlerAssessmentSession \
--region $REGION \
--region $REGION_FOR_STS \
--duration-seconds $SESSION_DURATION_TO_ASSUME > $TEMP_STS_ASSUMED_FILE
else
$AWSCLI $PROFILE_OPT sts assume-role --role-arn arn:${AWS_PARTITION}:iam::$ACCOUNT_TO_ASSUME:role/$ROLE_TO_ASSUME \
--role-session-name ProwlerAssessmentSession \
--duration-seconds $SESSION_DURATION_TO_ASSUME \
--region $REGION \
--region $REGION_FOR_STS \
--external-id $ROLE_EXTERNAL_ID > $TEMP_STS_ASSUMED_FILE
fi
@@ -64,6 +64,7 @@ assume_role(){
export AWS_ACCESS_KEY_ID=$(cat $TEMP_STS_ASSUMED_FILE | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(cat $TEMP_STS_ASSUMED_FILE | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(cat $TEMP_STS_ASSUMED_FILE | jq -r '.Credentials.SessionToken')
export AWS_SESSION_EXPIRATION=$(convert_date_to_timestamp "$(cat $TEMP_STS_ASSUMED_FILE | jq -r '.Credentials.Expiration')")
rm -fr $TEMP_STS_ASSUMED_FILE
}

View File

@@ -39,6 +39,8 @@ elif [[ $INSTANCE_PROFILE ]]; then
AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g')
AWS_SECRET_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g')
AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} grep Token| cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g')
elif [[ $AWS_EXECUTION_ENV == "CloudShell" ]]; then
PROFILE_OPT=""
else
PROFILE="default"
PROFILE_OPT="--profile $PROFILE"

View File

@@ -15,5 +15,5 @@
printCsvHeader() {
>&2 echo ""
>&2 echo "Generating \"${SEP}\" delimited report on stdout for profile $PROFILE, account $ACCOUNT_NUM"
echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}LEVEL${SEP}TITLE_TEXT${SEP}NOTES" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}LEVEL${SEP}TITLE_TEXT${SEP}NOTES${SEP}COMPLIANCE" | tee -a $OUTPUT_FILE_NAME.$EXTENSION_CSV
}

View File

@@ -100,6 +100,7 @@ addHtmlHeader() {
<th scope="col">Result</th>
<th scope="col">AccountID</th>
<th scope="col">Region</th>
<th scope="col">Compliance</th>
<th scope="col">Group</th>
<th scope="col">CheckID</th>
<th style="width:40%" scope="col">Check Title</th>

View File

@@ -108,6 +108,16 @@ bsd_get_iso8601_timestamp() {
"$DATE_CMD" -u +"%Y-%m-%dT%H:%M:%SZ"
}
gnu_convert_date_to_timestamp() {
date -d "$1" +%s
}
bsd_convert_date_to_timestamp() {
echo $(( $(date -j -f %Y-%m-%dT%H:%M:%S "$1" +%s) + 3600 ))
# Change above is because epoch time generator in BSD is 1h less than in Linux ¯\_(ツ)_/¯
#date -j -f "%Y-%m-%dT%H:%M:%S" "$1" "+%s"
}
gnu_test_tcp_connectivity() {
HOST=$1
PORT=$2
@@ -154,6 +164,9 @@ if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == "linux-musl" ]; then
test_tcp_connectivity() {
gnu_test_tcp_connectivity "$1" "$2" "$3"
}
convert_date_to_timestamp() {
gnu_convert_date_to_timestamp "$1"
}
elif [[ "$OSTYPE" == "darwin"* ]] || [[ "$OSTYPE" == "freebsd"* ]]; then
# BSD/OSX commands compatibility
TEMP_REPORT_FILE=$(mktemp -t prowler.cred_report-XXXXXX)
@@ -189,6 +202,9 @@ elif [[ "$OSTYPE" == "darwin"* ]] || [[ "$OSTYPE" == "freebsd"* ]]; then
get_iso8601_timestamp() {
gnu_get_iso8601_timestamp
}
convert_date_to_timestamp() {
gnu_convert_date_to_timestamp "$1"
}
else
how_older_from_today() {
bsd_how_older_from_today "$1"
@@ -208,6 +224,9 @@ elif [[ "$OSTYPE" == "darwin"* ]] || [[ "$OSTYPE" == "freebsd"* ]]; then
get_iso8601_timestamp() {
bsd_get_iso8601_timestamp
}
convert_date_to_timestamp() {
bsd_convert_date_to_timestamp "$1"
}
fi
if "$BASE64_CMD" --version >/dev/null 2>&1 ; then
decode_report() {
@@ -248,6 +267,9 @@ elif [[ "$OSTYPE" == "cygwin" ]]; then
test_tcp_connectivity() {
gnu_test_tcp_connectivity "$1" "$2" "$3"
}
convert_date_to_timestamp() {
gnu_convert_date_to_timestamp "$1"
}
else
echo "Unknown Operating System! Valid \$OSTYPE: linux-gnu, linux-musl, darwin* or cygwin"
echo "Found: $OSTYPE"

View File

@@ -51,7 +51,7 @@ textPass(){
REPREGION=$REGION
fi
if [[ "${MODES[@]}" =~ "csv" ]]; then
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" | tee -a ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1${SEP}$ASFF_COMPLIANCE_TYPE" | tee -a ${OUTPUT_FILE_NAME}.$EXTENSION_CSV
fi
if [[ "${MODES[@]}" =~ "json" ]]; then
generateJsonOutput "$1" "Pass" | tee -a ${OUTPUT_FILE_NAME}.$EXTENSION_JSON
@@ -88,7 +88,7 @@ textInfo(){
REPREGION=$REGION
fi
if [[ "${MODES[@]}" =~ "csv" ]]; then
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" | tee -a ${OUTPUT_FILE_NAME}.${EXTENSION_CSV}
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1${SEP}$ASFF_COMPLIANCE_TYPE" | tee -a ${OUTPUT_FILE_NAME}.${EXTENSION_CSV}
fi
if [[ "${MODES[@]}" =~ "json" ]]; then
generateJsonOutput "$1" "Info" | tee -a ${OUTPUT_FILE_NAME}.${EXTENSION_JSON}
@@ -140,7 +140,7 @@ textFail(){
fi
if [[ "${MODES[@]}" =~ "csv" ]]; then
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}${level}${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" | tee -a ${OUTPUT_FILE_NAME}.${EXTENSION_CSV}
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}${level}${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1${SEP}$ASFF_COMPLIANCE_TYPE" | tee -a ${OUTPUT_FILE_NAME}.${EXTENSION_CSV}
fi
if [[ "${MODES[@]}" =~ "json" ]]; then
generateJsonOutput "$1" "${level}" | tee -a ${OUTPUT_FILE_NAME}.${EXTENSION_JSON}
@@ -211,9 +211,9 @@ textTitle(){
:
else
if [[ "$ITEM_SCORED" == "Scored" ]]; then
echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT $group_ids"
echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT $6 $group_ids "
else
echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL $group_ids"
echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $6 $NORMAL $group_ids "
fi
fi
}
@@ -232,6 +232,7 @@ generateJsonOutput(){
--arg ITEM_LEVEL "$ITEM_LEVEL" \
--arg TITLE_ID "$TITLE_ID" \
--arg REPREGION "$REPREGION" \
--arg TYPE "$ASFF_COMPLIANCE_TYPE" \
--arg TIMESTAMP "$(get_iso8601_timestamp)" \
-n '{
"Profile": $PROFILE,
@@ -245,6 +246,7 @@ generateJsonOutput(){
"Control ID": $TITLE_ID,
"Region": $REPREGION,
"Timestamp": $TIMESTAMP,
"Compliance": $TYPE
}'
}
@@ -266,7 +268,8 @@ generateJsonAsffOutput(){
--arg SEVERITY "$(echo $CHECK_SEVERITY| awk '{ print toupper($0) }')" \
--arg TITLE_ID "$TITLE_ID" \
--arg CHECK_ID "$CHECK_ID" \
--arg TYPE "$ASFF_TYPE" \
--arg TYPE "$ASFF_COMPLIANCE_TYPE" \
--arg COMPLIANCE_RELATED_REQUIREMENTS "$ASFF_COMPLIANCE_TYPE" \
--arg RESOURCE_TYPE "$ASFF_RESOURCE_TYPE" \
--arg REPREGION "$REPREGION" \
--arg TIMESTAMP "$(get_iso8601_timestamp)" \
@@ -303,7 +306,8 @@ generateJsonAsffOutput(){
}
],
"Compliance": {
"Status": $STATUS
"Status": $STATUS,
"RelatedRequirements": [ $COMPLIANCE_RELATED_REQUIREMENTS ]
}
}'
}
@@ -317,6 +321,7 @@ generateHtmlOutput(){
echo '<td>INFO</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ACCOUNT_NUM'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$REPREGION'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ASFF_COMPLIANCE_TYPE'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ITEM_LEVEL'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$TITLE_ID'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$TITLE_TEXT'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
@@ -329,6 +334,7 @@ generateHtmlOutput(){
echo '<td>PASS</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ACCOUNT_NUM'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$REPREGION'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ASFF_COMPLIANCE_TYPE'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ITEM_LEVEL'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$TITLE_ID'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$TITLE_TEXT'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
@@ -341,6 +347,7 @@ generateHtmlOutput(){
echo '<td>FAIL</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ACCOUNT_NUM'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$REPREGION'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ASFF_COMPLIANCE_TYPE'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ITEM_LEVEL'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$TITLE_ID'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$TITLE_TEXT'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
@@ -353,6 +360,7 @@ generateHtmlOutput(){
echo '<td>WARN</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ACCOUNT_NUM'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$REPREGION'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ASFF_COMPLIANCE_TYPE'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$ITEM_LEVEL'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$TITLE_ID'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML
echo '<td>'$TITLE_TEXT'</td>' >> ${OUTPUT_FILE_NAME}.$EXTENSION_HTML

View File

@@ -13,25 +13,47 @@
# Get whoami in AWS, who is the user running this shell script
GETCALLER=$($AWSCLI sts get-caller-identity $PROFILE_OPT --region $REGION)
ACCOUNT_NUM=$(echo $GETCALLER | jq -r '.Account')
# Get a list of all available AWS Regions
# sice describe-regions doesn't seem to work at me-south-1|eu-south-1|ap-east-1|af-south-1.
# Probably dased on https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html
# when invoking regions with -r, those regions with STS disabled make GETCALLER fail then
# this if will filter them out (Africa (Cape Town), Asia Pacific (Hong Kong), Europe (Milan) and Middle East (Bahrain) ):
case "$REGION" in
me-south-1|eu-south-1|ap-east-1|af-south-1)
REGION_FOR_STS="us-east-1"
;;
*)
REGION_FOR_STS=$REGION
;;
esac
GETCALLER=$($AWSCLI sts get-caller-identity $PROFILE_OPT --region $REGION_FOR_STS)
RESULT_CALL=$?
if [[ $RESULT_CALL == 254 ]]; then
if [[ $PRINTCHECKSONLY || $PRINTGROUPSONLY ]]; then
echo Listing...
else
# Failed to get own identity ... exit
echo -e "$RED ERROR Getting credentials to run Prowler - EXITING! $NORMAL"
EXITCODE=2
exit $EXITCODE
fi
fi
if [[ $ACCOUNT_TO_ASSUME ]]; then
ACCOUNT_NUM=$ACCOUNT_TO_ASSUME
else
ACCOUNT_NUM=$(echo $GETCALLER | jq -r '.Account')
fi
CALLER_ARN=$(echo $GETCALLER | jq -r '.Arn')
USER_ID=$(echo $GETCALLER | jq -r '.UserId')
AWS_PARTITION=$(echo $CALLER_ARN| cut -d: -f2)
getWhoami(){
if [[ 255 -eq $? ]]; then
# Failed to get own identity ... exit
echo -e "$RED ERROR Getting credentials to run Prowler - EXITING! $NORMAL"
EXITCODE=2
exit $EXITCODE
fi
if [[ $ACCOUNT_TO_ASSUME ]]; then
ACCOUNT_NUM=$ACCOUNT_TO_ASSUME
fi
if [[ "$MODE" == "csv" ]]; then
if [[ 255 -eq $? ]]; then
# Failed to get own identity ... exit

43
prowler
View File

@@ -32,7 +32,7 @@ OPTRED=""
OPTNORMAL=""
# Set the defaults variables
PROWLER_VERSION=2.3.0RC5
PROWLER_VERSION=2.3.0RC7
PROWLER_DIR=$(dirname "$0")
REGION=""
@@ -90,13 +90,14 @@ USAGE:
-I External ID to be used when assuming roles (not mandatory), requires -A and -R
-w whitelist file. See whitelist_sample.txt for reference and format
(i.e.: whitelist_sample.txt)
-N <shodan_api_key> Shoadan API key used by check extra7102.
-V show version number & exit
-h this help
"
exit
}
while getopts ":hlLkqp:r:c:g:f:m:M:E:x:enbVsSI:A:R:T:w:" OPTION; do
while getopts ":hlLkqp:r:c:g:f:m:M:E:x:enbVsSI:A:R:T:w:N:" OPTION; do
case $OPTION in
h )
usage
@@ -177,6 +178,9 @@ while getopts ":hlLkqp:r:c:g:f:m:M:E:x:enbVsSI:A:R:T:w:" OPTION; do
w )
WHITELIST_FILE=$OPTARG
;;
N )
SHODAN_API_KEY=$OPTARG
;;
: )
echo ""
echo "$OPTRED ERROR!$OPTNORMAL -$OPTARG requires an argument"
@@ -232,12 +236,8 @@ trap handle_ctrl_c INT
. $PROWLER_DIR/include/securityhub_integration
. $PROWLER_DIR/include/junit_integration
# Get a list of all available AWS Regions
REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \
--output text \
$PROFILE_OPT \
--region $REGION \
--region-names $FILTERREGION)
# Get list of regions based on include/whoami
REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' --output text $PROFILE_OPT --region $REGION_FOR_STS --region-names $FILTERREGION)
# Pre-process whitelist file if supplied
if [[ -n "$WHITELIST_FILE" ]]; then
@@ -283,6 +283,7 @@ show_check_title() {
local check_title=CHECK_TITLE_$1
local check_scored=CHECK_SCORED_$1
local check_type=CHECK_TYPE_$1
local check_asff_compliance_type=CHECK_ASFF_COMPLIANCE_TYPE_$1
local group_ids
local group_index
# If requested ($2 is any non-null value) iterate all GROUP_CHECKS and produce a comma-separated list of all
@@ -297,7 +298,12 @@ show_check_title() {
fi
done
fi
textTitle "${!check_id}" "${!check_title}" "${!check_scored}" "${!check_type}" "$group_ids"
# This shows ASFF_COMPLIANCE_TYPE if group used is ens, this si used to show ENS compliance ID control, can be used for other compliance groups as well.
if [[ ${GROUP_ID_READ} == "ens" ]];then
textTitle "${!check_id}" "${!check_title}" "${!check_scored}" "${!check_type}" "$group_ids" "(${!check_asff_compliance_type})"
else
textTitle "${!check_id}" "${!check_title}" "${!check_scored}" "${!check_type}" "$group_ids"
fi
}
# Function to show the title of a group, by numeric id
@@ -310,6 +316,18 @@ show_group_title() {
# Function to execute the check
execute_check() {
if [[ $ACCOUNT_TO_ASSUME ]]; then
MINIMUM_REMAINING_TIME_ALLOWED=$(($SESSION_DURATION_TO_ASSUME / 10 ))
CURRENT_TIMESTAMP=$(date -u "+%s")
SESSION_CUTOFF=$(($CURRENT_TIMESTAMP + $MINIMUM_REMAINING_TIME_ALLOWED))
if [[ $AWS_SESSION_EXPIRATION < $SESSION_CUTOFF ]]; then
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
assume_role
fi
fi
# See if this is an alternate name for a check
# for example, we might have been passed 1.01 which is another name for 1.1
local alternate_name_var=CHECK_ALTERNATE_$1
@@ -317,6 +335,8 @@ execute_check() {
# See if this check defines an ASFF Type, if so, use this, falling back to a sane default
# For a list of Types, see: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format.html#securityhub-findings-format-type-taxonomy
local asff_type_var=CHECK_ASFF_TYPE_$1
local asff_compliance_type_var=CHECK_ASFF_COMPLIANCE_TYPE_$1
local severity_var=CHECK_SEVERITY_$1
@@ -325,6 +345,7 @@ execute_check() {
CHECK_ID="$1"
ASFF_TYPE="${!asff_type_var:-Software and Configuration Checks}"
ASFF_COMPLIANCE_TYPE="${!asff_compliance_type_var:-Software and Configuration Checks}"
# See if this check defines an ASFF Resource Type, if so, use this, falling back to a sane default
# For a list of Resource Types, see: https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format.html#asff-resources
local asff_resource_type_var=CHECK_ASFF_RESOURCE_TYPE_$1
@@ -339,7 +360,7 @@ execute_check() {
ignores="$(awk "/${1}/{print}" <(echo "${WHITELIST}"))"
if [ ${alternate_name} ];then
if [[ ${alternate_name} == check1* || ${alternate_name} == extra71 ]];then
if [[ ${alternate_name} == check1* || ${alternate_name} == extra71 || ${alternate_name} == extra774 || ${alternate_name} == extra7123 ]];then
if [ ! -s $TEMP_REPORT_FILE ];then
genCredReport
saveReport
@@ -363,7 +384,7 @@ execute_check() {
local check_id_var=CHECK_ID_$1
local check_id=${!check_id_var}
if [ ${check_id} ]; then
if [[ ${check_id} == 1* || ${check_id} == 7.1 || ${check_id} == 7.74 ]];then
if [[ ${check_id} == 1* || ${check_id} == 7.1 || ${check_id} == 7.74 || ${check_id} == 7.123 ]];then
if [ ! -s $TEMP_REPORT_FILE ];then
genCredReport
saveReport