Skip to content

Commit

Permalink
Merge pull request #177 from toniblyx/master
Browse files Browse the repository at this point in the history
New checks and improvements
  • Loading branch information
toniblyx authored Feb 16, 2018
2 parents 282f758 + ec79301 commit 111615b
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 48 deletions.
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ It covers hardening and security best practices for all AWS regions related to:
- Logging (8 checks)
- Monitoring (15 checks)
- Networking (5 checks)
- Extras (19 checks) *see Extras section
- Forensics related checks
- Extras (22 checks) *see Extras section*
- Forensics related group of checks

For a comprehesive list and resolution look at the guide on the link above.

Expand Down Expand Up @@ -128,14 +128,19 @@ USAGE:
prowler -p <profile> -r <region> [ -h ]
Options:
-p <profile> specify your AWS profile to use (i.e.: default)
-r <region> specify an AWS region to direct API requests to (i.e.: us-east-1), all regions are checked anyway
-c <checknum> specify a check number or group from the AWS CIS benchmark (i.e.: check11 for check 1.1, check3 for entire section 3 or level1 for CIS Level 1 Profile Definitions)
-f <filterregion> specify an AWS region to run checks against (i.e.: us-west-1)
-r <region> specify an AWS region to direct API requests to
(i.e.: us-east-1), all regions are checked anyway
-c <check_id> specify a check number or group from the AWS CIS benchmark
(i.e.: "check11" for check 1.1, "check3" for entire section 3, "level1" for CIS Level 1 Profile Definitions or "forensics-ready")
-f <filterregion> specify an AWS region to run checks against
(i.e.: us-west-1)
-m <maxitems> specify the maximum number of items to return for long-running requests (default: 100)
-M <mode> output mode: text (defalut), mono, csv (separator is ","; data is on stdout; progress on stderr)
-k keep the credential report
-n show check numbers to sort easier (i.e.: 1.01 instead of 1.1)
-n show check numbers to sort easier
(i.e.: 1.01 instead of 1.1)
-l list all available checks only (does not perform any check)
-e exclude extras
-h this help
```
Expand Down Expand Up @@ -326,7 +331,7 @@ We are adding additional checks to improve the information gather from each acco

Note: Some of these checks for publicly facing resources may not actually be fully public due to other layered controls like S3 Bucket Policies, Security Groups or Network ACLs.

At this moment we have 16 extra checks:
At this moment we have 22 extra checks:

- 7.1 (`extra71`) Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)
- 7.2 (`extra72`) Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)
Expand All @@ -347,6 +352,9 @@ At this moment we have 16 extra checks:
- 7.17 (`extra717`) Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)
- 7.18 (`extra718`) Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)
- 7.19 (`extra719`) Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)
- 7.20 (`extra720`) Check if Lambda functions are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)
- 7.21 (`extra721`) Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)
- 7.22 (`extra722`) Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)


To check all extras in one command:
Expand Down Expand Up @@ -376,6 +384,9 @@ With this group of checks, Prowler looks if each service with logging or audit c
- 7.17 Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark)
- 7.18 Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)
- 7.19 Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)
- 7.20 Check if Lambda functions are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)
- 7.21 Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)
- 7.22 Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)

The `forensics-ready` group of checks uses existing and extra checks. To get a forensics readiness report, run this command:
```
Expand Down
198 changes: 158 additions & 40 deletions prowler
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,28 @@ usage(){
echo "
USAGE:
`basename $0` -p <profile> -r <region> [ -h ]
Options:
-p <profile> specify your AWS profile to use (i.e.: default)
-r <region> specify an AWS region to direct API requests to (i.e.: us-east-1), all regions are checked anyway
-c <checknum> specify a check number or group from the AWS CIS benchmark (i.e.: check11 for check 1.1, extra71, check3 for entire section 3 or level1 for CIS Level 1 Profile Definitions)
-f <filterregion> specify an AWS region to run checks against (i.e.: us-west-1)
-r <region> specify an AWS region to direct API requests to
(i.e.: us-east-1), all regions are checked anyway
-c <check_id> specify a check number or group from the AWS CIS benchmark
(i.e.: "check11" for check 1.1, "check3" for entire section 3, "level1" for CIS Level 1 Profile Definitions or "forensics-ready")
-f <filterregion> specify an AWS region to run checks against
(i.e.: us-west-1)
-m <maxitems> specify the maximum number of items to return for long-running requests (default: 100)
-M <mode> output mode: text (default), mono, csv (separator is \"${SEP}\"; data is on stdout; progress on stderr)
-M <mode> output mode: text (defalut), mono, csv (separator is ","; data is on stdout; progress on stderr)
-k keep the credential report
-n show check numbers to sort easier (i.e.: 1.01 instead of 1.1)
-n show check numbers to sort easier
(i.e.: 1.01 instead of 1.1)
-l list all available checks only (does not perform any check)
-e exclude extras
-h this help
"
exit
}

while getopts ":hlkp:r:c:f:m:M:n" OPTION; do
while getopts ":hlkp:r:c:f:m:M:en" OPTION; do
case $OPTION in
h )
usage
Expand Down Expand Up @@ -94,6 +100,9 @@ while getopts ":hlkp:r:c:f:m:M:n" OPTION; do
n )
NUMERAL=1
;;
e )
EXTRAS=1
;;
: )
echo ""
echo "$OPTRED ERROR!$OPTNORMAL -$OPTARG requires an argument"
Expand Down Expand Up @@ -506,6 +515,12 @@ ID718="7.18,7.18"
TITLE718="Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark)"
ID719="7.19,7.19"
TITLE719="Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark)"
ID720="7.20,7.20"
TITLE720="Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)"
ID721="7.21,7.21"
TITLE721="Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)"
ID722="7.22,7.22"
TITLE722="Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)"

printCsvHeader() {
>&2 echo ""
Expand Down Expand Up @@ -1890,7 +1905,7 @@ extra713(){
# "Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)"
textTitle "$ID713" "$TITLE713" "NOT_SCORED" "EXTRA"
for regx in $REGIONS; do
LIST_OF_GUARDDUTY_DETECTORS=$($AWSCLI guardduty list-detectors $PROFILE_OPT --region $regx --output text 2>/dev/null |cut -f2)
LIST_OF_GUARDDUTY_DETECTORS=$($AWSCLI guardduty list-detectors $PROFILE_OPT --region $regx --output text |cut -f2)
if [[ $LIST_OF_GUARDDUTY_DETECTORS ]];then
while read -r detector;do
DETECTOR_ENABLED=$($AWSCLI guardduty get-detector --detector-id $detector $PROFILE_OPT --region $regx --output text| cut -f3|grep ENABLED)
Expand All @@ -1901,7 +1916,7 @@ extra713(){
fi
done <<< "$LIST_OF_GUARDDUTY_DETECTORS"
else
textWarn "$regx: GuardDuty detector $detector not configured" "$regx"
textWarn "$regx: GuardDuty detector not configured!" "$regx"
fi
done
}
Expand Down Expand Up @@ -2050,6 +2065,96 @@ extra719(){
fi
}
extra720(){
# "Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark)"
textTitle "$ID720" "$TITLE720" "NOT_SCORED" "EXTRA"
for regx in $REGIONS; do
LIST_OF_FUNCTIONS=$($AWSCLI lambda list-functions $PROFILE_OPT --region $regx --query Functions[*].FunctionName --output text)
if [[ $LIST_OF_FUNCTIONS ]]; then
for lambdafunction in $LIST_OF_FUNCTIONS;do
LIST_OF_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query trailList[?HomeRegion==\`$regx\`].Name --output text)
if [[ $LIST_OF_TRAILS ]]; then
for trail in $LIST_OF_TRAILS; do
FUNCTION_ENABLED_IN_TRAIL=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $regx --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$")
if [[ $FUNCTION_ENABLED_IN_TRAIL ]]; then
textOK "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx"
else
textWarn "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx"
fi
done
# LIST_OF_MULTIREGION_TRAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\`].Name" --output text)
# if [[ $LIST_OF_MULTIREGION_TRAILS ]]; then
# for trail in $LIST_OF_MULTIREGION_TRAILS; do
# REGION_OF_TRAIL=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query "trailList[?IsMultiRegionTrail == \`true\` && Name == \`$trail\` ].HomeRegion" --output text)
# FUNCTION_ENABLED_IN_THIS_REGION=$($AWSCLI cloudtrail get-event-selectors $PROFILE_OPT --trail-name $trail --region $REGION_OF_TRAIL --query "EventSelectors[*].DataResources[?Type == \`AWS::Lambda::Function\`].Values" --output text |xargs -n1| grep -E "^arn:aws:lambda.*function:$lambdafunction$")
# if [[ $FUNCTION_ENABLED_IN_THIS_REGION ]]; then
# textOK "$regx: Lambda function $lambdafunction enabled in trail $trail" "$regx"
# else
# textWarn "$regx: Lambda function $lambdafunction NOT enabled in trail $trail" "$regx"
# fi
# done
# else
# textWarn "$regx: Lambda function $lambdafunction is not being recorded!" "$regx"
# fi
else
textWarn "$regx: Lambda function $lambdafunction is not being recorded no CloudTrail found!" "$regx"
fi
done
else
textNotice "$regx: No Lambda functions found" "$regx"
fi
done
}
extra721(){
# "Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark)"
textTitle "$ID721" "$TITLE721" "NOT_SCORED" "EXTRA"
for regx in $REGIONS; do
LIST_OF_REDSHIFT_CLUSTERS=$($AWSCLI redshift describe-clusters $PROFILE_OPT --region $regx --query 'Clusters[*].ClusterIdentifier' --output text)
if [[ $LIST_OF_REDSHIFT_CLUSTERS ]]; then
for redshiftcluster in $LIST_OF_REDSHIFT_CLUSTERS;do
REDSHIFT_LOG_ENABLED=$($AWSCLI redshift describe-logging-status $PROFILE_OPT --region $regx --cluster-identifier $redshiftcluster --query LoggingEnabled --output text | grep True)
if [[ $REDSHIFT_LOG_ENABLED ]];then
REDSHIFT_LOG_ENABLED_BUCKET=$($AWSCLI redshift describe-logging-status $PROFILE_OPT --region $regx --cluster-identifier $redshiftcluster --query BucketName --output text)
textOK "$regx: Redshift cluster $redshiftcluster has audit logging enabled to bucket $REDSHIFT_LOG_ENABLED_BUCKET" "$regx"
else
textWarn "$regx: Redshift cluster $redshiftcluster logging disabled!" "$regx"
fi
done
else
textNotice "$regx: No Redshift cluster configured" "$regx"
fi
done
}
extra722(){
# "Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark)"
textTitle "$ID722" "$TITLE722" "NOT_SCORED" "EXTRA"
for regx in $REGIONS; do
LIST_OF_API_GW=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query items[*].id --output text)
if [[ $LIST_OF_API_GW ]];then
for apigwid in $LIST_OF_API_GW;do
API_GW_NAME=$($AWSCLI apigateway get-rest-apis $PROFILE_OPT --region $regx --query "items[?id==\`$apigwid\`].name" --output text)
CHECK_STAGES_NAME=$($AWSCLI apigateway get-stages $PROFILE_OPT --region $regx --rest-api-id $apigwid --query "item[*].stageName" --output text)
if [[ $CHECK_STAGES_NAME ]];then
for stagname in $CHECK_STAGES_NAME;do
CHECK_STAGE_METHOD_LOGGING=$($AWSCLI apigateway get-stages $PROFILE_OPT --region $regx --rest-api-id $apigwid --query "item[?stageName == \`$stagname\` ].methodSettings" --output text|awk '{ print $1" log level "$6}')
if [[ $CHECK_STAGE_METHOD_LOGGING ]];then
textOK "$regx: API Gateway $API_GW_NAME has stage logging enabled for $CHECK_STAGE_METHOD_LOGGING" "$regx"
else
textWarn "$regx: API Gateway $API_GW_NAME logging disabled for stage $stagname!" "$regx"
fi
done
else
textWarn "$regx: No Stage name found for $API_GW_NAME" "$regx"
fi
done
else
textNotice "$regx: No API Gateway found" "$regx"
fi
done
}
callCheck(){
if [[ $CHECKNUMBER ]];then
case "$CHECKNUMBER" in
Expand Down Expand Up @@ -2114,16 +2219,20 @@ callCheck(){
extra77|extra707 ) extra77;;
extra78|extra708 ) extra78;;
extra79|extra709 ) extra79;;
extra710|extra710 ) extra710;;
extra711|extra711 ) extra711;;
extra712|extra712 ) extra712;;
extra713|extra713 ) extra713;;
extra714|extra714 ) extra714;;
extra715|extra715 ) extra715;;
extra716|extra716 ) extra716;;
extra717|extra717 ) extra717;;
extra718|extra718 ) extra718;;
extra719|extra719 ) extra719;;
extra710 ) extra710;;
extra711 ) extra711;;
extra712 ) extra712;;
extra713 ) extra713;;
extra714 ) extra714;;
extra715 ) extra715;;
extra716 ) extra716;;
extra717 ) extra717;;
extra718 ) extra718;;
extra719 ) extra719;;
extra720 ) extra720;;
extra721 ) extra721;;
extra722 ) extra722;;
## Groups of Checks
check1 )
Expand Down Expand Up @@ -2161,12 +2270,13 @@ callCheck(){
extras )
extra71;extra72;extra73;extra74;extra75;extra76;extra77;extra78;
extra79;extra710;extra711;extra712;extra713;extra714;extra715;extra716;
extra717;extra718;extra719
extra717;extra718;extra719;extra720;extra721;extra722
;;
forensics-ready )
check21;check22;check23;check24;check25;check26;check27;
check43;
extra712;extra713;extra714;extra715;extra717;extra718;extra719
extra712;extra713;extra714;extra715;extra717;extra718;extra719;
extra720;extra721;extra722
;;
* )
textWarn "ERROR! Use a valid check name (i.e. check41 or extra71)\n";
Expand Down Expand Up @@ -2256,6 +2366,9 @@ if [[ $PRINTCHECKSONLY == "1" ]]; then
textTitle "$ID717" "$TITLE717" "NOT_SCORED" "EXTRA"
textTitle "$ID718" "$TITLE718" "NOT_SCORED" "EXTRA"
textTitle "$ID719" "$TITLE719" "NOT_SCORED" "EXTRA"
textTitle "$ID720" "$TITLE720" "NOT_SCORED" "EXTRA"
textTitle "$ID721" "$TITLE721" "NOT_SCORED" "EXTRA"
textTitle "$ID722" "$TITLE722" "NOT_SCORED" "EXTRA"
exit $EXITCODE
fi
Expand Down Expand Up @@ -2331,26 +2444,31 @@ check43
check44
check45
textTitle "7" "$TITLE7" "NOT_SCORED" "SUPPORT"
extra71
extra72
extra73
extra74
extra75
extra76
extra77
extra78
extra79
extra710
extra711
extra712
extra713
extra714
extra715
extra716
extra717
extra718
extra719
if [[ ! $EXTRAS ]]; then
textTitle "7" "$TITLE7" "NOT_SCORED" "SUPPORT"
extra71
extra72
extra73
extra74
extra75
extra76
extra77
extra78
extra79
extra710
extra711
extra712
extra713
extra714
extra715
extra716
extra717
extra718
extra719
extra720
extra721
extra722
fi
cleanTemp
exit $EXITCODE
3 changes: 2 additions & 1 deletion prowler-policy-additions.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"cloudwatchlogs:describemetricfilters",
"es:describeelasticsearchdomainconfig",
"ses:getidentityverificationattributes",
"sns:listsubscriptionsbytopic"
"sns:listsubscriptionsbytopic",
"guardduty:ListDetectors"
],
"Effect": "Allow",
"Resource": "*"
Expand Down

0 comments on commit 111615b

Please sign in to comment.