local nmap = require "nmap" local os = require "os" local shortport = require "shortport" local sslcert = require "sslcert" local stdnse = require "stdnse" local string = require "string" description = [[ Retrieves a server's SSL certificate. The amount of information printed about the certificate depends on the verbosity level. With no extra verbosity, the script prints the validity period and the commonName, organizationName, stateOrProvinceName, and countryName of the subject, the issuer name and fingerprints. 443/tcp open https | ssl-cert: | subject: | serialNumber: 3014267 | 1.3.6.1.4.1.311.60.2.1.3: US | 1.3.6.1.4.1.311.60.2.1.2: Delaware | businessCategory: Private Organization | organizationName: PayPal, Inc. | commonName: www.paypal.com | organizationalUnitName: PayPal Production | localityName: San Jose | streetAddress: 2211 N 1st St | stateOrProvinceName: California | countryName: US | postalCode: 95131-2021 | issuer: | commonName: VeriSign Class 3 Extended Validation SSL CA | organizationName: VeriSign, Inc. | organizationalUnitName: Terms of use at https://www.verisign.com/rpa (c)06 | countryName: US | pubkey: | type: rsa | bits: 2048 | validity: | notAfter: 2013-04-01 23:59:59 | notBefore: 2011-03-23 00:00:00 | md5: bf47cecad861efa77d1488ad4a73cb5b |_sha1: d8465221467a0d153df09f2eaf6d439002139a68 With -vv it adds the PEM-encoded contents of the entire certificate. 443/tcp open https | ssl-cert: | subject: | serialNumber: 3014267 | 1.3.6.1.4.1.311.60.2.1.3: US | 1.3.6.1.4.1.311.60.2.1.2: Delaware | businessCategory: Private Organization | organizationName: PayPal, Inc. | commonName: www.paypal.com | organizationalUnitName: PayPal Production | localityName: San Jose | streetAddress: 2211 N 1st St | stateOrProvinceName: California | countryName: US | postalCode: 95131-2021 | issuer: | commonName: VeriSign Class 3 Extended Validation SSL CA | organizationName: VeriSign, Inc. | organizationalUnitName: Terms of use at https://www.verisign.com/rpa (c)06 | countryName: US | pubkey: | type: rsa | bits: 2048 | validity: | notAfter: 2013-04-01 23:59:59 | notBefore: 2011-03-23 00:00:00 | md5: bf47cecad861efa77d1488ad4a73cb5b | sha1: d8465221467a0d153df09f2eaf6d439002139a68 | pem: -----BEGIN CERTIFICATE----- | MIIFxzCCBK+gAwIBAgIQX02QuADDB7CVjZdooVge+zANBgkqhkiG9w0BAQUFADCB ... ]] --- -- @output -- 443/tcp open https -- | ssl-cert: -- | subject: -- | serialNumber: 3014267 -- | 1.3.6.1.4.1.311.60.2.1.3: US -- | 1.3.6.1.4.1.311.60.2.1.2: Delaware -- | businessCategory: Private Organization -- | organizationName: PayPal, Inc. -- | commonName: www.paypal.com -- | organizationalUnitName: PayPal Production -- | localityName: San Jose -- | streetAddress: 2211 N 1st St -- | stateOrProvinceName: California -- | countryName: US -- | postalCode: 95131-2021 -- | issuer: -- | commonName: VeriSign Class 3 Extended Validation SSL CA -- | organizationName: VeriSign, Inc. -- | organizationalUnitName: Terms of use at https://www.verisign.com/rpa (c)06 -- | countryName: US -- | pubkey: -- | type: rsa -- | bits: 2048 -- | validity: -- | notAfter: 2013-04-01 23:59:59 -- | notBefore: 2011-03-23 00:00:00 -- | md5: bf47cecad861efa77d1488ad4a73cb5b -- |_sha1: d8465221467a0d153df09f2eaf6d439002139a68 -- --@xmloutput -- author = "David Fifield" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = { "default", "safe", "discovery" } portrule = function(host, port) return shortport.ssl(host, port) or sslcert.isPortSupported(port) end function date_to_string(date) if not date then return "MISSING" end if type(date) == "string" then return string.format("Can't parse; string is \"%s\"", date) else return os.date("%Y-%m-%d %H:%M:%S", os.time(date)) end end local function keys(t) local ret = {} for k, _ in pairs(t) do ret[#ret+1] = k end return ret end local nsedebug = require "nsedebug" -- Convert a cert (which is a kind of userdata object) into a normal Lua table. local function to_table(cert) local ret = { subject = cert.subject, issuer = cert.issuer, pubkey = cert.pubkey, validity = cert.validity, md5 = stdnse.tohex(cert:digest("md5")), sha1 = stdnse.tohex(cert:digest("sha1")), } local fields = {"subject", "issuer", "pubkey", "validity", "md5", "sha1"} if nmap.verbosity() > 1 then ret.pem = cert.pem fields[#fields+1] = "pem" end for _, k in ipairs(keys(ret.subject)) do if type(k) == "table" then ret.subject[table.concat(k,".")] = ret.subject[k] ret.subject[k] = nil end end stdnse.set_tostring(ret.validity.notBefore, date_to_string) stdnse.set_tostring(ret.validity.notAfter, date_to_string) stdnse.set_tostring(ret, stdnse.format_generator({ key_order = fields })) return ret end action = function(host, port) local status, cert = sslcert.getCertificate(host, port) if ( not(status) ) then return end return to_table(cert) end