Difference between revisions of "SSL testing"
m |
|||
(One intermediate revision by the same user not shown) | |||
Line 1: | Line 1: | ||
[[Category:Engineering]] | [[Category:Engineering]] | ||
+ | __FORCETOC__ | ||
The '''sslscan''' tool is useful. Openssl can also be used. | The '''sslscan''' tool is useful. Openssl can also be used. | ||
Line 141: | Line 142: | ||
</pre> | </pre> | ||
− | == SSL Testing | + | == SSL Testing Scripts == |
+ | |||
+ | This checks that the SSL certificate is valid and has no problems. | ||
+ | <pre> | ||
+ | #!/bin/sh | ||
+ | # FIXME: This does not handle star certs (*.example.com). | ||
+ | # if echo "${CERT_SUBJECT_CN}" | grep -q -v "*"; then | ||
+ | ###################################################################### | ||
+ | # | ||
+ | # This checks SSL certificates for problems. | ||
+ | # | ||
+ | # SYNOPSIS | ||
+ | # | ||
+ | # check_ssl_cert HOSTNAME | ||
+ | # | ||
+ | # DESCRIPTION | ||
+ | # | ||
+ | # This checks SSL certificates for problems. | ||
+ | # | ||
+ | # EXAMPLES | ||
+ | # | ||
+ | # check_ssl_cert hostname.example.com | ||
+ | # | ||
+ | # EXIT STATUS | ||
+ | # | ||
+ | # This exits with status 0 on success or non-zero on error. | ||
+ | # | ||
+ | # AUTHOR | ||
+ | # | ||
+ | # Noah Spurrier noah@noah.org | ||
+ | # | ||
+ | # LICENSE | ||
+ | # | ||
+ | # This license is OSI and FSF approved as GPL-compatible. | ||
+ | # This license identical to the ISC License and is registered with and | ||
+ | # approved by the Open Source Initiative. For more information vist: | ||
+ | # http://opensource.org/licenses/isc-license.txt | ||
+ | # | ||
+ | # Copyright (c) 2014, Noah Spurrier | ||
+ | # | ||
+ | # Permission to use, copy, modify, and/or distribute this software for any | ||
+ | # purpose with or without fee is hereby granted, provided that the above | ||
+ | # copyright notice and this permission notice appear in all copies. | ||
+ | # | ||
+ | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
+ | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
+ | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
+ | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
+ | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
+ | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
+ | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
+ | # | ||
+ | # | ||
+ | # VERSION | ||
+ | # | ||
+ | # Version 1 | ||
+ | # | ||
+ | ###################################################################### | ||
+ | |||
+ | SSL_HOSTNAME=$1 | ||
+ | |||
+ | NOW=$(date "+%s") | ||
+ | CERT_INFO=$(openssl s_client -connect ${SSL_HOSTNAME}:443 </dev/null 2>/dev/null | openssl x509 -text -noout) | ||
+ | CERT_EXPIRATION_DATE=$(echo "${CERT_INFO}" | sed -n 's/.*Not After.*: \(.*\)/\1/p') | ||
+ | CERT_EXPIRATION_SECONDS=$(date '+%s' --date "${CERT_EXPIRATION_DATE}") | ||
+ | CERT_EXPIRATION_DAYS=$(( ( $CERT_EXPIRATION_SECONDS - ${NOW} ) / 60 / 60 / 24)) | ||
+ | CERT_ISSUER=$(echo "${CERT_INFO}" | sed -n 's/.*Issuer.*: \(.*\)/\1/p') | ||
+ | CERT_ISSUER_CN=$(echo "${CERT_INFO}" | sed -n 's/.*Issuer.*:.*CN=\(.*\)/\1/p') | ||
+ | CERT_SUBJECT=$(echo "${CERT_INFO}" | sed -n 's/.*Subject.*: \(.*\)/\1/p') | ||
+ | CERT_SUBJECT_CN=$(echo "${CERT_INFO}" | sed -n 's/.*Subject.*:.*CN=\(.*\)/\1/p') | ||
+ | |||
+ | if [ "${CERT_SUBJECT_CN}" != "${SSL_HOSTNAME}" ]; then | ||
+ | # Ignore star certs. They match everything. | ||
+ | # FIXME I should at least check that the domain names are the same. | ||
+ | if ! printf '%s' "${CERT_SUBJECT_CN}" | egrep -q '\*'; then | ||
+ | echo "ERROR: SSL hostname does not match Subject CN in the cert." >&2 | ||
+ | echo "SSL_HOSTNAME: ${SSL_HOSTNAME}" >&2 | ||
+ | echo "CERT_SUBJECT_CN: ${CERT_SUBJECT_CN}" >&2 | ||
+ | exit 1 | ||
+ | fi | ||
+ | fi | ||
+ | |||
+ | if [ ${CERT_EXPIRATION_DAYS} -lt 0 ]; then | ||
+ | echo "ERROR: Certificate has expired." >&2 | ||
+ | echo "CERT_EXPIRATION_DATE: ${CERT_EXPIRATION_DATE}" >&2 | ||
+ | exit 1 | ||
+ | fi | ||
+ | ##################################################################### | ||
+ | # END | ||
+ | #########1#########2#########3#########4#########5#########6#########7 | ||
+ | #j | ||
+ | # __________________ _-_ | ||
+ | # \___=NCC-1701= __)) ____.---'---`---.____ | ||
+ | # \_ \ \----._________.----' | ||
+ | # \ \ / / `-_-' | ||
+ | # __,--`-`---'-'-. | ||
+ | # /}___ )(- | ||
+ | # `--.____,-' | ||
+ | # | ||
+ | # vim: set ft=sh sr et ts=4 sw=4 : See help 'modeline' | ||
+ | </pre> | ||
This show the default cipher used to connect to a remote host and it lists all the client ciphers that the remote host supports. | This show the default cipher used to connect to a remote host and it lists all the client ciphers that the remote host supports. | ||
− | |||
<pre> | <pre> | ||
#!/bin/bash | #!/bin/bash |
Latest revision as of 09:02, 21 July 2017
The sslscan tool is useful. Openssl can also be used.
Contents
openssl
This starts an interactive connection with a service sitting behind an SSL/TLS layer. The following command will connect to a remote HTTPS client and establish a connection. After you enter this command it will print some output and then wait for your input. It works more or less like telnet at this point. One of the more interesting lines to look for is the cipher: line, which shows the cipher algorithm that was negotiated and in use.
openssl s_client -showcerts -connect www.example.com:443
You can check if a specific cipher is allowed. The cipher: line should show that the given cipher is in use.
openssl s_client -showcerts -connect www.example.com:443 -cipher RC4
It's a bit like testing an unsecure HTTP server with telnet. Now you can type in manual requests. Remember, you have to enter two line feeds after the GET request. Note that some servers require the host: header, some do not. If you get an HTTP 400 Bad Request then you probably need to add the host: header.
GET / HTTP/1.1 host: www.example.com
A full test session might look like the following. In this example a redirect is returned as a response to GET / HTTP/1.1.
CONNECTED(00000003) depth=0 C = US, ST = California, O = "Exemplar, Inc.", OU = IT Department, CN = www.example.com, emailAddress = itteam@example.com verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 C = US, ST = California, O = "Exemplar, Inc.", OU = IT Department, CN = www.example.com, emailAddress = itteam@example.com verify error:num=27:certificate not trusted verify return:1 depth=0 C = US, ST = California, O = "Exemplar, Inc.", OU = IT Department, CN = www.example.com, emailAddress = itteam@example.com verify error:num=21:unable to verify the first certificate verify return:1 --- Certificate chain 0 s:/C=US/ST=California/O=Exemplar, Inc./OU=IT Department/CN=www.example.com/emailAddress=itteam@example.com i:/C=US/ST=California/L=San Francisco/O=Exemplar, Inc./OU=IT Department/CN=lb_test_root_CA_1/emailAddress=itteam@example.com --- Server certificate -----BEGIN CERTIFICATE----- MIIGRTCCBC2gAwIBAgICAVIwDQYJKoZIhvcNAQEFBQAwgbExCzAJBgNVBAYTAlVT MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRow GAYDVQQKExFTcXVhcmVUcmFkZSwgSW5jLjEWMBQGA1UECxMNSVQgRGVwYXJ0bWVu dDEaMBgGA1UEAxQRbGJfdGVzdF9yb290X0NBXzExJTAjBgkqhkiG9w0BCQEWFml0 dGVhbUBzcXVhcmV0cmFkZS5jb29wHhcNMTIwOTEzMjMzMTIwWhcNMTUwNjEwMjMz MTIwWjCBpDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExGjAYBgNV BAoMEVNxdWFyZVRyYWRlLCBJbmMuMRYwFAYDVQQLDA1JVCBEZXBhcnRtZW50MSUw IwYDVQQDDBx3d3ctbXVoYW1tYWQuc3F1YXJldHJhZGUuY29tMSUwIwYJKoZIhvcN AQkBFhZpdHRlYW1Ac3F1YXJldHJhZGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEApFz500fjWy0DfAvqm+H+Ol8sOp4ip12C5PZDh+CRVoAGGYvl tStfMojTeDSluAr5s49qdypjb3rOgL43NNATMBvNq8tS8XhTdnq+wd4WDTPe5TPL wE1Q67NVeEfFi33Zjt8VvcuPZSMU/JKL/7z96AxFdOFkYctPC6xGYAqywTZywT8+ Xshd3AILV5b4JqPzTjxSJZxRFDuWjp0gCHX/ATFIuoBoLoAdBISr/RAjn9qWxS+h 3xGH24SHLc5Js1oXu1Vlgnu9SLTYW14QmTYpNHByRUdWIPkrpAITCqjaUWUB7KJO 82aNCw+6LtF3UX6/t9hQmid9XWXHQTu+P/O05wIDAQABo4IBcDCCAWwwCQYDVR0T BAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgXgMBMGA1UdJQQMMAoG CCsGAQUFBwMBMDgGCWCGSAGG+EIBDQQrFilTcXVhcmVUcmFkZSAtIFdhcnJhbnRp ZXMgdGhhdCBtYWtlIHNlbnNlITAdBgNVHQ4EFgQUR9nBJsa0o9mYhWB54zX98vU7 HR0wgdAGA1UdIwSByDCBxaGBt6SBtDCBsTELMAkGA1UEBhMCVVMxEzARBgNVBAgT CkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xGjAYBgNVBAoTEVNx dWFyZVRyYWRlLCBJbmMuMRYwFAYDVQQLEw1JVCBEZXBhcnRtZW50MRowGAYDVQQD FBFsYl90ZXN0X3Jvb3RfQ0FfMTElMCMGCSqGSIb3DQEJARYWaXR0ZWFtQHNxdWFy ZXRyYWRlLmNvbYIJAOkVdZRJpqb+MA0GCSqGSIb3DQEBBQUAA4ICAQAphQ/SF3EP 8MS7hB1Cm2ntV9HUZD3DdLVIEBpujZhty9GsqPSExRGeU+uDnWYF8j+z7ZbhYHjd VcVfxszHn9VzX2HyQm9kFs2dry3qGJgILVmlvWcVYpuAdpgnpe6BxwW7gdGOIpwi OAKytVQLGsWsf/IbVjWnx3JQsb86XRodF3HGQNrb5Xzdez6dD4GaAVWHnZjqaPlS REHLS5iRz7Q8ZqtPGqqy/GPUEpT2kppJeqUprzcUByZwXFThkPUjF3pGZEdE753W Jlxvr8x6hapqY3dsFHbWiN6lI6mEGIjAK/8q+O+tihvk+9ZChw8rDMxj8q2C1IGG mhF8cIl1E0RVp4EVs+vVVlnMB8I+pMcocmR/8LIzPFnG2PyJxSKxu1ql6FSZ6zfx ZOjLRtvNdr0mBvAJT3zw6IwGnRSNNrqwqEOvfeDTB/nqaL/6B9/krNpGjcdIOwKB Atnscto7KI7Xdrp4shnsjJaQYf0F4Vl4HaiDXMS2ighESol+jT3v40GD//rLk/a0 tyIVpF2agxe8ePX6dKhJwaKvaWE4+xXJAseZHJoMV3o1sameXIHDdpjtxnx5DxD7 3x9nHI/w95EGG4/leq6MAcOg1zS/r/D9Bs3YocuejIjUZnbbg63Iu1hWoWz/xyGi U1GG58DEwDzOh+7Ol8huBJUaSfVuT5pQQw== -----END CERTIFICATE----- subject=/C=US/ST=California/O=Exemplar, Inc./OU=IT Department/CN=www.example.com/emailAddress=itteam@example.com issuer=/C=US/ST=California/L=San Francisco/O=Exemplar, Inc./OU=IT Department/CN=lb_test_root_CA_1/emailAddress=itteam@example.com --- No client certificate CA names sent --- SSL handshake has read 1913 bytes and written 460 bytes --- New, TLSv1/SSLv3, Cipher is RC4-SHA Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1 Cipher : RC4-SHA Session-ID: DE7F22EA486EFB11C8FAFAB9D191637875D9410273AD51EF2419A982E4A26FC1 Session-ID-ctx: Master-Key: 83ACFBB0CD615455FB35019C4FC2036AE0649A2238F0CA2F952D782A06A3C90794F5B4CA5FA00F861F88FFDDC1849C0D Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None TLS session ticket: 0000 - 82 c8 de 59 85 86 40 c9-be c8 d9 e6 7f 29 2e 91 ...Y..@......).. 0010 - a4 53 ea 18 bf 5f ff 3e-cd a4 ac 0b 54 fe 12 ef .S..._.>....T... 0020 - fd d9 8b 76 e6 69 81 9b-9b ed 79 69 26 d6 e2 70 ...v.i....yi&..p 0030 - 4f 8b 7d 15 d3 e3 43 6f-d5 60 f5 0b 76 5a 26 48 O.}...Co.`..vZ&H 0040 - 22 52 8f b3 a6 10 50 92-9d 8d d4 42 2b 8d b2 d7 "R....P....B+... 0050 - 83 a7 5b 6b fe 7b a2 d8-9a db 14 0e de bf 54 d4 ..[k.{........T. 0060 - db f8 4e 71 9d 7b 57 1d-7a 50 24 ae f3 16 76 e5 ..Nq.{W.zP$...v. 0070 - ef 8b 4d 04 60 05 43 d7-74 99 39 68 bc aa d0 d5 ..M.`.C.t.9h.... 0080 - 51 31 1a 96 b0 35 65 8c-ec 92 5f 1a 48 7f 4f 5c Q1...5e..._.H.O\ 0090 - 65 be 85 9f 36 13 13 84-4b aa df 92 e4 58 31 59 e...6...K....X1Y Start Time: 1362183958 Timeout : 300 (sec) Verify return code: 21 (unable to verify the first certificate) --- GET / HTTP/1.1 host: www.example.com HTTP/1.1 302 Found Server: nginx Date: Sat, 02 Mar 2013 00:26:17 GMT Content-Type: text/html Connection: keep-alive X-Powered-By: PHP/5.3.13-1~dotdeb.0 Expires: Sun, 19 Nov 1978 05:00:00 GMT Last-Modified: Sat, 02 Mar 2013 00:26:20 +0000 Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0 ETag: "1362183980" Location: http://www.example.com/ Content-Length: 9 302 Found
sslscan
sslscan www.example.com
SSL Testing Scripts
This checks that the SSL certificate is valid and has no problems.
#!/bin/sh # FIXME: This does not handle star certs (*.example.com). # if echo "${CERT_SUBJECT_CN}" | grep -q -v "*"; then ###################################################################### # # This checks SSL certificates for problems. # # SYNOPSIS # # check_ssl_cert HOSTNAME # # DESCRIPTION # # This checks SSL certificates for problems. # # EXAMPLES # # check_ssl_cert hostname.example.com # # EXIT STATUS # # This exits with status 0 on success or non-zero on error. # # AUTHOR # # Noah Spurrier noah@noah.org # # LICENSE # # This license is OSI and FSF approved as GPL-compatible. # This license identical to the ISC License and is registered with and # approved by the Open Source Initiative. For more information vist: # http://opensource.org/licenses/isc-license.txt # # Copyright (c) 2014, Noah Spurrier # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # # VERSION # # Version 1 # ###################################################################### SSL_HOSTNAME=$1 NOW=$(date "+%s") CERT_INFO=$(openssl s_client -connect ${SSL_HOSTNAME}:443 </dev/null 2>/dev/null | openssl x509 -text -noout) CERT_EXPIRATION_DATE=$(echo "${CERT_INFO}" | sed -n 's/.*Not After.*: \(.*\)/\1/p') CERT_EXPIRATION_SECONDS=$(date '+%s' --date "${CERT_EXPIRATION_DATE}") CERT_EXPIRATION_DAYS=$(( ( $CERT_EXPIRATION_SECONDS - ${NOW} ) / 60 / 60 / 24)) CERT_ISSUER=$(echo "${CERT_INFO}" | sed -n 's/.*Issuer.*: \(.*\)/\1/p') CERT_ISSUER_CN=$(echo "${CERT_INFO}" | sed -n 's/.*Issuer.*:.*CN=\(.*\)/\1/p') CERT_SUBJECT=$(echo "${CERT_INFO}" | sed -n 's/.*Subject.*: \(.*\)/\1/p') CERT_SUBJECT_CN=$(echo "${CERT_INFO}" | sed -n 's/.*Subject.*:.*CN=\(.*\)/\1/p') if [ "${CERT_SUBJECT_CN}" != "${SSL_HOSTNAME}" ]; then # Ignore star certs. They match everything. # FIXME I should at least check that the domain names are the same. if ! printf '%s' "${CERT_SUBJECT_CN}" | egrep -q '\*'; then echo "ERROR: SSL hostname does not match Subject CN in the cert." >&2 echo "SSL_HOSTNAME: ${SSL_HOSTNAME}" >&2 echo "CERT_SUBJECT_CN: ${CERT_SUBJECT_CN}" >&2 exit 1 fi fi if [ ${CERT_EXPIRATION_DAYS} -lt 0 ]; then echo "ERROR: Certificate has expired." >&2 echo "CERT_EXPIRATION_DATE: ${CERT_EXPIRATION_DATE}" >&2 exit 1 fi ##################################################################### # END #########1#########2#########3#########4#########5#########6#########7 #j # __________________ _-_ # \___=NCC-1701= __)) ____.---'---`---.____ # \_ \ \----._________.----' # \ \ / / `-_-' # __,--`-`---'-'-. # /}___ )(- # `--.____,-' # # vim: set ft=sh sr et ts=4 sw=4 : See help 'modeline'
This show the default cipher used to connect to a remote host and it lists all the client ciphers that the remote host supports.
#!/bin/bash ###################################################################### # # This tests the ciphers used by a remote HTTPS (SSL) server. # # SYNOPSIS # # test-ciphers [REMOTE_HOST] # # DESCRIPTION # # This shows the default cipher that is used with a remote host. # It also lists all the client ciphers that the remote host supports. # # LICENSE # # This license is OSI and FSF approved as GPL-compatible. # This license identical to the ISC License and is registered with and # approved by the Open Source Initiative. For more information vist: # http://opensource.org/licenses/isc-license.txt # # Copyright (c) 2013, Noah Spurrier <noah@noah.org> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # ###################################################################### HOST="${1}:443" echo "== default cipher used ==" DEFAULT_CIPHER=$(echo -n | openssl s_client -connect ${HOST} 2>/dev/null | sed -n -e "s/^.*Cipher[[:space:]]*:[[:space:]]*\(.*\)*/\1/ p") echo ${DEFAULT_CIPHER} echo echo "== check which client ciphers are supported by the remote server. ==" ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g') for cipher in ${ciphers[@]}; do response=$(echo -n | openssl s_client -cipher "$cipher" -connect $HOST 2>&1) if [[ "$response" =~ "Cipher is " ]] ; then echo "1 ${cipher}" else if [[ "$response" =~ ":error:" ]] ; then whynot=$(echo -n $response | cut -d':' -f6) echo "0 ${cipher} ${whynot}" else echo "0 ${cipher} ERROR: ${response}" fi fi done