mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
Add CHECK_ASFF_RESOURCE_TYPE variables for recently added checks
This commit is contained in:
@@ -14,30 +14,31 @@ CHECK_ID_extra786="7.86"
|
||||
CHECK_TITLE_extra786="[extra786] Check if EC2 Instance Metadata Service Version 2 (IMDSv2) is Enabled and Required (Not Scored) (Not part of CIS benchmark)"
|
||||
CHECK_SCORED_extra786="NOT_SCORED"
|
||||
CHECK_TYPE_extra786="EXTRA"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra786="AwsEc2Instance"
|
||||
CHECK_ALTERNATE_check786="extra786"
|
||||
|
||||
extra786(){
|
||||
for regx in $REGIONS; do
|
||||
for regx in $REGIONS; do
|
||||
TEMP_EXTRA786_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-es-domain.EXTRA786.XXXXXXXXXX)
|
||||
$AWSCLI ec2 describe-instances $PROFILE_OPT --region $regx \
|
||||
--query 'Reservations[*].Instances[*].{HttpTokens:MetadataOptions.HttpTokens,HttpEndpoint:MetadataOptions.HttpEndpoint,InstanceId:InstanceId}' \
|
||||
--output text --max-items $MAXITEMS > $TEMP_EXTRA786_FILE
|
||||
# if the file contains data, there are instances in that region
|
||||
# if the file contains data, there are instances in that region
|
||||
if [[ -s "$TEMP_EXTRA786_FILE" ]];then
|
||||
# here we read content from the file fields instanceid httptokens_status httpendpoint
|
||||
while read httpendpoint httptokens_status instanceid ; do
|
||||
while read httpendpoint httptokens_status instanceid ; do
|
||||
#echo i:$instanceid tok:$httptokens_status end:$httpendpoint
|
||||
if [[ "$httpendpoint" == "enabled" && "$httptokens_status" == "required" ]];then
|
||||
textPass "$regx: EC2 Instance $instanceid has IMDSv2 enabled and required" "$regx"
|
||||
elif [[ "$httpendpoint" == "disabled" ]];then
|
||||
elif [[ "$httpendpoint" == "disabled" ]];then
|
||||
textInfo "$regx: EC2 Instance $instanceid has HTTP endpoint access to metadata service disabled" "$regx"
|
||||
else
|
||||
textFail "$regx: EC2 Instance $instanceid has IMDSv2 disabled or not required" "$regx"
|
||||
fi
|
||||
fi
|
||||
done < <(cat $TEMP_EXTRA786_FILE)
|
||||
else
|
||||
else
|
||||
textInfo "$regx: no EC2 Instances found" "$regx"
|
||||
fi
|
||||
fi
|
||||
rm -fr $TEMP_EXTRA786_FILE
|
||||
done
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@
|
||||
# specific language governing permissions and limitations under the License.
|
||||
CHECK_ID_extra787="7.87"
|
||||
CHECK_TITLE_extra787="[extra787] Check connection and authentication for Internet exposed Elasticsearch/Kibana ports"
|
||||
CHECK_SCORED_extra787="NOT_SCORED"
|
||||
CHECK_SCORED_extra787="NOT_SCORED"
|
||||
CHECK_TYPE_extra787="EXTRA"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra787="AwsEc2Instance"
|
||||
CHECK_ALTERNATE_check787="extra787"
|
||||
|
||||
extra787(){
|
||||
@@ -25,7 +26,7 @@ extra787(){
|
||||
ES_KIBANA_PORT="5601"
|
||||
|
||||
for regx in $REGIONS; do
|
||||
# crate a list of SG open to the world with port $ES_API_PORT or $ES_DATA_PORT or $ES_KIBANA_PORT
|
||||
# create a list of SG open to the world with port $ES_API_PORT or $ES_DATA_PORT or $ES_KIBANA_PORT
|
||||
SG_LIST=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --output text \
|
||||
--query "SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=\`$ES_API_PORT\` && ToPort>=\`$ES_API_PORT\`) || (FromPort<=\`$ES_DATA_PORT\` && ToPort>=\`$ES_DATA_PORT\`) || (FromPort<=\`$ES_KIBANA_PORT\` && ToPort>=\`$ES_KIBANA_PORT\`)) && (contains(IpRanges[].CidrIp, \`0.0.0.0/0\`) || contains(Ipv6Ranges[].CidrIpv6, \`::/0\`))]) > \`0\`].{GroupId:GroupId}")
|
||||
# in case of open security groups goes through each one
|
||||
@@ -37,28 +38,28 @@ extra787(){
|
||||
$AWSCLI $PROFILE_OPT --region $regx ec2 describe-instances --filters Name=instance.group-id,Values=$sg --query 'Reservations[*].Instances[*].[InstanceId,PublicIpAddress]' --output text > $TEMP_EXTRA787_FILE
|
||||
# in case of exposed instances it does access checks
|
||||
if [[ -s "$TEMP_EXTRA787_FILE" ]];then
|
||||
while read instance eip ; do
|
||||
if [[ "$eip" != "None" ]];then
|
||||
while read instance eip ; do
|
||||
if [[ "$eip" != "None" ]];then
|
||||
# check for Elasticsearch on port $ES_API_PORT, rest API HTTP.
|
||||
CHECH_HTTP_ES_API=$(curl -m 2 -s -w "%{http_code}" -o /dev/null -X GET "http://$eip:$ES_API_PORT/_cat/indices")
|
||||
httpStatus $CHECH_HTTP_ES_API
|
||||
if [[ $CHECH_HTTP_ES_API -eq "200" ]];then
|
||||
if [[ $CHECH_HTTP_ES_API -eq "200" ]];then
|
||||
textFail "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Elasticsearch port $ES_API_PORT response $SERVER_RESPONSE" "$regx"
|
||||
else
|
||||
textInfo "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Elasticsearch port $ES_API_PORT response $SERVER_RESPONSE" "$regx"
|
||||
fi
|
||||
# check for port $ES_DATA_PORT TCP, this is the communication port, not:
|
||||
# test_tcp_connectivity is in include/os_detector
|
||||
# test_tcp_connectivity is in include/os_detector
|
||||
# syntax is 'test_tcp_connectivity $HOST $PORT $TIMEOUT' (in seconds)
|
||||
CHECH_HTTP_ES_DATA=$(test_tcp_connectivity $eip $ES_DATA_PORT 2)
|
||||
# Using HTTP error codes here as well to reuse httpStatus function
|
||||
# Using HTTP error codes here as well to reuse httpStatus function
|
||||
# codes for better handling, so 200 is open and 000 is not responding
|
||||
httpStatus $CHECH_HTTP_ES_DATA
|
||||
if [[ $CHECH_HTTP_ES_DATA -eq "200" ]];then
|
||||
textFail "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Elasticsearch port $ES_DATA_PORT response $SERVER_RESPONSE" "$regx"
|
||||
else
|
||||
textInfo "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Elasticsearch port $ES_DATA_PORT response $SERVER_RESPONSE" "$regx"
|
||||
fi
|
||||
fi
|
||||
# check for Kibana on port $ES_KIBANA_PORT
|
||||
CHECH_HTTP_ES_KIBANA=$(curl -m 2 -s -w "%{http_code}" -o /dev/null -X GET "http://$eip:$ES_KIBANA_PORT/api/status")
|
||||
httpStatus $CHECH_HTTP_ES_KIBANA
|
||||
@@ -66,13 +67,13 @@ extra787(){
|
||||
textFail "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Kibana on port $ES_KIBANA_PORT response $SERVER_RESPONSE" "$regx"
|
||||
else
|
||||
textInfo "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Kibana on port $ES_KIBANA_PORT response $SERVER_RESPONSE" "$regx"
|
||||
fi
|
||||
else
|
||||
fi
|
||||
else
|
||||
textInfo "$regx: Found instance $instance with private IP on Security Group: $sg" "$regx"
|
||||
fi
|
||||
fi
|
||||
done < <(cat $TEMP_EXTRA787_FILE)
|
||||
fi
|
||||
rm -rf $TEMP_EXTRA787_FILE
|
||||
fi
|
||||
rm -rf $TEMP_EXTRA787_FILE
|
||||
done
|
||||
else
|
||||
textPass "$regx: No Security Groups found open to 0.0.0.0/0 for Elasticsearch/Kibana ports" "$regx"
|
||||
|
||||
@@ -14,6 +14,7 @@ CHECK_ID_extra788="7.88"
|
||||
CHECK_TITLE_extra788="[extra788] Check connection and authentication for Internet exposed Amazon Elasticsearch Service (ES) domains"
|
||||
CHECK_SCORED_extra788="NOT_SCORED"
|
||||
CHECK_TYPE_extra788="EXTRA"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra788="AwsElasticsearchDomain"
|
||||
CHECK_ALTERNATE_check788="extra788"
|
||||
|
||||
extra788(){
|
||||
@@ -31,8 +32,8 @@ extra788(){
|
||||
# If the endpoint starts with "vpc-" it is in a VPC then it is fine.
|
||||
if [[ "$ES_DOMAIN_ENDPOINT" =~ ^vpc-* ]];then
|
||||
ES_DOMAIN_VPC=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.VPCOptions.VPCId' --output text)
|
||||
textInfo "$regx: Amazon ES domain $domain is in VPC $ES_DOMAIN_VPC run extra779 to make sure it is not exposed using custom proxy" "$regx"
|
||||
else
|
||||
textInfo "$regx: Amazon ES domain $domain is in VPC $ES_DOMAIN_VPC run extra779 to make sure it is not exposed using custom proxy" "$regx"
|
||||
else
|
||||
$AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.AccessPolicies.Options --output text > $TEMP_POLICY_FILE 2> /dev/null
|
||||
CHECK_ES_DOMAIN_POLICY_OPEN=$(cat $TEMP_POLICY_FILE | jq -r '. | .Statement[] | select(.Effect == "Allow" and (((.Principal|type == "object") and .Principal.AWS == "*") or ((.Principal|type == "string") and .Principal == "*")) and select(has("Condition") | not))')
|
||||
CHECK_ES_DOMAIN_POLICY_HAS_CONDITION=$(cat $TEMP_POLICY_FILE | jq -r '. | .Statement[] | select(.Effect == "Allow" and (((.Principal|type == "object") and .Principal.AWS == "*") or ((.Principal|type == "string") and .Principal == "*")) and select(has("Condition")))' )
|
||||
@@ -43,29 +44,29 @@ extra788(){
|
||||
CONDITION_HAS_PRIVATE_IP=$(echo "${condition_ip}" | grep -E '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.)')
|
||||
if [[ $CONDITION_HAS_PRIVATE_IP ]];then
|
||||
CONDITION_HAS_PRIVATE_IP_ARRAY+=($condition_ip)
|
||||
fi
|
||||
fi
|
||||
CONDITION_HAS_PUBLIC_IP=$(echo "${condition_ip}" | grep -vE '^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|0\.0\.0\.0|\*)')
|
||||
if [[ $CONDITION_HAS_PUBLIC_IP ]];then
|
||||
CONDITION_HAS_PUBLIC_IP_ARRAY+=($condition_ip)
|
||||
fi
|
||||
CONDITION_HAS_ZERO_NET=$(echo "${condition_ip}" | grep -E '^(0\.0\.0\.0)')
|
||||
CONDITION_HAS_STAR=$(echo "${condition_ip}" | grep -E '^\*')
|
||||
done
|
||||
done
|
||||
CHECK_ES_DOMAIN_POLICY_CONDITION_PRIVATE_IP=${CONDITION_HAS_PRIVATE_IP_ARRAY[@]}
|
||||
CHECK_ES_DOMAIN_POLICY_CONDITION_PUBLIC_IP=${CONDITION_HAS_PUBLIC_IP_ARRAY[@]}
|
||||
CHECK_ES_DOMAIN_POLICY_CONDITION_ZERO=$CONDITION_HAS_ZERO_NET
|
||||
CHECK_ES_DOMAIN_POLICY_CONDITION_STAR=$CONDITION_HAS_STAR
|
||||
fi
|
||||
fi
|
||||
if [[ $CHECK_ES_DOMAIN_POLICY_OPEN || $CHECK_ES_DOMAIN_POLICY_CONDITION_ZERO || $CHECK_ES_DOMAIN_POLICY_CONDITION_STAR || ${CHECK_ES_DOMAIN_POLICY_CONDITION_PUBLIC_IP[@]} ]];then
|
||||
#Prowler will check to read indices or kibaba status if no conditions, condition IP is *, 0.0.0.0/0, 0.0.0.0/8 or any public IP.
|
||||
# check for REST API on port 443
|
||||
CHECH_ES_HTTPS=$(curl -m 2 -s -w "%{http_code}" -o /dev/null -X GET "https://$ES_DOMAIN_ENDPOINT/_cat/indices")
|
||||
httpStatus $CHECH_ES_HTTPS
|
||||
if [[ $CHECH_ES_HTTPS -eq "200" ]];then
|
||||
if [[ $CHECH_ES_HTTPS -eq "200" ]];then
|
||||
textFail "$regx: Amazon ES domain $domain policy allows Anonymous access and ES service endpoint $ES_DOMAIN_ENDPOINT responded $SERVER_RESPONSE" "$regx"
|
||||
else
|
||||
textInfo "$regx: Amazon ES domain $domain policy allows Anonymous access but ES service endpoint $ES_DOMAIN_ENDPOINT responded $SERVER_RESPONSE" "$regx"
|
||||
fi
|
||||
fi
|
||||
# check for Kibana on port 443
|
||||
CHECH_KIBANA_HTTPS=$(curl -m 2 -s -w "%{http_code}" -o /dev/null -X GET "https://$ES_DOMAIN_ENDPOINT/_plugin/kibana/api/status")
|
||||
httpStatus $CHECH_KIBANA_HTTPS
|
||||
@@ -73,13 +74,13 @@ extra788(){
|
||||
textFail "$regx: Amazon ES domain $domain policy allows Anonymous access and Kibana service endpoint $ES_DOMAIN_ENDPOINT responded $SERVER_RESPONSE" "$regx"
|
||||
else
|
||||
textInfo "$regx: Amazon ES domain $domain policy allows Anonymous access but Kibana service endpoint $ES_DOMAIN_ENDPOINT responded $SERVER_RESPONSE" "$regx"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if [[ $CHECK_ES_DOMAIN_POLICY_HAS_CONDITION && ${CHECK_ES_DOMAIN_POLICY_CONDITION_PRIVATE_IP[@]} ]];then
|
||||
textInfo "$regx: Amazon ES domain $domain policy allows access from a Private IP or CIDR RFC1918 $(echo ${CONDITION_HAS_PRIVATE_IP_ARRAY[@]})" "$regx"
|
||||
else
|
||||
textPass "$regx: Amazon ES domain $domain does not allow Anonymous cross account access" "$regx"
|
||||
fi
|
||||
else
|
||||
textPass "$regx: Amazon ES domain $domain does not allow Anonymous cross account access" "$regx"
|
||||
fi
|
||||
fi
|
||||
rm -f $TEMP_POLICY_FILE
|
||||
fi
|
||||
@@ -88,4 +89,4 @@ extra788(){
|
||||
textInfo "$regx: No Amazon ES domain found" "$regx"
|
||||
fi
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,12 @@ CHECK_ID_extra789="7.89"
|
||||
CHECK_TITLE_extra789="[extra789] Find trust boundaries in VPC endpoint services connections"
|
||||
CHECK_SCORED_extra789="NOT_SCORED"
|
||||
CHECK_TYPE_extra789="EXTRA"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra789="AwsEc2Vpc"
|
||||
CHECK_ALTERNATE_extra789="extra789"
|
||||
|
||||
extra789(){
|
||||
TRUSTED_ACCOUNT_IDS=$( echo "${ACCOUNT_NUM} ${GROUP_TRUSTBOUNDARIES_TRUSTED_ACCOUNT_IDS}" | xargs )
|
||||
|
||||
|
||||
for regx in ${REGIONS}; do
|
||||
ENDPOINT_SERVICES_IDS=$(${AWSCLI} ec2 describe-vpc-endpoint-services \
|
||||
${PROFILE_OPT} \
|
||||
@@ -29,19 +30,19 @@ extra789(){
|
||||
)
|
||||
|
||||
for ENDPOINT_SERVICE_ID in ${ENDPOINT_SERVICES_IDS}; do
|
||||
|
||||
|
||||
ENDPOINT_CONNECTION_LIST=$(${AWSCLI} ec2 describe-vpc-endpoint-connections \
|
||||
${PROFILE_OPT} \
|
||||
--query "VpcEndpointConnections[?VpcEndpointState=='available'].VpcEndpointOwner" \
|
||||
--region ${regx} \
|
||||
--output text | xargs
|
||||
)
|
||||
|
||||
|
||||
for ENDPOINT_CONNECTION in ${ENDPOINT_CONNECTION_LIST}; do
|
||||
for ACCOUNT_ID in ${TRUSTED_ACCOUNT_IDS}; do
|
||||
if [[ "${ACCOUNT_ID}" == "${ENDPOINT_CONNECTION}" ]]; then
|
||||
textPass "${regx}: Found trusted account in VPC endpoint service connection ${ENDPOINT_CONNECTION}" "${regx}"
|
||||
# Algorithm:
|
||||
# Algorithm:
|
||||
# Remove all trusted ACCOUNT_IDs from ENDPOINT_CONNECTION_LIST.
|
||||
# As a result, the ENDPOINT_CONNECTION_LIST finally contains only unknown/untrusted account ids.
|
||||
ENDPOINT_CONNECTION_LIST=("${ENDPOINT_CONNECTION_LIST[@]/$ENDPOINT_CONNECTION}") # remove hit from whitelist
|
||||
@@ -52,6 +53,6 @@ extra789(){
|
||||
for UNTRUSTED_CONNECTION in ${ENDPOINT_CONNECTION_LIST}; do
|
||||
textFail "${regx}: Found untrusted account in VPC endpoint service connection ${UNTRUSTED_CONNECTION}" "${regx}"
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ CHECK_ID_extra790="7.90"
|
||||
CHECK_TITLE_extra790="[extra790] Find trust boundaries in VPC endpoint services whitelisted principles"
|
||||
CHECK_SCORED_extra790="NOT_SCORED"
|
||||
CHECK_TYPE_extra790="EXTRA"
|
||||
CHECK_ASFF_RESOURCE_TYPE_extra790="AwsEc2Vpc"
|
||||
CHECK_ALTERNATE_extra790="extra790"
|
||||
|
||||
extra790(){
|
||||
@@ -40,14 +41,14 @@ extra790(){
|
||||
for ENDPOINT_PERMISSION in ${ENDPOINT_PERMISSIONS_LIST}; do
|
||||
# Take only account id from ENDPOINT_PERMISSION: arn:aws:iam::965406151242:root
|
||||
ENDPOINT_PERMISSION_ACCOUNT_ID=$(echo ${ENDPOINT_PERMISSION} | cut -d':' -f5 | xargs)
|
||||
|
||||
|
||||
for ACCOUNT_ID in ${TRUSTED_ACCOUNT_IDS}; do
|
||||
if [[ "${ACCOUNT_ID}" == "${ENDPOINT_PERMISSION_ACCOUNT_ID}" ]]; then
|
||||
textPass "${regx}: Found trusted account in VPC endpoint service permission ${ENDPOINT_PERMISSION}" "${regx}"
|
||||
# Algorithm:
|
||||
# Algorithm:
|
||||
# Remove all trusted ACCOUNT_IDs from ENDPOINT_PERMISSIONS_LIST.
|
||||
# As a result, the ENDPOINT_PERMISSIONS_LIST finally contains only unknown/untrusted account ids.
|
||||
ENDPOINT_PERMISSIONS_LIST=("${ENDPOINT_PERMISSIONS_LIST[@]/$ENDPOINT_PERMISSION}")
|
||||
ENDPOINT_PERMISSIONS_LIST=("${ENDPOINT_PERMISSIONS_LIST[@]/$ENDPOINT_PERMISSION}")
|
||||
fi
|
||||
done
|
||||
done
|
||||
@@ -55,6 +56,6 @@ extra790(){
|
||||
for UNTRUSTED_PERMISSION in ${ENDPOINT_PERMISSIONS_LIST}; do
|
||||
textFail "${regx}: Found untrusted account in VPC endpoint service permission ${UNTRUSTED_PERMISSION}" "${regx}"
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user