create check files

This commit is contained in:
Toni de la Fuente
2018-03-20 22:59:34 -04:00
parent 2f761f62a6
commit a21bff31a5
97 changed files with 635 additions and 315 deletions

0
checks/check Normal file
View File

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
CHECK_ID[check11]="1.1,1.01"
CHECK_TITLE[check11]="Avoid the use of the root account (Scored)."
CHECK_TITLE[check11]="Avoid the use of the root account (Scored)"
CHECK_SCORED[check11]="SCORED"
CHECK_TYPE[check11]="LEVEL1"
CHECK_ALTERNATE[check101]="check11"

0
checks/check110 Normal file
View File

0
checks/check111 Normal file
View File

0
checks/check112 Normal file
View File

0
checks/check113 Normal file
View File

0
checks/check114 Normal file
View File

0
checks/check115 Normal file
View File

0
checks/check116 Normal file
View File

0
checks/check117 Normal file
View File

0
checks/check118 Normal file
View File

0
checks/check119 Normal file
View File

25
checks/check12 Normal file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
CHECK_ID[check12]="1.2,1.02"
CHECK_TITLE[check12]="Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)"
CHECK_SCORED[check12]="SCORED"
CHECK_TYPE[check12]="LEVEL1"
CHECK_ALTERNATE[check102]="check12"
check12(){
# "Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)"
# List users with password enabled
COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED=$(cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$4 }' |grep true | awk '{ print $1 }')
COMMAND12=$(
for i in $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED; do
cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$8 }' |grep "$i " |grep false | awk '{ print $1 }'
done)
textTitle "$ID12" "$TITLE12" "SCORED" "LEVEL1"
if [[ $COMMAND12 ]]; then
for u in $COMMAND12; do
textWarn "User $u has Password enabled but MFA disabled"
done
else
textOK "No users found with Password enabled and MFA disabled"
fi
}

0
checks/check120 Normal file
View File

0
checks/check121 Normal file
View File

0
checks/check122 Normal file
View File

0
checks/check123 Normal file
View File

0
checks/check124 Normal file
View File

0
checks/check13 Normal file
View File

0
checks/check14 Normal file
View File

0
checks/check15 Normal file
View File

0
checks/check16 Normal file
View File

0
checks/check17 Normal file
View File

0
checks/check18 Normal file
View File

0
checks/check19 Normal file
View File

0
checks/check21 Normal file
View File

0
checks/check22 Normal file
View File

0
checks/check23 Normal file
View File

0
checks/check24 Normal file
View File

0
checks/check25 Normal file
View File

0
checks/check26 Normal file
View File

0
checks/check27 Normal file
View File

0
checks/check28 Normal file
View File

0
checks/check31 Normal file
View File

0
checks/check310 Normal file
View File

0
checks/check311 Normal file
View File

0
checks/check312 Normal file
View File

0
checks/check313 Normal file
View File

0
checks/check314 Normal file
View File

0
checks/check315 Normal file
View File

0
checks/check32 Normal file
View File

0
checks/check33 Normal file
View File

0
checks/check34 Normal file
View File

0
checks/check35 Normal file
View File

0
checks/check36 Normal file
View File

0
checks/check37 Normal file
View File

0
checks/check38 Normal file
View File

0
checks/check39 Normal file
View File

0
checks/check41 Normal file
View File

0
checks/check42 Normal file
View File

0
checks/check43 Normal file
View File

0
checks/check44 Normal file
View File

0
checks/check45 Normal file
View File

0
checks/check_extra71 Normal file
View File

0
checks/check_extra710 Normal file
View File

0
checks/check_extra711 Normal file
View File

0
checks/check_extra712 Normal file
View File

0
checks/check_extra713 Normal file
View File

0
checks/check_extra714 Normal file
View File

0
checks/check_extra715 Normal file
View File

0
checks/check_extra716 Normal file
View File

0
checks/check_extra717 Normal file
View File

0
checks/check_extra718 Normal file
View File

0
checks/check_extra719 Normal file
View File

0
checks/check_extra72 Normal file
View File

0
checks/check_extra720 Normal file
View File

0
checks/check_extra721 Normal file
View File

0
checks/check_extra722 Normal file
View File

0
checks/check_extra723 Normal file
View File

0
checks/check_extra73 Normal file
View File

0
checks/check_extra74 Normal file
View File

0
checks/check_extra75 Normal file
View File

0
checks/check_extra76 Normal file
View File

0
checks/check_extra77 Normal file
View File

0
checks/check_extra78 Normal file
View File

0
checks/check_extra79 Normal file
View File

166
checks/list Normal file
View File

@@ -0,0 +1,166 @@
_
_ __ _ __ _____ _| | ___ _ __
| '_ \| '__/ _ \ \ /\ / / |/ _ \ '__|
| |_) | | | (_) \ V V /| | __/ |
| .__/|_| \___/ \_/\_/ |_|\___|_|
|_| CIS based AWS Account Hardening Tool
Date: Tue Mar 20 21:50:38 EDT 2018
1 Identity and Access Management ****************************************
1.1 Avoid the use of the root account (Scored).
1.2 Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)
1.3 Ensure credentials unused for 90 days or greater are disabled (Scored)
1.4 Ensure access keys are rotated every 90 days or less (Scored)
1.5 Ensure IAM password policy requires at least one uppercase letter (Scored)
1.6 Ensure IAM password policy require at least one lowercase letter (Scored)
1.7 Ensure IAM password policy require at least one symbol (Scored)
1.8 Ensure IAM password policy require at least one number (Scored)
1.9 Ensure IAM password policy requires minimum length of 14 or greater (Scored)
1.10 Ensure IAM password policy prevents password reuse: 24 or greater (Scored)
1.11 Ensure IAM password policy expires passwords within 90 days or less (Scored)
1.12 Ensure no root account access key exists (Scored)
1.13 Ensure MFA is enabled for the root account (Scored)
1.14 Ensure hardware MFA is enabled for the root account (Scored)
1.15 Ensure security questions are registered in the AWS account (Not Scored)
1.16 Ensure IAM policies are attached only to groups or roles (Scored)
1.17 Enable detailed billing (Scored)
1.18 Ensure IAM Master and IAM Manager roles are active (Scored)
1.19 Maintain current contact details (Scored)
1.20 Ensure security contact information is registered (Scored)
1.21 Ensure IAM instance roles are used for AWS resource access from instances (Not Scored)
1.22 Ensure a support role has been created to manage incidents with AWS Support (Scored)
1.23 Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored)
1.24 Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored)
2 Logging ***************************************************************
2.1 Ensure CloudTrail is enabled in all regions (Scored)
2.2 Ensure CloudTrail log file validation is enabled (Scored)
2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)
2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)
2.5 Ensure AWS Config is enabled in all regions (Scored)
2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)
2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)
2.8 Ensure rotation for customer created CMKs is enabled (Scored)
3 Monitoring ************************************************************
3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)
3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored)
3.3 Ensure a log metric filter and alarm exist for usage of root account (Scored)
3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored)
3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored)
3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored)
3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored)
3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored)
3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored)
3.10 Ensure a log metric filter and alarm exist for security group changes (Scored)
3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored)
3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored)
3.13 Ensure a log metric filter and alarm exist for route table changes (Scored)
3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored)
3.15 Ensure appropriate subscribers to each SNS topic (Not Scored)
4 Networking ************************************************************
4.1 Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored)
4.2 Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored)
4.3 Ensure VPC Flow Logging is Enabled in all VPCs (Scored)
4.4 Ensure the default security group of every VPC restricts all traffic (Scored)
4.5 Ensure routing tables for VPC peering are "least access" (Not Scored)
7 Extras ****************************************************************
7.1 Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark)
7.2 Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark)
7.3 Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark)
7.4 Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark)
7.5 Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark)
7.6 Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark)
7.7 Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark)
7.8 Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark)
7.9 Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark)
7.10 Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark)
7.11 Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark)
7.12 Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark)
7.13 Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark)
7.14 Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark)
7.15 Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark)
7.16 Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)
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 invoke API operations 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)

79
checks/lista Normal file
View File

@@ -0,0 +1,79 @@
check1
check11
check12
check13
check14
check15
check16
check17
check18
check19
check110
check111
check112
check113
check114
check115
check116
check117
check118
check119
check120
check121
check122
check123
check124
check2
check21
check22
check23
check24
check25
check26
check27
check28
check3
check31
check32
check33
check34
check35
check36
check37
check38
check39
check310
check311
check312
check313
check314
check315
check4
check41
check42
check43
check44
check45
check7
check71
check72
check73
check74
check75
check76
check77
check78
check79
check710
check711
check712
check713
check714
check715
check716
check717
check718
check719
check720
check721
check722

View File

@@ -2,6 +2,6 @@
GROUP_ID[1]="group1"
GROUP_NUMBER[1]="1.0"
GROUP_TITLE[1]="Identity and Access Management"
GROUP_RUN_BY_DEFAULT[1]="Y" # run it when execute_all is called
GROUP_CHECKS[1]="check11"
GROUP_TITLE[1]="Identity and Access Management ****************************************"
GROUP_RUN_BY_DEFAULT[1]="Y" # run it when execute_all is called
GROUP_CHECKS[1]="check11,check12"

0
groups/group2 Normal file
View File

0
groups/group3 Normal file
View File

0
groups/group4 Normal file
View File

0
groups/group_cislevel1 Normal file
View File

0
groups/group_cislevel2 Normal file
View File

0
groups/group_extras Normal file
View File

0
groups/group_forensics Normal file
View File

View File

@@ -0,0 +1,22 @@
# It checks -p optoin first and use it as profile, if not -p provided then
# check environment variables and if not, it checks and loads credentials from
# instance profile (metadata server) if runs in an EC2 instance
if [[ $PROFILE ]]; then
PROFILE_OPT="--profile $PROFILE"
else
# if Prowler runs insinde an AWS instance with IAM instance profile attached
INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/)
if [[ $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')
fi
if [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then
PROFILE="ENV"
PROFILE_OPT=""
else
PROFILE="default"
PROFILE_OPT="--profile $PROFILE"
fi
fi

7
include/awscli_detector Normal file
View File

@@ -0,0 +1,7 @@
# AWS-CLI detector variable
AWSCLI=$(which aws)
if [ -z "${AWSCLI}" ]; then
echo -e "\n$RED ERROR!$NORMAL AWS-CLI (aws command) not found. Make sure it is installed correctly and in your \$PATH\n"
EXITCODE=1
exit $EXITCODE
fi

19
include/banner Normal file
View File

@@ -0,0 +1,19 @@
prowlerBanner() {
echo -e "$CYAN _"
echo -e " _ __ _ __ _____ _| | ___ _ __"
echo -e " | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__|"
echo -e " | |_) | | | (_) \ V V /| | __/ |"
echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|"
echo -e " |_|$NORMAL$BLUE CIS based AWS Account Hardening Tool$NORMAL\n"
echo -e "$YELLOW Date: $(date)"
}
infoReferenceLong(){
# Report review note:
echo -e ""
echo -e "For more information on the Prowler, feedback and issue reporting:"
echo -e "https://github.com/toniblyx/prowler"
echo -e ""
echo -e "For more information on the CIS benchmark:"
echo -e "https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf"
}

View File

@@ -0,0 +1,58 @@
if [[ $MODE != "mono" && $MODE != "text" && $MODE != "csv" ]]; then
echo ""
echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, or csv."
usage
EXITCODE=1
exit $EXITCODE
fi
if [[ "$MODE" == "mono" || "$MODE" == "csv" ]]; then
MONOCHROME=1
fi
if [[ $MONOCHROME -eq 1 ]]; then
# Colors
NORMAL=''
WARNING='' # Bad (red)
SECTION='' # Section (yellow)
NOTICE='' # Notice (yellow)
OK='' # Ok (green)
BAD='' # Bad (red)
CYAN=''
BLUE=''
BROWN=''
DARKGRAY=''
GRAY=''
GREEN=''
MAGENTA=''
PURPLE=''
RED=''
YELLOW=''
WHITE=''
else
# Colors
# NOTE: Your editor may NOT show the 0x1b / escape character left of the '['
NORMAL=""
WARNING="" # Bad (red)
SECTION="" # Section (yellow)
NOTICE="" # Notice (yellow)
OK="" # Ok (green)
BAD="" # Bad (red)
CYAN=""
BLUE=""
BROWN=""
DARKGRAY=""
GRAY=""
GREEN=""
MAGENTA=""
PURPLE=""
RED=""
YELLOW=""
WHITE=""
fi
printColorsCode(){
if [[ $MONOCHROME -eq 0 ]]; then
echo -e "\n$NORMAL Colors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL"
fi
}

View File

@@ -0,0 +1,26 @@
# Generate Credential Report
genCredReport() {
textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT"
until $( $AWSCLI iam generate-credential-report --output text --query 'State' $PROFILE_OPT --region $REGION |grep -q -m 1 "COMPLETE") ; do
sleep 1
done
}
# Save report to a file, decode it, deletion at finish and after every single check
saveReport(){
$AWSCLI iam get-credential-report --query 'Content' --output text $PROFILE_OPT --region $REGION | decode_report > $TEMP_REPORT_FILE
if [[ $KEEPCREDREPORT -eq 1 ]]; then
textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT"
textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE"
fi
}
# Delete temporary report file
cleanTemp(){
if [[ $KEEPCREDREPORT -ne 1 ]]; then
rm -fr $TEMP_REPORT_FILE
fi
}
# Delete the temporary report file if we get interrupted/terminated
trap cleanTemp EXIT

5
include/csv_header Normal file
View File

@@ -0,0 +1,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"
}

76
include/os_detector Normal file
View File

@@ -0,0 +1,76 @@
# Functions to manage dates depending on OS
if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == "linux-musl" ]; then
TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX)
# function to compare in days, usage how_older_from_today date
# date format %Y-%m-%d
how_older_from_today()
{
DATE_TO_COMPARE=$1
TODAY_IN_DAYS=$(date -d "$(date +%Y-%m-%d)" +%s)
DATE_FROM_IN_DAYS=$(date -d $DATE_TO_COMPARE +%s)
DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24))
echo $DAYS_SINCE
}
# function to convert from timestamp to date, usage timestamp_to_date timestamp
# output date format %Y-%m-%d
timestamp_to_date()
{
# remove fractions of a second
TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".")
OUTPUT_DATE=$(date -d @$TIMESTAMP_TO_CONVERT +'%Y-%m-%d')
echo $OUTPUT_DATE
}
decode_report()
{
base64 -d
}
elif [[ "$OSTYPE" == "darwin"* ]]; then
# BSD/OSX commands compatibility
TEMP_REPORT_FILE=$(mktemp -t prowler.cred_report-XXXXXX)
how_older_from_today()
{
DATE_TO_COMPARE=$1
TODAY_IN_DAYS=$(date +%s)
DATE_FROM_IN_DAYS=$(date -jf %Y-%m-%d $DATE_TO_COMPARE +%s)
DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24))
echo $DAYS_SINCE
}
timestamp_to_date()
{
# remove fractions of a second
TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".")
OUTPUT_DATE=$(date -r $TIMESTAMP_TO_CONVERT +'%Y-%m-%d')
echo $OUTPUT_DATE
}
decode_report()
{
base64 -D
}
elif [[ "$OSTYPE" == "cygwin" ]]; then
# POSIX compatibility layer and Linux environment emulation for Windows
TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX)
how_older_from_today()
{
DATE_TO_COMPARE=$1
TODAY_IN_DAYS=$(date -d "$(date +%Y-%m-%d)" +%s)
DATE_FROM_IN_DAYS=$(date -d $DATE_TO_COMPARE +%s)
DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24))
echo $DAYS_SINCE
}
timestamp_to_date()
{
# remove fractions of a second
TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".")
OUTPUT_DATE=$(date -d @$TIMESTAMP_TO_CONVERT +'%Y-%m-%d')
echo $OUTPUT_DATE
}
decode_report()
{
base64 -d
}
else
echo "Unknown Operating System! Valid \$OSTYPE: linux-gnu, linux-musl, darwin* or cygwin"
echo "Found: $OSTYPE"
EXITCODE=1
exit $EXITCODE
fi

81
include/outputs Normal file
View File

@@ -0,0 +1,81 @@
## Output formatting functions
textOK(){
if [[ "$MODE" == "csv" ]]; then
if [[ $2 ]]; then
REPREGION=$2
else
REPREGION=$REGION
fi
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1"
else
echo " $OK OK! $NORMAL $1"
fi
}
textNotice(){
if [[ "$MODE" == "csv" ]]; then
if [[ $2 ]]; then
REPREGION=$2
else
REPREGION=$REGION
fi
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1"
else
echo " $NOTICE INFO! $1 $NORMAL"
fi
}
textWarn(){
EXITCODE=3
if [[ "$MODE" == "csv" ]]; then
if [[ $2 ]]; then
REPREGION=$2
else
REPREGION=$REGION
fi
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1"
else
echo " $BAD WARNING! $1 $NORMAL"
fi
}
textTitle(){
TITLE_ID=$1
if [[ $NUMERAL ]]; then
TITLE_ID=$(echo $TITLE_ID | cut -d, -f2)
else
TITLE_ID=$(echo $TITLE_ID | cut -d, -f1)
fi
TITLE_TEXT=$2
case "$3" in
0|No|NOT_SCORED)
ITEM_SCORED="Not Scored"
;;
1|Yes|SCORED)
ITEM_SCORED="Scored"
;;
*)
ITEM_SCORED="Unspecified"
;;
esac
case "$4" in
LEVEL1) ITEM_LEVEL="Level 1";;
LEVEL2) ITEM_LEVEL="Level 2";;
EXTRA) ITEM_LEVEL="Extra";;
SUPPORT) ITEM_LEVEL="Support";;
*) ITEM_LEVEL="Unspecified or Invalid";;
esac
if [[ "$MODE" == "csv" ]]; then
>&2 echo "$TITLE_ID $TITLE_TEXT"
else
if [[ "$ITEM_SCORED" == "Scored" ]]; then
echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT"
else
echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL"
fi
fi
}

44
include/whoami Normal file
View File

@@ -0,0 +1,44 @@
# Get whoami in AWS, who is the user running this shell script
getWhoami(){
ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Account" | tr -d '"')
if [[ "$MODE" == "csv" ]]; then
CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Arn")
if [[ 255 -eq $? ]]; then
# Failed to get own identity ... exit
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
>&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
EXITCODE=2
exit $EXITCODE
fi
CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"')
printCsvHeader
textTitle "0.0" "Show report generation info" "NOT_SCORED" "SUPPORT"
textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME"
else
echo ""
echo -e " This report is being generated using credentials below:\n"
echo -e " AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS API Region: $NOTICE[$REGION]$NORMAL AWS Filter Region: $NOTICE[${FILTERREGION:-all}]$NORMAL\n"
if [[ $MONOCHROME -eq 1 ]]; then
echo -e " Caller Identity:"
$AWSCLI sts get-caller-identity --output text $PROFILE_OPT --region $REGION --query "Arn"
if [[ 255 -eq $? ]]; then
# Failed to get own identity ... exit
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
>&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
exit 2
fi
else
echo -e " Caller Identity:"
$AWSCLI sts get-caller-identity --output table $PROFILE_OPT --region $REGION
if [[ 255 -eq $? ]]; then
# Failed to get own identity ... exit
echo variable $PROFILE_OPT
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
>&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
EXITCODE=2
exit $EXITCODE
fi
echo ""
fi
fi
}

View File

334
prowler2
View File

@@ -31,12 +31,15 @@ MODE="text"
SEP=','
KEEPCREDREPORT=0
EXITCODE=0
SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" )
TITLE_ID=""
TITLE_TEXT="CALLER ERROR - UNSET TITLE"
# Command usage menu
usage(){
echo "
USAGE:
`basename $0` -p <profile> -r <region> [ -h ]
`basename $0` [ -p <profile> -r <region> -h ]
Options:
-p <profile> specify your AWS profile to use (i.e.: default)
@@ -53,12 +56,13 @@ USAGE:
(i.e.: 1.01 instead of 1.1)
-l list all available checks only (does not perform any check)
-e exclude extras
-b do not print Prowler banner
-h this help
"
exit
}
while getopts ":hlkp:r:c:f:m:M:en" OPTION; do
while getopts ":hlkp:r:c:f:m:M:enb" OPTION; do
case $OPTION in
h )
usage
@@ -92,6 +96,9 @@ while getopts ":hlkp:r:c:f:m:M:en" OPTION; do
n )
NUMERAL=1
;;
b )
NOBANNER="true"
;;
e )
EXTRAS=1
;;
@@ -113,297 +120,14 @@ while getopts ":hlkp:r:c:f:m:M:en" OPTION; do
done
. include/colors
SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" )
# Functions to manage dates depending on OS
if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == "linux-musl" ]; then
TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX)
# function to compare in days, usage how_older_from_today date
# date format %Y-%m-%d
how_older_from_today()
{
DATE_TO_COMPARE=$1
TODAY_IN_DAYS=$(date -d "$(date +%Y-%m-%d)" +%s)
DATE_FROM_IN_DAYS=$(date -d $DATE_TO_COMPARE +%s)
DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24))
echo $DAYS_SINCE
}
# function to convert from timestamp to date, usage timestamp_to_date timestamp
# output date format %Y-%m-%d
timestamp_to_date()
{
# remove fractions of a second
TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".")
OUTPUT_DATE=$(date -d @$TIMESTAMP_TO_CONVERT +'%Y-%m-%d')
echo $OUTPUT_DATE
}
decode_report()
{
base64 -d
}
elif [[ "$OSTYPE" == "darwin"* ]]; then
# BSD/OSX commands compatibility
TEMP_REPORT_FILE=$(mktemp -t prowler.cred_report-XXXXXX)
how_older_from_today()
{
DATE_TO_COMPARE=$1
TODAY_IN_DAYS=$(date +%s)
DATE_FROM_IN_DAYS=$(date -jf %Y-%m-%d $DATE_TO_COMPARE +%s)
DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24))
echo $DAYS_SINCE
}
timestamp_to_date()
{
# remove fractions of a second
TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".")
OUTPUT_DATE=$(date -r $TIMESTAMP_TO_CONVERT +'%Y-%m-%d')
echo $OUTPUT_DATE
}
decode_report()
{
base64 -D
}
elif [[ "$OSTYPE" == "cygwin" ]]; then
# POSIX compatibility layer and Linux environment emulation for Windows
TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX)
how_older_from_today()
{
DATE_TO_COMPARE=$1
TODAY_IN_DAYS=$(date -d "$(date +%Y-%m-%d)" +%s)
DATE_FROM_IN_DAYS=$(date -d $DATE_TO_COMPARE +%s)
DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24))
echo $DAYS_SINCE
}
timestamp_to_date()
{
# remove fractions of a second
TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".")
OUTPUT_DATE=$(date -d @$TIMESTAMP_TO_CONVERT +'%Y-%m-%d')
echo $OUTPUT_DATE
}
decode_report()
{
base64 -d
}
else
echo "Unknown Operating System! Valid \$OSTYPE: linux-gnu, linux-musl, darwin* or cygwin"
echo "Found: $OSTYPE"
EXITCODE=1
exit $EXITCODE
fi
# It checks -p optoin first and use it as profile, if not -p provided then
# check environment variables and if not, it checks and loads credentials from
# instance profile (metadata server) if runs in an EC2 instance
if [[ $PROFILE ]]; then
PROFILE_OPT="--profile $PROFILE"
else
# if Prowler runs insinde an AWS instance with IAM instance profile attached
INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/)
if [[ $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')
fi
if [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then
PROFILE="ENV"
PROFILE_OPT=""
else
PROFILE="default"
PROFILE_OPT="--profile $PROFILE"
fi
fi
# AWS-CLI variables
AWSCLI=$(which aws)
if [ -z "${AWSCLI}" ]; then
echo -e "\n$RED ERROR!$NORMAL AWS-CLI (aws command) not found. Make sure it is installed correctly and in your \$PATH\n"
EXITCODE=1
exit $EXITCODE
fi
TITLE_ID=""
TITLE_TEXT="CALLER ERROR - UNSET TITLE"
## Output formatting functions
textOK(){
if [[ "$MODE" == "csv" ]]; then
if [[ $2 ]]; then
REPREGION=$2
else
REPREGION=$REGION
fi
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1"
else
echo " $OK OK! $NORMAL $1"
fi
}
textNotice(){
if [[ "$MODE" == "csv" ]]; then
if [[ $2 ]]; then
REPREGION=$2
else
REPREGION=$REGION
fi
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1"
else
echo " $NOTICE INFO! $1 $NORMAL"
fi
}
textWarn(){
EXITCODE=3
if [[ "$MODE" == "csv" ]]; then
if [[ $2 ]]; then
REPREGION=$2
else
REPREGION=$REGION
fi
echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1"
else
echo " $BAD WARNING! $1 $NORMAL"
fi
}
textTitle(){
TITLE_ID=$1
if [[ $NUMERAL ]]; then
TITLE_ID=$(echo $TITLE_ID | cut -d, -f2)
else
TITLE_ID=$(echo $TITLE_ID | cut -d, -f1)
fi
TITLE_TEXT=$2
case "$3" in
0|No|NOT_SCORED)
ITEM_SCORED="Not Scored"
;;
1|Yes|SCORED)
ITEM_SCORED="Scored"
;;
*)
ITEM_SCORED="Unspecified"
;;
esac
case "$4" in
LEVEL1) ITEM_LEVEL="Level 1";;
LEVEL2) ITEM_LEVEL="Level 2";;
EXTRA) ITEM_LEVEL="Extra";;
SUPPORT) ITEM_LEVEL="Support";;
*) ITEM_LEVEL="Unspecified or Invalid";;
esac
if [[ "$MODE" == "csv" ]]; then
>&2 echo "$TITLE_ID $TITLE_TEXT"
else
if [[ "$ITEM_SCORED" == "Scored" ]]; then
echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT"
else
echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL"
fi
fi
}
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"
}
prowlerBanner() {
echo -e "$CYAN _"
echo -e " _ __ _ __ _____ _| | ___ _ __"
echo -e " | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__|"
echo -e " | |_) | | | (_) \ V V /| | __/ |"
echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|"
echo -e " |_|$NORMAL$BLUE CIS based AWS Account Hardening Tool$NORMAL\n"
echo -e "$YELLOW Date: $(date)"
}
# Get whoami in AWS, who is the user running this shell script
getWhoami(){
ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Account" | tr -d '"')
if [[ "$MODE" == "csv" ]]; then
CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Arn")
if [[ 255 -eq $? ]]; then
# Failed to get own identity ... exit
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
>&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
EXITCODE=2
exit $EXITCODE
fi
CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"')
printCsvHeader
textTitle "0.0" "Show report generation info" "NOT_SCORED" "SUPPORT"
textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME"
else
echo ""
echo "This report is being generated using credentials below:"
echo ""
echo -e "AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS API Region: $NOTICE[$REGION]$NORMAL AWS Filter Region: $NOTICE[${FILTERREGION:-all}]$NORMAL\n"
if [[ $MONOCHROME -eq 1 ]]; then
echo "Caller Identity:"
$AWSCLI sts get-caller-identity --output text $PROFILE_OPT --region $REGION --query "Arn"
if [[ 255 -eq $? ]]; then
# Failed to get own identity ... exit
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
>&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
exit 2
fi
echo ""
else
echo "Caller Identity:"
$AWSCLI sts get-caller-identity --output table $PROFILE_OPT --region $REGION
if [[ 255 -eq $? ]]; then
# Failed to get own identity ... exit
echo variable $PROFILE_OPT
echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
>&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!"
EXITCODE=2
exit $EXITCODE
fi
echo ""
fi
fi
}
printColorsCode(){
if [[ $MONOCHROME -eq 0 ]]; then
echo -e "\nColors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL \n"
fi
}
# Generate Credential Report
genCredReport() {
textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT"
until $( $AWSCLI iam generate-credential-report --output text --query 'State' $PROFILE_OPT --region $REGION |grep -q -m 1 "COMPLETE") ; do
sleep 1
done
}
# Save report to a file, decode it, deletion at finish and after every single check
saveReport(){
$AWSCLI iam get-credential-report --query 'Content' --output text $PROFILE_OPT --region $REGION | decode_report > $TEMP_REPORT_FILE
if [[ $KEEPCREDREPORT -eq 1 ]]; then
textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT"
textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE"
fi
}
# Delete temporary report file
cleanTemp(){
if [[ $KEEPCREDREPORT -ne 1 ]]; then
rm -fr $TEMP_REPORT_FILE
fi
}
# Delete the temporary report file if we get interrupted/terminated
trap cleanTemp EXIT
. include/os_detector
. include/aws_profile_loader
. include/awscli_detector
. include/outputs
. include/csv_header
. include/banner
. include/whoami
. include/credentials_report
# Get a list of all available AWS Regions
REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \
@@ -412,17 +136,6 @@ REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \
--region $REGION \
--region-names $FILTERREGION)
infoReferenceLong(){
# Report review note:
echo -e ""
echo -e "For more information on the Prowler, feedback and issue reporting:"
echo -e "https://github.com/Alfresco/prowler"
echo -e ""
echo -e "For more information on the CIS benchmark:"
echo -e "https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf"
}
callCheck(){
if [[ $CHECKNUMBER ]];then
case "$CHECKNUMBER" in
@@ -436,20 +149,19 @@ callCheck(){
}
# List only check tittles
if [[ $PRINTCHECKSONLY == "1" ]]; then
prowlerBanner
show_all_titles
exit $EXITCODE
fi
# Include all of the groups of checks inside include folder
# Load all of the groups of checks inside groups folder named as "group*"
for group in $(ls groups/group*); do
. "$group"
done
# Include all of the checks inside include folder
# this includes also extra check since they are "check_extraNN"
# Load all of the checks inside checks folder named as "check*"
# this includes also extra checks since they are "check_extraNN"
for checks in $(ls checks/check*); do
. "$checks"
done
@@ -462,7 +174,7 @@ show_check_title() {
# Function to show the title of a group, by numeric id
show_group_title() {
# This would also just call textTitle in the real prowler
# when csv mode is used, no group tittle is shown
if [[ "$MODE" != "csv" ]]; then
textTitle "${GROUP_NUMBER[$1]}" "${GROUP_TITLE[$1]}" "NOT_SCORED" "SUPPORT"
fi
@@ -523,7 +235,7 @@ show_all_titles() {
### All functions defined above ... run the workflow
if [[ $MODE != "csv" ]]; then
if [[ $MODE != "csv" || $NOBANNER != "true" ]]; then
prowlerBanner
printColorsCode
fi
@@ -532,7 +244,7 @@ genCredReport
saveReport
callCheck
show_all_titles
execute_all
# if [[ ! $EXTRAS ]]; then