Merge pull request #407 from zfLQ2qx2/prowler_misc_fixes

Misc prowler fixes


    Add GetEbsEncryptionByDefault wherever Prowler policies are mentioned
    Update Extra718 check to be aware of access denied responses
    Update Extra726 check to be more verbose for non-failure items
    Update Extra73 check to be aware of access denied responses
    Update Extra734 check to be aware of access denied responses and parse policies with jq for better accuracy
    Update Extra742 check for verbiage
    Update Extra756 check for verbiage and parameter order
    Update Extra761 check for failure scenarios (requires most recent awscli and addition to Prowler IAM policy)
    Added Extra763 check to verify that object versioning is enabled on S3 buckets
    Added Extra764 check to verify that S3 buckets enforce a secure transport policy
This commit is contained in:
Toni de la Fuente
2019-11-20 22:03:02 +00:00
committed by GitHub
14 changed files with 192 additions and 60 deletions

View File

@@ -314,6 +314,7 @@ Instead of using default policy SecurityAudit for the account you use for checks
"directconnect:describe*",
"dynamodb:listtables",
"ec2:describe*",
"ec2:GetEbsEncryptionByDefault",
"ecr:describe*",
"ecs:describe*",
"ecs:list*",
@@ -343,6 +344,11 @@ Instead of using default policy SecurityAudit for the account you use for checks
"rds:downloaddblogfileportion",
"rds:listtagsforresource",
"redshift:describe*",
"route53domains:getdomaindetail",
"route53domains:getoperationdetail",
"route53domains:listdomains",
"route53domains:listoperations",
"route53domains:listtagsfordomain",
"route53:getchange",
"route53:getcheckeripranges",
"route53:getgeolocation",
@@ -361,12 +367,8 @@ Instead of using default policy SecurityAudit for the account you use for checks
"route53:listreusabledelegationsets",
"route53:listtagsforresource",
"route53:listtagsforresources",
"route53domains:getdomaindetail",
"route53domains:getoperationdetail",
"route53domains:listdomains",
"route53domains:listoperations",
"route53domains:listtagsfordomain",
"s3:getbucket*",
"s3:GetEncryptionConfiguration",
"s3:getlifecycleconfiguration",
"s3:getobjectacl",
"s3:getobjectversionacl",

View File

@@ -21,11 +21,15 @@ extra718(){
LIST_OF_BUCKETS=$($AWSCLI s3api list-buckets $PROFILE_OPT --query Buckets[*].Name --output text|xargs -n1)
if [[ $LIST_OF_BUCKETS ]]; then
for bucket in $LIST_OF_BUCKETS;do
BUCKET_SERVER_LOG_ENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket $PROFILE_OPT --query [LoggingEnabled] --output text|grep -v "^None$")
if [[ $BUCKET_SERVER_LOG_ENABLED ]];then
textPass "Bucket $bucket has server access logging enabled"
else
BUCKET_SERVER_LOG_ENABLED=$($AWSCLI s3api get-bucket-logging --bucket $bucket $PROFILE_OPT --query [LoggingEnabled] --output text 2>&1)
if [[ $(echo "$BUCKET_SERVER_LOG_ENABLED" | grep AccessDenied) ]]; then
textFail "Access Denied Trying to Get Bucket Logging for $bucket"
continue
fi
if [[ $(echo "$BUCKET_SERVER_LOG_ENABLED" | grep "^None$") ]]; then
textFail "Bucket $bucket has server access logging disabled!"
else
textPass "Bucket $bucket has server access logging enabled"
fi
done
else

View File

@@ -22,10 +22,14 @@ extra726(){
# forcing us-east-1 region only since support only works in that region
TA_CHECKS_ID=$($AWSCLI support describe-trusted-advisor-checks --language en $PROFILE_OPT --region us-east-1 --query checks[*].id --output text)
for checkid in $TA_CHECKS_ID; do
QUERY_RESULT_NO_OK=$($AWSCLI support describe-trusted-advisor-check-result --check-id $checkid --language en $PROFILE_OPT --region us-east-1 --query 'result.status' --output text | grep -v "ok" )
if [[ $QUERY_RESULT_NO_OK ]]; then
TA_CHECKS_NAME=$($AWSCLI support describe-trusted-advisor-checks --language en $PROFILE_OPT --region us-east-1 --query "checks[?id==\`$checkid\`].{name:name}[*]" --output text)
textFail "Trusted Advisor check $TA_CHECKS_NAME is in state $QUERY_RESULT_NO_OK"
TA_CHECKS_NAME=$($AWSCLI support describe-trusted-advisor-checks --language en $PROFILE_OPT --region us-east-1 --query "checks[?id==\`$checkid\`].{name:name}[*]" --output text)
QUERY_TA_CHECK_RESULT=$($AWSCLI support describe-trusted-advisor-check-result --check-id $checkid --language en $PROFILE_OPT --region us-east-1 --query 'result.status' --output text)
if [[ $(echo $QUERY_TA_CHECK_RESULT | grep ok) ]]; then
textPass "Trusted Advisor check $TA_CHECKS_NAME is in state $QUERY_TA_CHECK_RESULT"
elif [[ $(echo $QUERY_TA_CHECK_RESULT | grep warning) ]]; then
textInfo "Trusted Advisor check $TA_CHECKS_NAME is in state $QUERY_TA_CHECK_RESULT"
else
textFail "Trusted Advisor check $TA_CHECKS_NAME is in state $QUERY_TA_CHECK_RESULT"
fi
done
}

View File

@@ -24,7 +24,11 @@ CHECK_ALTERNATE_check703="extra73"
# extra73(){
# ALL_BUCKETS_LIST=$($AWSCLI s3api list-buckets --query 'Buckets[*].{Name:Name}' $PROFILE_OPT --region $REGION --output text)
# for bucket in $ALL_BUCKETS_LIST; do
# BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket $PROFILE_OPT --region $REGION --output text)
# BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket $PROFILE_OPT --region $REGION --output text 2>&1)
# if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then
# textFail "Access Denied Trying to Get Bucket Location for $bucket"
# continue
# fi
# if [[ "None" == $BUCKET_LOCATION ]]; then
# BUCKET_LOCATION="us-east-1"
# fi
@@ -54,7 +58,11 @@ extra73(){
S3_FINDING_POLICY="Ok"
# LOCATION
BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket $PROFILE_OPT --output text)
BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket $PROFILE_OPT --output text 2>&1)
if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then
textFail "Access Denied Trying to Get Bucket Location for $bucket"
continue
fi
if [[ "None" == $BUCKET_LOCATION ]]; then
BUCKET_LOCATION="us-east-1"
fi
@@ -133,7 +141,11 @@ extra73(){
# }
# extra73Thread(){
# bucket=$1
# BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket --profile $PROFILE --region $REGION --output text)
# BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location --bucket $bucket --profile $PROFILE --region $REGION --output text 2>&1)
# if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then
# textFail "Access Denied Trying to Get Bucket Location for $bucket"
# return
# fi
# if [[ "None" == $BUCKET_LOCATION ]]; then
# BUCKET_LOCATION="us-east-1"
# fi

View File

@@ -20,31 +20,45 @@ extra734(){
LIST_OF_BUCKETS=$($AWSCLI s3api list-buckets $PROFILE_OPT --query Buckets[*].Name --output text|xargs -n1)
if [[ $LIST_OF_BUCKETS ]]; then
for bucket in $LIST_OF_BUCKETS;do
# query to get if has encryption enabled or not
RESULT=$($AWSCLI s3api get-bucket-encryption $PROFILE_OPT --bucket $bucket --query ServerSideEncryptionConfiguration.Rules[].ApplyServerSideEncryptionByDefault[].SSEAlgorithm --output text 2>&1)
if [[ $(echo "$RESULT" | grep ServerSideEncryptionConfigurationNotFoundError) ]] ; then
textFail "Bucket $bucket does not enforce encryption!"
elif [[ $(echo "$RESULT" | grep AccessDenied) ]] ; then
if [[ $(echo "$RESULT" | grep AccessDenied) ]]; then
textFail "Access Denied Trying to Get Encryption for $bucket"
else
TEMP_SSE_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX)
# get bucket policy
$AWSCLI s3api get-bucket-policy $PROFILE_OPT --bucket $bucket --output text --query Policy > $TEMP_SSE_POLICY_FILE 2> /dev/null
# check if the S3 policy forces SSE s3:x-amz-server-side-encryption:true
CHECK_BUCKET_SSE_POLICY_PRESENT=$(cat $TEMP_SSE_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'| awk '/Condition/ && !skip { print } { skip = /x-amz-server-side-encryption/} '|grep \"true\")
CHECK_BUCKET_SSE_POLICY_VALUE=$(cat $TEMP_SSE_POLICY_FILE | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'| awk '/Condition/ && !skip { print } { skip = /x-amz-server-side-encryption/} '|grep -Eo "AES256|aws:kms")
echo "$RESULT" | while read RBUCKET SSEALG; do
if [[ $SSEALG ]]; then
textPass "Bucket $RBUCKET has default encryption enabled with algorithm $SSEALG"
fi
done
if [[ $CHECK_BUCKET_SSE_POLICY_PRESENT && $CHECK_BUCKET_SSE_POLICY_VALUE ]]; then
textPass "Bucket $bucket has S3 bucket policy to enforce encryption with $CHECK_BUCKET_SSE_POLICY_VALUE"
fi
rm -fr $TEMP_SSE_POLICY_FILE
continue
fi
if [[ $(echo "$RESULT" | grep ServerSideEncryptionConfigurationNotFoundError) ]]; then
textFail "Bucket $bucket does not enforce encryption!"
continue
fi
TEMP_SSE_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX)
# get bucket policy
$AWSCLI s3api get-bucket-policy $PROFILE_OPT --bucket $bucket --output text --query Policy > $TEMP_SSE_POLICY_FILE 2> /dev/null
if [[ $(grep AccessDenied $TEMP_SSE_POLICY_FILE) ]]; then
textFail "Access Denied Trying to Get Bucket Policy for $bucket"
rm -fr $TEMP_SSE_POLICY_FILE
continue
fi
if [[ $(grep NoSuchBucketPolicy $TEMP_SSE_POLICY_FILE) ]]; then
textFail "No bucket policy for $bucket"
rm -fr $TEMP_SSE_POLICY_FILE
continue
fi
# check if the S3 policy forces SSE s3:x-amz-server-side-encryption:true
CHECK_BUCKET_SSE_POLICY_PRESENT=$(cat $TEMP_SSE_POLICY_FILE | jq --arg arn "arn:aws:s3:::${bucket}/*" '.Statement[]|select(.Effect=="Deny" and (.Principal|type == "object") and .Principal.AWS == "*" and .Action=="s3:PutObject" and .Resource==$arn and .Condition.StringNotEquals."s3:x-amz-server-side-encryption" != null)')
if [[ $CHECK_BUCKET_SSE_POLICY_PRESENT == "" ]]; then
textFail "Bucket $bucket does not enforce encryption!"
rm -fr $TEMP_SSE_POLICY_FILE
continue
fi
CHECK_BUCKET_SSE_POLICY_VALUE=$(echo "$CHECK_BUCKET_SSE_POLICY_PRESENT" | jq -r '.Condition.StringNotEquals."s3:x-amz-server-side-encryption"')
textPass "Bucket $bucket has S3 bucket policy to enforce encryption with $CHECK_BUCKET_SSE_POLICY_VALUE"
rm -fr $TEMP_SSE_POLICY_FILE
done
else

View File

@@ -45,7 +45,7 @@ extra742(){
rm -f $CFN_OUTPUTS_FILE
fi
else
textInfo "$regx: CloudFormation stack $stack has not Outputs" "$regx"
textInfo "$regx: CloudFormation stack $stack has no Outputs" "$regx"
fi
done
else

View File

@@ -18,10 +18,10 @@ CHECK_ALTERNATE_check756="extra756"
extra756(){
for regx in $REGIONS; do
LIST_OF_RS_CLUSTERS=$($AWSCLI $PROFILE_OPT --region $regx redshift describe-clusters --query Clusters[*].ClusterIdentifier --output text)
LIST_OF_RS_CLUSTERS=$($AWSCLI $PROFILE_OPT redshift describe-clusters --region $regx --query Clusters[*].ClusterIdentifier --output text)
if [[ $LIST_OF_RS_CLUSTERS ]];then
for cluster in $LIST_OF_RS_CLUSTERS; do
IS_PUBLICLY_ACCESSIBLE=$($AWSCLI $PROFILE_OPT --region $regx redshift describe-clusters --cluster-identifier $cluster --query Clusters[*].PubliclyAccessible --output text|grep True)
IS_PUBLICLY_ACCESSIBLE=$($AWSCLI $PROFILE_OPT redshift describe-clusters --region $regx --cluster-identifier $cluster --query Clusters[*].PubliclyAccessible --output text|grep True)
if [[ $IS_PUBLICLY_ACCESSIBLE ]]; then
textFail "$regx: Redshift cluster $cluster is publicly accessible" "$regx"
else
@@ -29,7 +29,7 @@ extra756(){
fi
done
else
textInfo "$regx: Redshift clusters found" "$regx"
textInfo "$regx: No Redshift clusters found" "$regx"
fi
done
}

View File

@@ -19,7 +19,15 @@ CHECK_ALTERNATE_check761="extra761"
extra761(){
textInfo "Looking for EBS Default Encryption activation in all regions... "
for regx in $REGIONS; do
EBS_DEFAULT_ENCRYPTION=$($AWSCLI ec2 get-ebs-encryption-by-default $PROFILE_OPT --region $regx --query 'EbsEncryptionByDefault')
EBS_DEFAULT_ENCRYPTION=$($AWSCLI ec2 get-ebs-encryption-by-default $PROFILE_OPT --region $regx --query 'EbsEncryptionByDefault' 2>&1)
if [[ $(echo "$EBS_DEFAULT_ENCRYPTION" | grep "argument operation: Invalid choice") ]]; then
textFail "Newer aws cli needed for get-ebs-encryption-by-default"
continue
fi
if [[ $(echo "$EBS_DEFAULT_ENCRYPTION" | grep UnauthorizedOperation) ]]; then
textFail "Prowler needs ec2:GetEbsEncryptionByDefault permission for this check"
continue
fi
if [[ $EBS_DEFAULT_ENCRYPTION == "true" ]];then
textPass "$regx: EBS Default Encryption is activated" "$regx"
else

38
checks/check_extra763 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_extra763="7.63"
CHECK_TITLE_extra763="[extra763] Check if S3 buckets have object versioning enabled (Not Scored) (Not part of CIS benchmark)"
CHECK_SCORED_extra763="NOT_SCORED"
CHECK_TYPE_extra763="EXTRA"
CHECK_ALTERNATE_check763="extra763"
extra763(){
# "Check if S3 buckets have object versioning enabled (Not Scored) (Not part of CIS benchmark)"
LIST_OF_BUCKETS=$($AWSCLI s3api list-buckets $PROFILE_OPT --query Buckets[*].Name --output text|xargs -n1)
if [[ $LIST_OF_BUCKETS ]]; then
for bucket in $LIST_OF_BUCKETS;do
BUCKET_VERSIONING_ENABLED=$($AWSCLI s3api get-bucket-versioning --bucket $bucket $PROFILE_OPT --query Status --output text 2>&1)
if [[ $(echo "$BUCKET_VERSIONING_ENABLED" | grep AccessDenied) ]]; then
textFail "Access Denied Trying to Get Bucket Versioning for $bucket"
continue
fi
if [[ $(echo "$BUCKET_VERSIONING_ENABLED" | grep "^Enabled$") ]]; then
textPass "Bucket $bucket has versioning enabled"
else
textFail "Bucket $bucket has versioning disabled!"
fi
done
else
textInfo "No S3 Buckets found"
fi
}

50
checks/check_extra764 Normal file
View File

@@ -0,0 +1,50 @@
#!/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_extra764="7.64"
CHECK_TITLE_extra764="[extra764] Check if S3 buckets have secure transport policy (Not Scored) (Not part of CIS benchmark)"
CHECK_SCORED_extra764="NOT_SCORED"
CHECK_TYPE_extra764="EXTRA"
CHECK_ALTERNATE_check764="extra764"
extra764(){
LIST_OF_BUCKETS=$($AWSCLI s3api list-buckets $PROFILE_OPT --query Buckets[*].Name --output text|xargs -n1)
if [[ $LIST_OF_BUCKETS ]]; then
for bucket in $LIST_OF_BUCKETS;do
TEMP_STP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-${bucket}.policy.XXXXXXXXXX)
# get bucket policy
$AWSCLI s3api get-bucket-policy $PROFILE_OPT --bucket $bucket --output text --query Policy > $TEMP_STP_POLICY_FILE 2>&1
if [[ $(grep AccessDenied $TEMP_STP_POLICY_FILE) ]]; then
textFail "Access Denied Trying to Get Bucket Policy for $bucket"
continue
fi
if [[ $(grep NoSuchBucketPolicy $TEMP_STP_POLICY_FILE) ]]; then
textFail "No bucket policy for $bucket"
continue
fi
# check if the S3 policy denies all actions by all principals when aws:SecureTransport:false
CHECK_BUCKET_STP_POLICY_PRESENT=$(cat $TEMP_STP_POLICY_FILE | jq --arg arn "arn:aws:s3:::${bucket}/*" '.Statement[]|select(.Effect=="Deny" and (.Principal|type == "object") and .Principal.AWS == "*" and .Action=="s3:*" and .Resource==$arn and .Condition.Bool."aws:SecureTransport" == "false")')
if [[ $CHECK_BUCKET_STP_POLICY_PRESENT ]]; then
textPass "Bucket $bucket has S3 bucket policy to deny requests over insecure transport"
else
textFail "Bucket $bucket allows requests over insecure transport"
fi
rm -fr $TEMP_STP_POLICY_FILE
done
else
textInfo "No S3 Buckets found"
fi
}

View File

@@ -15,7 +15,7 @@ GROUP_ID[7]='extras'
GROUP_NUMBER[7]='7.0'
GROUP_TITLE[7]='Extras - [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'
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'
# Extras 759 and 760 (lambda variables and code secrets finder are not included)
# to run detect-secrets use `./prowler -g secrets`

View File

@@ -5,18 +5,19 @@
"Action": [
"acm:describecertificate",
"acm:listcertificates",
"apigateway:GET",
"cloudtrail:GetEventSelectors",
"ec2:GetEbsEncryptionByDefault",
"es:describeelasticsearchdomainconfig",
"guardduty:GetDetector",
"guardduty:ListDetectors",
"logs:DescribeLogGroups",
"logs:DescribeMetricFilters",
"s3:GetEncryptionConfiguration",
"ses:getidentityverificationattributes",
"sns:listsubscriptionsbytopic",
"guardduty:ListDetectors",
"guardduty:GetDetector",
"S3:GetEncryptionConfiguration",
"trustedadvisor:Describe*",
"cloudtrail:GetEventSelectors",
"apigateway:GET",
"support:*"
"trustedadvisor:Describe*",
],
"Effect": "Allow",
"Resource": "*"

View File

@@ -50,18 +50,20 @@ Resources:
Action:
- "acm:describecertificate"
- "acm:listcertificates"
- "apigateway:GET"
- "cloudtrail:GetEventSelectors"
- "ec2:GetEbsEncryptionByDefault"
- "es:describeelasticsearchdomainconfig"
- "logs:DescribeLogGroups"
- "logs:DescribeMetricFilters"
- "ses:getidentityverificationattributes"
- "sns:listsubscriptionsbytopic"
- "guardduty:ListDetectors"
- "guardduty:GetDetector"
- "S3:GetEncryptionConfiguration"
- "trustedadvisor:Describe*"
- "cloudtrail:GetEventSelectors"
- "apigateway:GET"
- "logs:DescribeLogGroups"
- "logs:DescribeMetricFilters"
- "s3:GetEncryptionConfiguration"
- "ses:getidentityverificationattributes"
- "sns:listsubscriptionsbytopic"
- "support:*"
- "trustedadvisor:Describe*"
Metadata:
cfn_nag:
rules_to_suppress:

View File

@@ -301,9 +301,6 @@ Resources:
discard-paths: no
base-directory: out
ProwlerAuditTriggerRole:
Type: AWS::IAM::Role
Properties: