matteocorti / check_ssl_cert

A shell script (that can be used as a Nagios/Icinga plugin) to check an SSL/TLS connection.
GNU General Public License v3.0
360 stars 132 forks source link

NMAP cipher checks is not using SNI #505

Closed eLvErDe closed 4 months ago

eLvErDe commented 4 months ago

Describe the bug

If using SNI routing (yes this is possible), it is expected to have different SSL responses for the same IP address if provided server name is different.

However, this option is not propagated to NMAP when checking ciphers, leading to incorrect report.

To Reproduce

Not really reproducible unless you have such stup, but I can perform the test for your

Expected behavior

NMAP implemented proper option since release Nmap 7.40 [2016-12-20]:

o [NSE][GH#540] Add tls.servername script-arg for forcing a name to be used for
  TLS Server Name Indication extension. The argument overrides the default use
  of the host's targetname. [Bertrand Bonnefoy-Claudet]

Quick and dirty fix (on old version):

diff --git a/check_ssl_cert b/check_ssl_cert
index 935870f..57a427a 100755
--- a/check_ssl_cert
+++ b/check_ssl_cert
@@ -4504,9 +4504,13 @@ main() {

         # see https://github.com/matteocorti/check_ssl_cert/issues/378

-        debuglog "Executing ${NMAP_BIN} -Pn -p \"${PORT}\" \"${NMAP_INETPROTO}\" --script +ssl-enum-ciphers \"${HOST_ADDR}\" 2>&1 | grep '^|'"
-
-        OFFERED_PROTOCOLS=$(${NMAP_BIN} -Pn -p "${PORT}" "${NMAP_INETPROTO}" --script +ssl-enum-ciphers "${HOST_ADDR}" 2>&1 | grep '^|')
+        if [ -n ${SNI} ]; then  # https://github.com/matteocorti/check_ssl_cert/issues/505
+          debuglog "Executing ${NMAP_BIN} -Pn -p \"${PORT}\" \"${NMAP_INETPROTO}\" --script +ssl-enum-ciphers --script-args=tls.servername=\"${SNI}\" \"${HOST_ADDR}\" 2>&1 | grep '^|'"
+          OFFERED_PROTOCOLS=$(${NMAP_BIN} -Pn -p "${PORT}" "${NMAP_INETPROTO}" --script +ssl-enum-ciphers --script-args=tls.servername="${SNI}" "${HOST_ADDR}" 2>&1 | grep '^|')
+        else
+          debuglog "Executing ${NMAP_BIN} -Pn -p \"${PORT}\" \"${NMAP_INETPROTO}\" --script +ssl-enum-ciphers  \"${HOST_ADDR}\" 2>&1 | grep '^|'"
+          OFFERED_PROTOCOLS=$(${NMAP_BIN} -Pn -p "${PORT}" "${NMAP_INETPROTO}" --script +ssl-enum-ciphers "${HOST_ADDR}" 2>&1 | grep '^|')
+        fi

         debuglog "offered ciphers and protocols:"
         debuglog "${OFFERED_PROTOCOLS}" | sed 's/^|/[DBG] /'
@@ -5391,7 +5395,11 @@ EOF

         # -Pn is needed even if we specify a port
         TIMEOUT_REASON="checking ciphers"
-        exec_with_timeout "${NMAP_BIN} -Pn --script +ssl-enum-ciphers ${NMAP_INETPROTO} ${HOST_ADDR} -p ${PORT}" "${NMAP_OUT}" "${NMAP_ERR}"
+        if [ -n ${SNI} ]; then
+          exec_with_timeout "${NMAP_BIN} -Pn --script +ssl-enum-ciphers ${NMAP_INETPROTO} --script-args=tls.servername="${SNI}" ${HOST_ADDR} -p ${PORT}" "${NMAP_OUT}" "${NMAP_ERR}"
+        else
+          exec_with_timeout "${NMAP_BIN} -Pn --script +ssl-enum-ciphers ${NMAP_INETPROTO} ${HOST_ADDR} -p ${PORT}" "${NMAP_OUT}" "${NMAP_ERR}"
+        fi

         if [ "${DEBUG}" -ge 1 ]; then
             debuglog 'nmap output:'

System (please complete the following information):

Not relevant

matteocorti commented 4 months ago

Thanks, I never thought about this and didn't think about the possibility to have different setting for different names. But you are right it could be possible.

I'll try to integrate the fix (maybe with a check on the nmap version to see if the option is there)

matteocorti commented 4 months ago

Seems that nmap doesn't care if a script-arg does not exist (no errors or warnings)