Add Elasticsearch checks issue #521

This commit is contained in:
Toni de la Fuente
2020-03-24 23:46:11 +01:00
parent 705d75606d
commit 568bba4c38
12 changed files with 313 additions and 14 deletions

View File

@@ -11,7 +11,7 @@
# CONDITIONS OF ANY KIND, either express or implied. See the License for the # CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License. # specific language governing permissions and limitations under the License.
CHECK_ID_extra716="7.16" CHECK_ID_extra716="7.16"
CHECK_TITLE_extra716="[extra716] Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark)" CHECK_TITLE_extra716="[extra716] Check if Elasticsearch Service domains are set as Public and have cross account access (Not Scored) (Not part of CIS benchmark)"
CHECK_SCORED_extra716="NOT_SCORED" CHECK_SCORED_extra716="NOT_SCORED"
CHECK_TYPE_extra716="EXTRA" CHECK_TYPE_extra716="EXTRA"
CHECK_ALTERNATE_check716="extra716" CHECK_ALTERNATE_check716="extra716"
@@ -22,19 +22,14 @@ extra716(){
LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text) LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
if [[ $LIST_OF_DOMAINS ]]; then if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do for domain in $LIST_OF_DOMAINS;do
CHECK_IF_MEMBER_OF_VPC=$($AWSCLI es describe-elasticsearch-domain-config --domain-name $domain $PROFILE_OPT --region $regx --query DomainConfig.VPCOptions.Options.VPCId --output text|grep -v ^None) TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-es-domain.policy.XXXXXXXXXX)
if [[ ! $CHECK_IF_MEMBER_OF_VPC ]];then $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
TEMP_POLICY_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-es-domain.policy.XXXXXXXXXX) # check if the policy has Principal as *
$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_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | jq -r '. | .Statement[] | select(.Effect == "Allow" and (((.Principal|type == "object") and .Principal.AWS == "*") or ((.Principal|type == "string") and .Principal == "*")) and .Condition == null)')
# check if the policy has Principal as * if [[ $CHECK_ES_DOMAIN_ALLUSERS_POLICY ]];then
CHECK_ES_DOMAIN_ALLUSERS_POLICY=$(cat $TEMP_POLICY_FILE | jq -r '. | .Statement[] | select(.Effect == "Allow" and (((.Principal|type == "object") and .Principal.AWS == "*") or ((.Principal|type == "string") and .Principal == "*")) and .Condition == null)') textFail "$regx: $domain policy allow Anonymous cross account access (Principal: \"*\")" "$regx"
if [[ $CHECK_ES_DOMAIN_ALLUSERS_POLICY ]];then
textFail "$regx: $domain policy \"may\" allow Anonymous users to perform actions (Principal: \"*\")" "$regx"
else
textPass "$regx: $domain is not open" "$regx"
fi
else else
textPass "$regx: $domain is in a VPC" "$regx" textPass "$regx: $domain does not allow Anonymous cross account access" "$regx"
fi fi
rm -f $TEMP_POLICY_FILE rm -f $TEMP_POLICY_FILE
done done

0
checks/check_extra777 Executable file → Normal file
View File

0
checks/check_extra778 Executable file → Normal file
View File

76
checks/check_extra779 Normal file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2019) 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_extra779="7.79"
CHECK_TITLE_extra779="[extra779] Ensure no security groups allow ingress from 0.0.0.0/0 or ::/0 to Elasticsearch/Kibana ports 9200/9300/5601 (Not Scored) (Not part of CIS benchmark)"
CHECK_SCORED_extra779="NOT_SCORED"
CHECK_TYPE_extra779="EXTRA"
CHECK_ALTERNATE_check779="extra779"
extra779(){
# if TEST_AUTHENTICATION has a value Prowler will try to access each ElasticSearch server to ports 9200/9300/5601
# from the host where Prowler is running and will try to read indices or get kibana status
TEST_ES_AUTHENTICATION=
for regx in $REGIONS; do
# crate a list of SG open to the world with port 9200 or 9300 or 5601
SG_LIST=$($AWSCLI ec2 describe-security-groups $PROFILE_OPT --region $regx --output text \
--query 'SecurityGroups[?length(IpPermissions[?((FromPort==null && ToPort==null) || (FromPort<=`9200` && ToPort>=`9200`) || (FromPort<=`9300` && ToPort>=`9300`)) || (FromPort<=`5601` && ToPort>=`5601 `) && (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
if [[ $SG_LIST ]];then
for sg in $SG_LIST;do
# temp file store the list of instances IDs and public IP address if found
TEMP_EXTRA779_FILE=$(mktemp -t prowler-${ACCOUNT_NUM}-es-domain.EXTRA779.XXXXXXXXXX)
# finds instances with that open security group attached and get its public ip address (if it has one)
$AWSCLI $PROFILE_OPT --region $regx ec2 describe-instances --filters Name=instance.group-id,Values=$sg --query 'Reservations[*].Instances[*].[InstanceId,PublicIpAddress]' --output text > $TEMP_EXTRA779_FILE
# in case of exposed instances it does access checks
if [[ -s "$TEMP_EXTRA779_FILE" ]];then
while read instance eip ; do
if [[ $TEST_ES_AUTHENTICATION ]];then
if [[ "$eip" != "None" ]];then
CHECH_AUTH_9200=$(curl -m 2 -s -X GET "http://$eip:9200/_cat/indices" | grep -v "not authorized" >/dev/null 2>&1 && echo "open" || echo "closed")
# timeout 1 bash -c '(echo > /dev/tcp/'$eip'/9300) >/dev/null 2>&1 && echo "open" || echo "closed"'
CHECH_AUTH_5601=$(curl -m 2 -s "http://$eip:5601/api/status" | jq .version.number | grep -v null >/dev/null 2>&1 && echo "open" || echo "closed")
if [[ $CHECH_AUTH_9200 -eq "closed" ]];then
textInfo "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Elasticsearch $CHECH_AUTH_9200" "$regx"
else
textFail "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Elasticsearch $CHECH_AUTH_9200" "$regx"
fi
if [[ $CHECH_AUTH_5601 -eq "closed" ]];then
textInfo "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Kibana $CHECH_AUTH_5601" "$regx"
else
textFail "$regx: Found instance $instance with public IP $eip on Security Group: $sg with Kibana $CHECH_AUTH_5601" "$regx"
fi
fi
else
if [[ "$eip" == "None" ]];then
textInfo "$regx: Found instance $instance with private IP on Security Group: $sg" "$regx"
else
textFail "$regx: Found instance $instance with public IP $eip on Security Group: $sg open to 0.0.0.0/0 on for Elasticsearch/Kibana ports" "$regx"
fi
fi
if [[ "$eip" == "None" ]];then
textInfo "$regx: Found instance $instance with private IP on Security Group: $sg" "$regx"
fi
# done < <(cat $TEMP_EXTRA779_FILE | grep -v None$)
done < <(cat $TEMP_EXTRA779_FILE)
# while read instance eip ; do
# textInfo "$regx: Found instance $instance with private IP on Security Group: $sg" "$regx"
# done < <(cat $TEMP_EXTRA779_FILE | grep None$)
fi
rm -rf $TEMP_EXTRA779_FILE
#textFail "$regx: Found Security Group: $sg open to 0.0.0.0/0 on for Elasticsearch ports" "$regx"
done
else
textPass "$regx: No Security Groups found open to 0.0.0.0/0 for Elasticsearch/Kibana ports" "$regx"
fi
done
}

35
checks/check_extra780 Normal file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) 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_extra780="7.80"
CHECK_TITLE_extra780="[extra780] Check if Elasticsearch Service domains has Cognito authentication for Kibana enabled (Not Scored) (Not part of CIS benchmark)"
CHECK_SCORED_extra780="NOT_SCORED"
CHECK_TYPE_extra780="EXTRA"
CHECK_ALTERNATE_check780="extra780"
extra780(){
for regx in $REGIONS; do
LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
CHECK_IF_COGNITO_ENABLED=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.CognitoOptions.Enabled' --output text|grep -i true)
if [[ $CHECK_IF_COGNITO_ENABLED ]];then
textPass "$regx: $domain has Cognito authentication for Kibana enabled" "$regx"
else
textFail "$regx: $domain does not have Cognito authentication for Kibana enabled" "$regx"
fi
done
else
textInfo "$regx: No Elasticsearch Service domains found" "$regx"
fi
done
}

35
checks/check_extra781 Normal file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) 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_extra781="7.81"
CHECK_TITLE_extra781="[extra781] Check if Elasticsearch Service domains has encryption at-rest enabled (Not Scored) (Not part of CIS benchmark)"
CHECK_SCORED_extra781="NOT_SCORED"
CHECK_TYPE_extra781="EXTRA"
CHECK_ALTERNATE_check781="extra781"
extra781(){
for regx in $REGIONS; do
LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
CHECK_IF_ENCREST_ENABLED=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.EncryptionAtRestOptions.Enabled' --output text|grep -i true)
if [[ $CHECK_IF_ENCREST_ENABLED ]];then
textPass "$regx: $domain has encryption at-rest enabled" "$regx"
else
textFail "$regx: $domain does not have encryption at-rest enabled" "$regx"
fi
done
else
textInfo "$regx: No Elasticsearch Service domains found" "$regx"
fi
done
}

35
checks/check_extra782 Normal file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) 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_extra782="7.82"
CHECK_TITLE_extra782="[extra782] Check if Elasticsearch Service domains has node-to-node encryption enabled (Not Scored) (Not part of CIS benchmark)"
CHECK_SCORED_extra782="NOT_SCORED"
CHECK_TYPE_extra782="EXTRA"
CHECK_ALTERNATE_check782="extra782"
extra782(){
for regx in $REGIONS; do
LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
CHECK_IF_NODETOENCR_ENABLED=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.NodeToNodeEncryptionOptions.Enabled' --output text|grep -i true)
if [[ $CHECK_IF_NODETOENCR_ENABLED ]];then
textPass "$regx: $domain has node-to-node encryption enabled" "$regx"
else
textFail "$regx: $domain does not have node-to-node encryption enabled" "$regx"
fi
done
else
textInfo "$regx: No Elasticsearch Service domains found" "$regx"
fi
done
}

35
checks/check_extra783 Normal file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) 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_extra783="7.83"
CHECK_TITLE_extra783="[extra783] Check if Elasticsearch Service domains has enforce HTTPS enabled (Not Scored) (Not part of CIS benchmark)"
CHECK_SCORED_extra783="NOT_SCORED"
CHECK_TYPE_extra783="EXTRA"
CHECK_ALTERNATE_check783="extra783"
extra783(){
for regx in $REGIONS; do
LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
CHECK_IF_ENFORCEHTTPS_ENABLED=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.DomainEndpointOptions.EnforceHTTPS' --output text|grep -i true)
if [[ $CHECK_IF_ENFORCEHTTPS_ENABLED ]];then
textPass "$regx: $domain has enforce HTTPS enabled" "$regx"
else
textFail "$regx: $domain does not have enforce HTTPS enabled" "$regx"
fi
done
else
textInfo "$regx: No Elasticsearch Service domains found" "$regx"
fi
done
}

35
checks/check_extra784 Normal file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) 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_extra784="7.84"
CHECK_TITLE_extra784="[extra784] Check if Elasticsearch Service domains internal user database enabled (Not Scored) (Not part of CIS benchmark)"
CHECK_SCORED_extra784="NOT_SCORED"
CHECK_TYPE_extra784="EXTRA"
CHECK_ALTERNATE_check784="extra784"
extra784(){
for regx in $REGIONS; do
LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
CHECK_IF_INTERNALDB_ENABLED=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.AdvancedSecurityOptions.InternalUserDatabaseEnabled' --output text|grep -i true)
if [[ $CHECK_IF_INTERNALDB_ENABLED ]];then
textPass "$regx: $domain has internal user database enabled" "$regx"
else
textFail "$regx: $domain does not have internal user database enabled" "$regx"
fi
done
else
textInfo "$regx: No Elasticsearch Service domains found" "$regx"
fi
done
}

35
checks/check_extra785 Normal file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) 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_extra785="7.85"
CHECK_TITLE_extra785="[extra785] Check if Elasticsearch Service domains have updates available (Not Scored) (Not part of CIS benchmark)"
CHECK_SCORED_extra785="NOT_SCORED"
CHECK_TYPE_extra785="EXTRA"
CHECK_ALTERNATE_check785="extra785"
extra785(){
for regx in $REGIONS; do
LIST_OF_DOMAINS=$($AWSCLI es list-domain-names $PROFILE_OPT --region $regx --query DomainNames --output text)
if [[ $LIST_OF_DOMAINS ]]; then
for domain in $LIST_OF_DOMAINS;do
CHECK_IF_UPDATE_AVAILABLE=$($AWSCLI es describe-elasticsearch-domain --domain-name $domain $PROFILE_OPT --region $regx --query 'DomainStatus.ServiceSoftwareOptions.UpdateAvailable' --output text|grep -i true)
if [[ $CHECK_IF_UPDATE_AVAILABLE ]];then
textInfo "$regx: $domain has updates available" "$regx"
else
textPass "$regx: $domain does not have have updates available" "$regx"
fi
done
else
textInfo "$regx: No Elasticsearch Service domains found" "$regx"
fi
done
}

View File

@@ -0,0 +1,18 @@
#!/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.
GROUP_ID[14]='elasticsearch'
GROUP_NUMBER[14]='14.0'
GROUP_TITLE[14]='Elasticsearch security checks - [elasticsearch] ***************'
GROUP_RUN_BY_DEFAULT[14]='N' # run it when execute_all is called
GROUP_CHECKS[14]='extra715,extra716,extra779,extra780,extra781,extra782,extra783,extra784,extra785'

View File

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