HTTP Public Key Pinning (HPKP)

HTTP Public Key Pinning is a mechanism that can prevent Man-in-the-Middle attacks against TLS connections to HTTP services.  Essentially, the web service tells the browser which certificates it should expect and that it should reject all others.  It is a header and looks a little like this:

Public-Key-Pins: pin-sha256=”eZ2mT3Q9rS+P5WO3beF1Du9Jojk2oaO3eM0BYjl+uKk=”; pin-sha256=”2RvDQRJ3jUJaIvGRBMATMgSMrTecA3HXQXeUgRFKIcc=”; max-age=5184000; includeSubDomains

Each of the sections prefixed with “pin-sha256” are the identifiers for the certificates and they are known as “pins”.  Pins are base64 encoded, sha256 hashes of the public keys.  You need to have two pins, one is your current certificate, and one is a backup certificate in case the current one is compromised or expires.  The good news is, you can produce this hash based on the CSR (Certificate Signing Request) and you don’t actually need to buy a cert at this stage to be able to have a backup pin in place!

The “max-age” section is better thought of as a Time To Live (TTL).  That is because it is the value in seconds for which the browser is instructed to honour the security header.  5,184,000 is approximately 2 months.

Optionally, you can include all subdomains as well – though you need to think about this and make sure it is appropriate for your environment.

To get the current certificate pin you can cheat a little and use this web service ( written by Scott Helme.  You only need the pin is associated with your site which is usually the top entry when the service finishes its analysis.  The ones below are not required and potentially weaken the policy – they are after all pins for certificates that are outside your control!

The backup pin is required – without it, browsers will ignore the header.  It is important to have a backup pin in place anyway just in case your existing cert becomes compromised or deleted, or (and more likely) the certificate expires.  To generate the backup pin, first get yourself a private key and CSR.  Once you have these you can use OpenSSL:

openssl req -in yoursigningrequest.csr -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

As for sticking them in your web server config, this can be pretty easy.  For example, with Apache you can simply add the header to your .htaccess file.  For example:

Header always set Public-Key-Pins “pin-sha256=\”eZ2mT3Q9rS+P5WO3beF1Du9Jojk2oaO3eM0BYjl+uKk=\”; pin-sha256=\”2RvDQRJ3jUJaIvGRBMATMgSMrTecA3HXQXeUgRFKIcc=\”; max-age=5184000; includeSubDomains”

Another good tool, also by Scott, for analysing your configuration is here (

At the time of writing, this header is relatively new and isn’t really deployed much.  It is also worth knowing that there appears to be slight implementation differences in browsers.  The main one that my colleague and I noticed is that on one machine running Firefox 38 ESR, the HPKP header didn’t work until its configuration was tweaked.  At the same time, Firefox 43 seemed to work exactly as we would expect without any configuration tweaks.  The tweak was to change:


From false to true.  This was not required in Firefox 43.  The only theory I have about the cause of this is that the certificate being used requires an additional “sf_bundle” to be included in the Apache configuration as the CA root is listed as part of the default store in both versions of Firefox.

Whilst discussing Firefox, there may be a tweak that the neurotic amongst us want to change…  It seems their are four states for this protection in Firefox:

0 – HPKP Disabled
1 – HPKP Enforced, except when certificate is chained to user-supplied root CA
2 – HPKP Fully Enforced
3 – HPKP Enforced Testing

This is controlled by the setting:


Personally, I have chosen to change it to “2” as there should not be any user-supplied root CA in my Firefox configuration.  Having said that, it is fair to say that if an attacker is able to insert a root CA into my machine, they can probably do a lot of other attacks as well.  Including simply disabling HPKP.  Both of these values can be found in “about:config” within Firefox.

And final note on this topic, make sure you replace your certs well in advance of them expiring!  If you do not have a backup pin in place for the next certificate, clients will not be able to connect to your web service once you change certificate.  This is because the mechanism is designed to only accept the known certificate, so even if it is a legitimate cert which is chained to a legitimate root CA, it will be ignored.

Posted in Security Basics | 3 Comments

SMBExec 2.0 and Cracking Domain Cached Credentials on oclHashcat

Recently, on one of my experimentation days, I decided to play with the “Cached Hashes” that are provided when using SMBExec 2.0. SMBExec is a good tool, so if you haven’t already used it it is highly recommended. For those of you who do though you may have seen output a little like this:

[+] – Found 3 Local, 5 Cached, 0 in Memory
[+] – Found 4 Local, 2 Cached, 1 in Memory
[+] – Found 4 Local, 6 Cached, 0 in Memory

“Local” means the local SAM database, “Memory” means the plain text passwords extracted from the lsass process and “Cached” means Domain Cached Credentials. These cached hashes are the ones I am interested in for this post and are a special type of hash, unlike NetNTLM etc or plain NTLM hashes. The cached hashes file saved from SMBExec looks a little like this:


Just to add to any confusion – “Cached” in SMBExec 2.0 is the same thing as Domain Cached Credentials which is the same thing as MSCash hashes.

It would be easy to look at the hash and decide that it is just an MD5 or NTLM and infact if you were to tell oclHashcat that that is what it is, it would keep trying but would almost certainly never find the plain text. That is because MSCash passwords are in a different format and have had more work performed on them than a single pass algorithm such as MD5. MSCash hashes come in two varieties – Windows Vista and above have MSCashv2, where as earlier had MSCashv1.

To convert the above SMBExec hash to MSCashv1 you will probably want a command like the following:

cat cached_hashes_unique.txt | awk -F “:” {‘print $2″:”$1’} > mscashv1.txt

This will produce an output file that looks a little like this:


To convert the above SMBExec hash to MSCashv2 you will probably want a command like the following:

cat cached_hashes_unique.txt | awk -F “:” {‘print “$DCC2$10240#”$1″#”$2’} > mscashv2.txt

This will produce an output file that looks a little like this:


In MSCashv1 the username is the salt for the final hash – this slows down cryptanalysis a little but is not too bad. In oclHashcat you want hashtype 1100 to crack these.

In MSCashv2 the begining part of the string (“DCC2”) is to denote it as MSCashv2, the second part (“10240”) is to indicate the number of cryptographic rounds it is configured for – strictly speaking this can be configured to any number, however the default is 10240. The username is still used as a salt in MSCashv2. In oclHashcat you want hashtype 2100 to crack these.

Posted in Uncategorized | Leave a comment

LogJam on Cisco ASA 5500 series devices

Got LogJam (pre-computation variety) on your Cisco ASA? Took someone I knew a long time to find / work out the following information, so I figured I would post a short one on it…
Basically, there was once a Cisco ASA 5512X that had the LogJam vuln on it. In particular, the variety where everyone is using the same 1024 bit diffie hellman group modulus. The sys admmin for this box worked through the config and changed all the items they could see so that it was using “group14” (Cisco speak for a DH group of 2K). In short, this was the expected fix but when scanned by SSLScan and the Qualys SSL Labs scanner, no change was seen. It got pretty annoying, but eventually it was discovered that there was another setting that hadn’t been changed despite there being nothing else left to change in the config when running:
sh run ssl
This outputs:
ssl cipher default custom "AES256-SHA:DHE-RSA-AES256-SHA:AES128-SHA:DHE-RSA-AES128-SHA"
ssl cipher sslv3 custom "AES256-SHA:DHE-RSA-AES256-SHA:AES128-SHA:DHE-RSA-AES128-SHA"
ssl cipher tlsv1 custom "AES256-SHA:DHE-RSA-AES256-SHA:AES128-SHA:DHE-RSA-AES128-SHA"
ssl cipher dtlsv1 custom "AES256-SHA:DHE-RSA-AES256-SHA:AES128-SHA:DHE-RSA-AES128-SHA"
ssl trust-point [TrustPoint] inside
ssl trust-point [TrustPoint] outside

Nothing there to change right? Wrong… If you run:
sh run all ssl
You end up with a whole few extra lines in the config:
ssl server-version tlsv1
ssl client-version tlsv1
ssl cipher default custom "AES256-SHA:DHE-RSA-AES256-SHA:AES128-SHA:DHE-RSA-AES128-SHA"
ssl cipher sslv3 custom "AES256-SHA:DHE-RSA-AES256-SHA:AES128-SHA:DHE-RSA-AES128-SHA"
ssl cipher tlsv1 custom "AES256-SHA:DHE-RSA-AES256-SHA:AES128-SHA:DHE-RSA-AES128-SHA"
ssl cipher tlsv1.1 medium
ssl cipher tlsv1.2 medium
ssl cipher dtlsv1 custom "AES256-SHA:DHE-RSA-AES256-SHA:AES128-SHA:DHE-RSA-AES128-SHA"
ssl dh-group group2
ssl trust-point [TrustPoint] inside
ssl trust-point [TrustPoint] outside
ssl certificate-authentication fca-timeout 2

Including one “ssl dh-group group2”, which is the offending configuration setting. This just needs changing to group14 and away you go, no more LogJam.

Posted in Lessons Learnt | Leave a comment