Nmap Development mailing list archives
Re: Request: public key retrieval in nmap.get_ssl_certificate
From: Brandon Enright <bmenrigh () ucsd edu>
Date: Thu, 28 Jan 2010 21:56:06 +0000
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thu, 28 Jan 2010 12:36:03 -0700 David Fifield <david () bamsoftware com> wrote:
All, I got a request for ssl-cert.nse to return the length of the certificate's public key, so the scritp can be used to check for short keys. Who wants to add support for this? I think it will be straightforward to add a new accessor method in nse_ssl_cert.cc. I see the addition of a new function, ssl_cert_pubkey, that calls the function X509_get_pubkey and returns a table representing the key information. David Fifield
I wrote a perl script that pulls the cert out of the script output and passes it through openssl like so: # $ cat | openssl x509 -text -fingerprint -noout my @cmd = ('openssl', 'x509', '-text', '-fingerprint', '-noout'); my ($ccode, $in, $out, $err, $rcode); $in = $cert; $ccode = run \@cmd, \$in, \$out, \$err, timeout(5); $rcode = $?; unless ((defined $ccode) && ($rcode == 0)) { warn $err if ((defined $err) && ($err ne '')); } else { $cert_text = $out; #warn 'got ', $out, "\n"; } While we're on the topic of SSL certs and checking for bad things, here are the things I'm checking for in snippets of hopefully-readable perl. I know some of this is out of context but when you see a "push @warning" that is a message that will be reported by the script. # The sig alg if ($cert_text =~ m/Signature Algorithm: (\S+)/) { my $sig_alg = $1; if ($sig_alg =~ m/md5/i) { push @warning, {('name'=>'SSLCERT_MD5', 'severity'=>4, 'text'=>'SSL Cert on ' . $ps_port . ' is signed with MD5')}; } elsif ($sig_alg =~ m/md2/i) { push @warning, {('name'=>'SSLCERT_MD2', 'severity'=>7, 'text'=>'SSL Cert on ' . $ps_port . ' is signed with MD2')}; } elsif ($sig_alg =~ m/md4/i) { push @warning, {('name'=>'SSLCERT_MD4', 'severity'=>6, 'text'=>'SSL Cert on ' . $ps_port . ' is signed with MD4')}; } elsif ($sig_alg !~ m/sha[1235]/i) { push @warning, {('name'=>'SSLCERT_NOTSHA', 'severity'=>5, 'text'=>'SSL Cert on ' . $ps_port . ' is signed with a ' . 'SHA family algorithm')}; } } # The RSA size if ($cert_text =~ m/Modulus \((\d+) bit\):/) { my $size = $1; if ($size < 1024) { push @warning, {('name'=>'SSLCERT_SMALL', 'severity'=>6, 'text'=>'SSL Cert on ' . $ps_port . ' uses a small key (' . $size . ')')}; } if (($size != 512) && ($size != 1024) && ($size != 1536) && ($size != 2048) && ($size != 3072) && ($size != 4096)) { push @warning, {('name'=>'SSLCERT_ODDSIZE', 'severity'=>2, 'text'=>'SSL Cert on ' . $ps_port . ' uses odd sized key (' . $size . ')')}; } } # The issuer and subject if ($cert_text =~ m/Issuer: ([^\r\n]+)/) { my $issuer = $1; if ($cert_text =~ m/Subject: ([^\r\n]+)/) { my $subject = $1; my $selfsigned = 0; if ($issuer eq $subject) { push @warning, {('name'=>'SSLCERT_SELFSIG', 'severity'=>4, 'text'=>'SSL Cert on ' . $ps_port . ' is self-signed')}; $selfsigned = 1; } if ($issuer =~ m/Globus\sSimple|DigiCert|Thawt| Equifax|cacert|Go\sDaddy| IPS\sCertification|Comodo\sCA| VeriSign\sTrust|Entrust\.net /ix) { push @warning, {('name'=>'SSLCERT_CASIG', 'severity'=>1, 'text'=>'SSL Cert on ' . $ps_port . ' is not ' . 'self-signed and may hold ' . 'more trust')}; } else { if ($issuer ne $subject) { # To try to find more CAs #warn 'Issuer: ', $issuer, "\n"; } } if ($subject =~ m/CN=(.*?)(?:, |\/|$)/) { my $cn = $1; unless ($cn =~ m/^[a-zA-Z0-9@._*-]+$/) { push @warning, {('name'=>'SSLCERT_BADCN', 'severity'=>4, 'text'=>'SSL Cert on ' . $ps_port . ' does not have ' . 'a well-formed CN')}; } if ($cn =~ m/^\*/) { push @warning, {('name'=>'SSLCERT_WILDCARD', 'severity'=>4, 'text'=>'SSL Cert on ' . $ps_port . ' has wildcard' . ' CN (' . $cn . ')')}; } # Look for evil or fake CNs if ($selfsigned == 1) { if ($cn =~ m/Microsoft/i) { push @warning, {('name'=>'SSLCERT_FAKECN', 'severity'=>8, 'text'=>'SSL Cert on ' . $ps_port . ' appears to' . ' be faking a company CN')}; } if ($cn =~ m/\b(?:evil| hack(?:ed)?| [op]wn(?:ed)? )\b/xi) { push @warning, {('name'=>'SSLCERT_EVILCN', 'severity'=>8, 'text'=>'SSL Cert on ' . $ps_port . ' appears to ' . ' be indicate a malicious service')}; } } } else { push @warning, {('name'=>'SSLCERT_NOCN', 'severity'=>4, 'text'=>'SSL Cert on ' . $ps_port . ' does not have ' . 'a CN in the subject')}; #warn 'Subject: ', $subject, "\n"; } } } # The validity dates if ($cert_text =~ m/Not Before: ([^\r\n]+(\d{4}) GMT)/) { my $sbadyear = 0; my $starttime = 0; if (($2 < 1970) || ($2 >= 2038)) { $sbadyear = 1; } else { #warn 'start: ', $1, "\n"; $starttime = str2time($1); unless (defined $starttime) { $sbadyear = 1; } } if ($cert_text =~ m/Not After : ([^\r\n]+(\d{4}) GMT)/) { my $ebadyear = 0; my $endtime = 0; if (($2 < 1970) || ($2 >= 2038)) { $ebadyear = 1; } else { #warn 'end: ', $1, "\n"; $endtime = str2time($1); unless (defined $endtime) { $ebadyear = 1; } } if (($sbadyear == 1) || ($ebadyear == 1)) { push @warning, {('name'=>'SSLCERT_BADYEAR', 'severity'=>2, 'text'=>'SSL Cert on ' . $ps_port . ' is valid for a ' . 'nonsensical date range')}; } else { if ($starttime >= $endtime) { push @warning, {('name'=>'SSLCERT_NEVER', 'severity'=>2, 'text'=>'SSL Cert on ' . $ps_port . ' is never valid' . ' based on date range')}; } if ($starttime > $cur_time) { push @warning, {('name'=>'SSLCERT_FUTURE', L 'severity'=>2, 'text'=>'SSL Cert on ' . $ps_port . ' is only valid ' . 'in the future')}; } if ($endtime < $cur_time) { push @warning, {('name'=>'SSLCERT_EXPIRED', 'severity'=>3, 'text'=>'SSL Cert on ' . $ps_port . ' has expired')}; } if (($endtime > $cur_time) && ($endtime < $cur_time + 60 * 24 * 60 * 60)) { push @warning, {('name'=>'SSLCERT_EXPIRESOON', 'severity'=>1, 'text'=>'SSL Cert on ' . $ps_port . ' will expire' . ' soon')}; } if (($endtime - $starttime) > (10 * 356.4 * 24 * 60 * 60)) { push @warning, {('name'=>'SSLCERT_DECADE', 'severity'=>3, 'text'=>'SSL Cert on ' . $ps_port . ' is valid for ' . 'more than a decade')}; } } # End is good year in dates } Hopefully other people wanting to audit their organization's SSL deployments will find this useful. Brandon -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.11 (GNU/Linux) iEYEARECAAYFAktiCAUACgkQqaGPzAsl94IqtwCeM+l660HJLUQ0/mMKuzuPj88n l/4AoItH7/t6PWjAnucKsNCmLysXX9ha =/kA4 -----END PGP SIGNATURE----- _______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://seclists.org/nmap-dev/
Current thread:
- Request: public key retrieval in nmap.get_ssl_certificate David Fifield (Jan 28)
- Re: Request: public key retrieval in nmap.get_ssl_certificate Ron (Jan 28)
- Re: Request: public key retrieval in nmap.get_ssl_certificate Brandon Enright (Jan 28)