Monday, 28 November 2016

Azure Federated Security Signing Key Rollover

Lately, I've been working with Azure's implementation of OAuth and OpenID, using mod_auth_mellon in particular.

Azure has been updating their signing keys rather frequently (twice in the last month), and each time the keys have been updated, our authentication solution has failed until we've refreshed the Federation Metadata file from Azure.

The documentation from Azure indicates that applications really ought to be able to handle key rollover automatically (see - and indeed, Mellon does handle this gracefully, but only when the key is already known in the Federation Metadata file (known as the MellonIdPMetadataFile in Mellon).  However, the failures occur when Azure moves to a new key that Mellon didn't know about in advance.

What's actually happening is that Azure has been adding new keys, and starting to use them after 1-2 weeks.  However, since we don't refresh the Metadata automatically, the first Mellon knows about the new key is when it gets used... at which point, we fail to verify the signature, and authentication fails.

The simple & naive solution would be to refresh the Federation Metadata automatically - but that left me with an uncomfortable feeling, which I shall explain below.
However, after a full analysis, it turns out that this naive solution is indeed correct (with a few caveats, which I shall also explain).

Why was I nervous?  Consider the authentication flow:
  • We send a request to Azure to authenticate a user 
  • We get a response back with a token, and verify that it really is from Azure by checking the signature on that Token 
  • We then grant access to the user
Having a signature on the token guards against any kind of Man-in-the-Middle attack - If a Man-in-the-Middle was compromised (e.g. DNS spoofing, proxy redirection etc.), we would currently be safe:
  • We send a request to Azure to authenticate the user
    • It gets redirected to Attacker’s server instead
  • We get a response back which actually comes from the Attacker’s server
    • We reject that response, because it is not (cannot be!) signed with a valid key
However, if we are automatically refreshing the Federation Metadata document, we no longer have any safeguard that the token really comes from Azure
  • We fetch the latest federation metadata file from the Azure server
    • Again, we get redirected to the Attacker’s server instead, and get a metadata document with his key added
  • We send a request to Azure to authenticate the user 
    • It gets redirected to Attacker’s server instead
  • We get a response back which actually comes from the Attacker’s server
    • We validate the response, because it’s signed with a key that we’ve been told is valid
A patient MitM could even keep the authentication requests going to the real authentication server for days/weeks until he detects a refresh of the metadata file and therefore knows his key will now be accepted…

Based on this attack scenario, it seems that automatic refreshes of the metadata file need to either be authenticate, or be signed in some way so that we know that this metadata file does really come from a trusted source.

Of course, we already have a mechanism to do this.  The Federation Metadata from Azure is served over HTTPS, which means not only is the data encrypted in transit, but (more relevantly) the connection to the server can be authenticated as "yes, this really is the Microsoft Azure server"

The code sample in the Azure documentation has the slightly cryptic comment here:
MetadataSerializer serializer = new MetadataSerializer()
    // Do not disable for production code
    CertificateValidationMode = X509CertificateValidationMode.None
Here,  the example code is disabling the check that the Metadata is really coming from the expected server... which is rather a bad idea in any code, not just Production.

Indeed, fetching the Federation Metadata automatically is safe, but only if it is done over HTTPS, and the certificate from the HTTPS server is verified as coming from a trusted certificate authority.

Indeed, any MitM can serve a doctored Metadata document over HTTPS with a certificate indicating that it's coming from - but only Azure will be able to provide a certificate that has been issued to and has been signed by a suitably trusted Root CA.

To be fully secure then, we should use curl with the "--with-ca-bundle" parameter or wget with the "--ca-certificate" parameter to be 100% sure that the Metadata document has come from a trusted server.

Wednesday, 13 July 2016

TravelEx Supercard - Not so Super anymore!

About a year ago, I was fortunate enough to be able to join in the pilot of the TravelEx SuperCard

This card offers 0% fees on foreign currency transactions, which saves a few pounds of the typical UK credit cards which charge anything from 50p to £2.50, plus up to 3% of the transaction amount.

Of course, I already had a 0% fee card for foreign currency, so this wasn't new... but what is new and special is that with Supercard, your transactions are recharged back to some other card in sterling - allowing you to gain cashback or loyalty points with that card as normal.
Additionally, all your transactions appear immediately in an App, showing you exactly how much you would be charged in pounds (and of course, emphasising the savings you'd made with Supercard).

This immediate display of the sterling amount turned out to be the most useful feature of the card, for me, since it allowed me to claim my work expenses immediately (instead of waiting for the transaction to clear).  It was also great on holiday, since I could keep a running total of the real cost of the trip.

Supercard has now launched publicly, with one significant change - they are now a Mastercard instead of Visa.

I haven't yet had chance to use this card abroad myself, but reports are coming in that people are being charged a mysterious extra charge.
Thankfully, the community at Head for Points has been quick to analyse these charges - my thanks to John in the comments there, who seems to have done a lot of research and analysis on this!

My interpretation of this is that Supercard is receiving the exchange rate data from Mastercard one day late.  This means that the transaction is initially being charged at "yesterday's" rate - and this is what is shown in the app as well.
Later, when Supercard receives the correct rate for the transaction date, they are doing an adjustment - so in fact, they are sticking perfectly to their own terms and conditions.
They've also stated on Twitter that if the rate had changed the other way, a refund would be issued instead (although, with Brexit, we've yet to see that in action!)


Assuming that this is all correct and true, financially we're probably still better off with the Mastercard solution - the statistics seem to show that the Mastercard rates are very slightly better than the Visa rates.

However, the fact that Supercard is now charging a second transaction to issue the correct exchange rate means that the app is no longer as useful for me as a traveller.  I can no longer rely on the figures shown to be the final charge, as I could before, since it is likely that a correction will be made a few days later.

This appears to be a limitation from Mastercard, since their exchange rate is defined based on the "Settlement Rate", which appears to be determined (or at least published) one day in arrears.

However, since at the moment Supercard is not updating the transaction on the App when the final exchange rate is determined, they appear to be in breach of their own terms and conditions!
In particular, section 7.5 indicates:
... Your statement will show:
(d) the exchange rate (where applicable) which applied to each Transaction;
(e) where applicable, the amount of each Transaction following a currency conversion (in GBP sterling) 

My only hope is that Supercard will update the App to reflect this more clearly (since it's unlikely that they can get "today's" Settlement Rate from Mastercard).
I would suggest the following improvements:
  • Mark the initial transaction as an "indicative rate" - perhaps faded grey, as is often used for pending transactions on online statements
  • As soon as the correct rate is available, show that as the final rate in the app - ideally, it should be possible to do this within 24 hours of the transaction taking place
  • Instead of charging the linked credit card the full transaction amount immediately, put a hold on the "indicative" amount, and put through the full charge only once the real exchange rate is known.
Sadly, I think the chances of this being changed correctly are very, very slim!