I was recently working on a requirement to log the number of breached sites a password appeared on when customers were registering (if that password had been breached at all)
Importantly, we are not logging the breached password itself (nor the hash of the password) – just the number of breaches that particular password appeared in (as per the Pwned Passwords data set)

So, to log this, I’m raising a custom Application Insights event, using the client side Javascript SDK.

Pwned Passwords implements a k-anonymity approach to protecting the hashed passwords, to prevent the necessity to call the API with the full password hash. You can’t validate the entire hash, by calling the API with it.
Instead, you call the API, supplying the first 5 characters of the hash.

For example, the SHA1 hash of ‘password1’ is e38ad214943daad1d64c102faec29de4afe9da3d
So, to test if ‘password1’ has been breached, we call the Pwned Passwords API, specifying the first 5 characters of that hash as a parameter:


That returns some 486 results in total. In other words, 486 breached password hashes start with e38ad
The results are all the suffixes of those hashes, along with the number of breaches that hash appeared on.
This way, we can validate if that password hash appears in the breached list, without giving away the password, or even the hashed password, by searching the list for the original password hash; minus the first five characters:
pwnedpasswords e38ad results

We can see that the suffix of our hash is in that list:

So far, so good, we can perform this client side quite easily, and send our custom event to Application Insights.

Here’s a documented, cut down version of the code I was using to do that:

This worked great.
The problem, however, is Application Insights, by default, logs dependencies, and other telemetry.

If we take a look at End-to-end transaction details of our logged custom event, we can see that before our CUSTOMEVENT is logged, we have a dependency – an Ajax call, to api.pwnedpasswords.com/range/e38ad

App Insights showing AJAX call to pwned passwords API

Our custom event, by design, contains the number of breaches.

In a lot of cases, this breach number was unique in the returned range.
In the case of ‘password1’ (at the time of writing) this number was 2391888.

When plain text searching for ‘2391888’ (the count, recorded in our custom event) we can see:
pwnedpasswords e38ad results - count

Join the prefix, to the returned suffix and we know the full hash is:

Because these are generally ‘weak’ or breached passwords, we can try a SHA1 reverse tool, such as: https://isc.sans.edu/tools/reversehash.html – which gives us the correct, original password: password1

The security risk here is incredibly low…

For a start, our Application Insights instance is obviously protected.
Secondly, not every password can be reversed. Also, the count may be something quite low, like 1, or 2 – hundreds of breached passwords returned in the range query may also have a breach count of 1, or 2.

However small the risk, I wanted to eradicate this, while still using the client-side Javascript SDK for Application Insights.
I’ve written a separate post on how to Hide Sensitive Data with Application Insights JavaScript SDK using a Telemetry Initializer

Another possible solution…

This would require the PwnedPasswords api to change slightly, but instead of returning the whole suffix of the hash, perhaps the last n characters could be returned.
By omitting 5 characters from the start of the suffix, the collision rate would be sufficiently low enough, but make hash-reversal impossible.

Just a thought…

Application Insights is incredibly powerful, especially when using the JavaScript Client SDK.

The problem is, sometimes we can be logging a little too much.

In a recent post, I explained how I needed to log the number of breaches a breached password had appeared on, using the Have I Been Pwned API.
The trouble was, since I was doing all of this client side, the AJAX request was visible as a dependency of my custom event log.
The AJAX request contained information that allowed me (or anyone with access to Application Insights) to piece together the full password (hash) in some cases.

My paranoid mind didn’t like this.
I needed to obfuscate the irrelevant data in the GET request to that particular API.

All I really needed to do is stop the Ajax dependency call logging the hash prefix part of my query to the api.pwnedpasswords.com endpoint.

To solve this, I created a very simple telemetry initializer.
This function runs for each piece of telemetry recorded, and checks to see if the target is “api.pwnedpasswords.com
If it is, it simply replaces (for example) /range/e38ad with  /range/{SHA} whilst still recording that the call was made.

Adding this just after initialising the Application Insights SDK did the trick:

Application Insights now receives this dependency call as /range/{RANGE} (as opposed to the actual hash prefix)

As some people know, I run a web development agency called Cohoda LTD.

As part of our service, like most development agencies, we offer web hosting. To keep things as lean as possible, we deliberately don’t try to host email servers ourselves, instead we set up clients with email on Google GSuite (or Office 365 if the client prefers)
I always (where possible) use CloudFlare for DNS, and found myself repeatedly entering the same MX records for each domain, time and time again.

CloudFlare has a handy “Upload DNS File” feature tucked under ‘Advanced’ at the bottom of your DNS entries.

Here, you can specify any file to upload (which must conform to the BIND format to work)
On upload, those DNS entries will be added.

Here’s one for quickly adding GSuite (Google Apps / Gmail) mx records to CloudFlare:

Simply save this as (for example) gsuite-cloudflare.txt and upload that when you want to quickly add Google Apps mx records to your domain in CloudFlare.

I travel from Farnborugh main to Waterloo reasonably regularly, and it works out cheaper for me to buy monthly season tickets, with a Travel Card (allowing travel on the underground and busses)

I was recently looking at how much extra a First Class season ticket would be than Standard Class.

Turns out, South Western Railway are charging a premium – for the Travel Card portion of the First Class ticket!

We can see this as follows:

Standard Class – Without Travel Card


Standard Class – With Travel Card


This means, the Travel Card portion of this fare is £82.90

Now, let’s take look at First Class season tickets:

First Class – Without Travel Card


First Class – With Travel Card


As before, we can work out the Travel Card portion of the fare:
£776.10 – £635.20 = £140.90
That equates to £140.90 for the Travel Card.

Charging £58 on top of the ‘standard class’ Travel Card portion.

Last time I checked (I travel on the tube most days) I couldn’t find a first class carriage?

Phishing with internationalised domains

While on a train this morning, one of my close friends sent me this WhatsApp message:

Adidas Shoes WhatsApp Message

The person who sent it to me is not usually someone to send out scams or spam, but, to me at least, this message, did not look legit. It smelled strongly of a phishing scam.

However, it was a link to adidas.com/shoes – so how was this going to phish me?
Of course they are not giving away 3000 free pairs of shoes! Are they?

Cautiously, I pressed on the link.
Obviously, I didn’t end up on adidas.com
Clicking on the link, I’m redirected to http://xn--adids-m11b.com/shoes – which contained a registration form, asking for all manner of personal details to claim my ‘free pair of shoes’

But, how did they get the link http://adidas.com/shoes to redirect to this dodgy site from WhatsApp?
Was Adidas hacked? No.
Can you change the text of a hyperlink in WhatsApp? No. (I tried)

The thing is, it’s not a link to adidas.com
It’s a link to adidạs.com

Two very different URLs indeed.
Look closely at the second ‘a’ in the domain. It’s not an a. It’s an ạ
More info on this character  – latin small letter a with dot below (U+1EA1)

Looking at the domain on my phone, it looks as though there’s a small mark on the screen under the ‘a’

This is known as an internationalised domain name, and this specific kind of ‘attack’ is a IDN Homograph (or homoglyph) Attack – https://en.wikipedia.org/wiki/IDN_homograph_attack

This technique is similar to some personalised, or “cherished” vehicle number plates in the UK.
A fine example of such a number plate is:

4lex number plate

The 4 is supposed to look like an ‘A’ in this particular example.
This is known as a Homoglyph – where 2 characters look alike.

So what’s the deal with xn--adids-m11b?

xn--adids-m11b is punycode – which when converted in to unicode, is adidạs

Punycode is a representation of Unicode with the limited ASCII character subset used for Internet host names

(thanks to Wikipedia)

You can try that out with this Punycode converter:

Just how dangerous is it?

For example, Chrome, and most other browsers will display the puny-code domain in the status bar when hovering over an href:

Safari, for example, can’t display the IDN at all:

safari idn

However, some chat-applications (WhatsApp included at the time of writing) display the link as it was written.


The first warning sign something is up – the redirection, or perceived redirection from adidạs.com to the punycode equivalent.

But for a lot of people, particularly those who are not tech-savvy, this small detail may go unnoticed. Particularly if the URL bar is hidden on some mobiles.

So the vector of attack (at least successful attack) relies on the user not noticing the punycode domain it is actually resolved to (or not caring – because they’re excited to receive the promised offer for example)
Or, more likely, them not understanding the correlation between what they click on, and where they end up.

Another technique IDN attacks deploy is a quick redirect to a similar but believable domain name.
In our adidạs.com/shoes example, the attacker could have registered something such as adidas-shoes.gifts
.gifts is a generic top level domain, just like .com .co.uk .org etc…

Now, setting the puny-code domain (xn--adids-m11b.com) to redirect to adidas-shoes.gifts – would create something that looks more realistic – at least to those a little less tech-savvy.

y tho

As I mentioned, in the Adidas example, they were phishing my personal data.
But these sites could quite easily display an official looking login page to that site (capturing your username / password)
Or a ‘buy now’ page – harvesting your credit card details.

The fact they have their victims trust that they are on the legitimate brand site means they are free to essentially do what they want.

Page 1 of 41