Shammer's Philosophy

My private adversaria

SSL Server Cipher Check Client with python

I wrote similar scripts which I will write in this article. The latest one of those is Python SSL Client for checking ciphers supported on the server - Shammerism. This version can be check only one cipher at one execution, but I wrote the one before at Remote SSL Server cipher check script with python - 20150130 - Shammerism. Then, merging these script makes a remote ssl cipher checker perfectly ignoring server certificate error. That version is below.

#!/usr/bin/env python
import argparse
import commands
import httplib
import ssl

parser = argparse.ArgumentParser()
parser.add_argument('-host', dest = 'host', required = True)
parser.add_argument('-port', dest = 'port', default = 443)
x = vars(parser.parse_args())

ciphers = commands.getoutput('openssl ciphers -v | awk \'{print $1}\' | grep -v \'SRP-\\|PSK-\'').split('\n')
OK = []
NG = []
NOSUPPORT = []
for i in ciphers:
    try:
        sslContext = ssl._create_unverified_context()
        sslContext.set_ciphers(i)
        try:
            s = httplib.HTTPSConnection(x['host'], port = x['port'], context = sslContext)
            s.send('GET / HTTP/1.1\r\n')
            s.send('Host: ' + x['host'] + '\r\n')
            s.send('\r\n')
            OK.append(i)
        except ssl.SSLError, e:
            print 'Connect failure because of ' + e.args[1]
            NG.append(i)
        finally:
            s.close()
    except ssl.SSLError, e:
        print 'Can not set ' +  i + ' to SSLContext because ' + e.args[0]
        NOSUPPORT.append(i)
      

print '========== Supported Ciphers =========='
for i in OK:
    print i
print '========== Ciphers which can not be set on this host =========='
for i in NOSUPPORT:
    print i
print '========== Connection failed Ciphers =========='
for i in NG:
    print i

I added a new ciphers group named NOSUPPORT. In my environment, python is used in the system default but openssl was upgraded. So a lot of ciphers are faced with error "No cipher can be selected" when sslContext.set_cipher('SOME_NEW_CIPHER'). This caused by the openssl version difference. The openssl version linked from python is older than the one invoked by "commands.getoutput('openssl ciphers -v ...". In my environment, which openssl returns "/usr/local/bin/openssl", but other openssl is installed whose path is /usr/bin/openssl. Python seems to be linked with /usr/bin/openssl, so some ciphers supported only /usr/local/bin/openssl are not run correctly. The best way how to resolve this is linked again the latest openssl with python. But, I am not sure how to link openssl libraries which python uses. I will investigate this point someday.