Stuff I Learned Scripting - Evaluating a Remote SSL Certificate

Published: 2011-11-07
Last Updated: 2011-11-07 17:56:09 UTC
by Rob VandenBrink (Version: 1)
7 comment(s)

 I find that the longer I work in this field, the more scripts I write. Solving a problem with a script might take a bit longer the first time, but the next time you see the problem it takes seconds to resolve (assuming you can find your script back, that is). This is illustrated so well (and so timely) here ==> http://www.xkcd.com/974/ 

But I'm not here to sell you on scripting, or on any particular scripting language. This story about neat stuff I've learned while scripting, tid-bits that I wouldn't have learned otherwise that I hope you find useful as well.

Recently I had to assess if a remote windows host was using a self-signed certificate, or one issued by a public or a private CA (Certificate Authority). The remote host was a VMware vCenter console, but that's not material to the script really, other than dictating the path.

Easy you say, use a browser! Sure, that's ONE easy way, but what if you've got 10 others to assess, or a hundred? Or more likely, what if this is one check in hundreds in an audit or assessment? It's at that point that the "this needs a script" lightbulb goes off for me.

In this case I "discovered" the windows command CERTUTIL.EXE. Typing "certutil -?" will get you pages of syntax of the complex things that this command can do, but in this case all we want to do is dump the certificate information. Since the server is remote, let's map a drive and query the cert:

>map l: \\c%$
>certutil -dump "l:\programdata\vmware\vmware virtualcenter\SSL\rui.crt"

ah- 2 things on this though - is your L: drive available? If you are writing this from someone else, is their L: drive available? Also, this is located off of %ALLUSERSPROFILE%, not neccessarily in the directory above. We can fix this in one fell swoop - we'll use Microsoft's PSTOOLS ( http://technet.microsoft.com/en-us/sysinternals/default ) to run it on the remote host directly:

>psexec \\%1 -u %2 -p %3 certutil -dump "%allusersprofile%\vmware\vmware virtualcenter\SSL\rui.crt"

This is set up to take the target host and credentials from the command line in a script - - where %1 is the server name, %2 is the userid, and %3 is the password

Finally, this seems like a lot of output - if we're just trying to validate who signed the certificate, we can tack on a "find" command to get that (the output is shown here as well):

>psexec \\%1 -u %2 -p %3 cmd /c certutil -dump "%allusersprofile%\vmware\vmware virtualcenter\SSL\rui.crt" | find "O="
O=VMware Installer
O=VMware, Inc.
>psexec \\%1 -u %2 -p %3 cmd /c certutil -dump "%allusersprofile%\vmware\vmware virtualcenter\ssl\rui.crt" | find "CN="
CN=VMware default certificate


These show that the certificate is the Default cert, installed by the VMware Installer.

Finally, the approaches so far have required credentials, which you really shouldn't need for this task - let's try it directly, using the HTTPS protocol.  if you want to do this entirely over an SSL session, you'll need openssl installed (installed by default on many Linux distros, but can be bolted on to Windows easily enough):

# openssl s_client -connect servername:443 < QUIT.in o

where the file "QUIT.in", contains the word  "QUIT", followed by a carriage return.

The certificate itself will be included, between the "BEGIN CERTIFICATE" and "END CERTIFICATE" markers. Getting just the information we need is simple at this point, use "find", or "grep" in Linux:

# openssl s_client -connect servername:443 < QUIT.in | grep "O="
depth=0 /O=VMware, Inc./OU=VMware, Inc./CN=VMware default certificate/emailAddress=support@vmware.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /O=VMware, Inc./OU=VMware, Inc./CN=VMware default certificate/emailAddress=support@vmware.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 /O=VMware, Inc./OU=VMware, Inc./CN=VMware default certificate/emailAddress=support@vmware.com
verify error:num=21:unable to verify the first certificate
verify return:1
0 s:/O=VMware, Inc./OU=VMware, Inc./CN=VMware default certificate/emailAddress=support@vmware.com i:/O=VMware Installer subject=/O=VMware, Inc./OU=VMware, Inc./CN=VMware default certificate/emailAddress=support@vmware.com issuer=/O=VMware Installer
DONE

As you can see from this output, it returns the same answer (with a bit more detail) - that this server has a self-signed certificate

Finally, the beauty of "Stuff I Learned Scripting" is that you are probably scripting as well. If you've found a better way to assess certificates, by all means post to our comment form ! In particular, if you've found a way to duplicate what openssl can do over tcp/443, without installing openssl (maybe using wget or curl to feed certutil?), we're all ears !!

 

Oh - and can you please pass the salt ?

===============
Rob VandenBrink
Metafore

 

7 comment(s)

Comments

A master artisan of great foresight!
if you're going to use this as is (and why not?) then you can use output redirection to eliminate the need for QUIT.in, viz:

echo "QUIT" | openssl s_client ...
that should be:

echo -en "QUIT\r" | openssl s_client ...

to get the CR rather than LF/NL as required by protocol, no?
or rather:

echo -en 'QUIT\r' | openssl s_client ...

to avoid the shell eating the backslash. Sometimes putting the thing in a file is actually easier and more straightforward...
"QUIT" isn't the important bit, lines that start with "Q" are treated as EOF by default, and lines that start with "R" cause a renegotiation.

A useful one-liner is:
echo "" | openssl s_client -connect www.gmail.com:443 |
openssl x509 -noout -subject -dates
To cleanly do the same for SMTP+STARTTLS
printf "QUIT\r\n" | openssl s_client -connect mail.messaging.microsoft.com:25 -starttls smtp -ign_eof |
openssl x509 -noout -subject -dates

To show chain details too (where available from the server):
echo "" | openssl s_client -connect www.facebook.com:443 -showcerts |
gawk 'BEGIN { pipe="openssl x509 -noout -subject -issuer -dates -serial "} \
/^-+BEGIN CERT/,/^-+END CERT/ { print | pipe }
/END CERT/ { close(pipe); printf("\n\n")} '
reinventing the wheel? sometimes it's enough to put on your g00gles :)

#!/bin/sh
#
for CERT in \
myfirst.server.local:443 \
mysecond.server.local:993 \
do
echo |\
openssl s_client -connect ${CERT} 2>/dev/null |\
sed -ne "/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p" |\
openssl x509 -noout -subject -dates
done
echo "need more? type: openssl x509 -?"


###
REF -> http://www.madboa.com/geek/openssl/#cert-retrieve
salt:
_____
^ <_ _ _/ )
/ \ /
/ \ + / = [ . . . . x 2^~ ]
/ \

*the proper stones (NaCl) and a input of a < "brute-force-hammer"*

Diary Archives