The Optus hack is the third biggest breach of Australian consumer Personally Identifiable Information (PII) in history, with 9.8m customer records being exposed.
Optus maintains that the hack was a sophisticated attack, using rotating IP addresses to carry out the attack.
The Minister For Cyber Security, Clare O’Neil, and the Federal Government have slammed Optus, indicating that their belief is that Optus “left the window open”. It’s worth noting that this is a technique that has been in use so long it’s been consumerised into products that do it for you and even into browsers. For example, Brave Browser has a built-in ToR network routing and with about 40 lines of python code you can force new IP address circuits.
Who is right? Sophisticated attack or a gaping hole in security? Let’s look at thoughts from several analysts. While there is an ongoing criminal investigation, some of the details are under wraps, analysts are fairly sure they understand the nature of the breach.
It is so simple it’s scary.
Cardinal Sin 1 – Unauthenticated endpoint
There is some debate over whether the endpoint had authentication at ALL. Journalist Jeremy Kirk talked to the hacker responsible. They claimed it was a completely unauthenticated endpoint that they accessed the data through.
Optus has since taken the endpoint down so we can no longer validate this fact. If the hacker is correct then Optus had at least one endpoint that was completely devoid of any authentication or authorisation. You could have whipped up a curl script (a simple script that kids learn in school) and have made a request against this endpoint with no login credentials.
If this is true it wouldn’t be a particularly sophisticated hack. You can’t exactly call it a security breach if you don’t have any security.
There is some contention over whether or not the endpoint was secure. Some analysts believe that it at least had some kind of cookie based authentication. In code samples of API consumers we can see that cookies are set, but without insight we may never know.
If we give Optus the benefit of the doubt and assume it was an authenticated endpoint then surely with a secure endpoint there’s no way for this breach to have occurred? Unfortunately, this brings us to the next attack vector.
Cardinal Sin 2 – Insecure direct object references
Back in 2007 OWASP brought the IDOR (Insecure Direct Object References) vulnerability to the forefront of people’s attention by placing it at number 4 in their top 10 most critical risks to web applications.
What is an IDOR vulnerability? Let’s take a look, we can use Optus as an example (thanks to @onejvo for breaking this example down for us).
This is code pulled from a public github repo that talks to the endpoint in question (the hacker and one other anonymous source confirmed the endpoint with Jeremy Kirk).
Line 78 defines an endpoint. It looks rather harmless, It has two query string params and an ID as part of its route.
- Customer Number
- Account Number
- Subscription ID
Analysts currently believe that this endpoint did not use the authorised user to vet access to the customer data. Instead it relied solely on the customer number parameter passed in the query string.
Let’s look at this part here:
It’s a pretty common REST-ish pattern. A noun that describes the object you’re accessing then an ID to indicate the ID of the noun you want.
Hypothetically, let’s say I’m logged in as user Roy. My cookie has the auth state for Roy but I make this request:
Does the API give you Deckard’s data?
It shouldn’t but in the case of an IDOR vulnerability it will incorrectly give you Deckard’s data.
Let that sink in. It will give you a different user’s data.
If a nefarious actor knew other customer numbers/ account numbers or Subscription IDs i could do the following:
- Find the Customer/Account/Subscription ID of some other random Optus customer. Let’s use Deckard again.
- Log in as Roy, an actual Optus customer.
- Reusing the auth state for Roy, make the above api call but, pass in Deckard’s IDs.
- Receive Deckard’s data.
- Upset Deckard
In this example we can see that IDOR vulnerabilities usually result in horizontal privilege escalation (that is the same level of permission but across different users) but there are cases where it can result in vertical privilege escalation (accessing additional permissions)
How do you fix it, you say? If you’re impatient you can scroll to the end but first let’s address the thing you’re hopefully thinking about.
Item 1. Finding another user’s ID
The IDOR vulnerability hinges on a hacker’s ability to get their hands on other users’ IDs)
Which brings us onto Cardinal Sin number 3. (Which technically is more of an ordinal sin. )
Cardinal Sin 3 – Enumerable Keys
By itself isn’t a critical issue but combined with the above issue there is a huge problem with having primary keys and IDs that are predictable.
What do we mean by enumerable keys?
I’ll spare you the math and instead lean on another example:
We used Deckard and Roy as example customer IDs above. (They’re unlikely to be actual primary keys, but it’s way easier than just a list of GUIDS). Let’s just add some for completeness’ sake:
set1 = [“deckard”, “roy”, “jessica”, ”gaff”]
And now perhaps a more reasonable set for comparison:
set2 = [“Customer–1”, ”Customer-2”, ”Customer-3”]
Set2 is enumerable because we can see a relationship between the natural numbers (1,2,3,4,….n) and the ID.
id(n) = Customer-n
Where n is a natural number 1,2,3,4,etc
Set1 does not exhibit this at all. There is no function that turns 1-> deckard, 2->roy for all ids. Disclaimer: I mean a formal mathematical function. You could of course warm up your IDE and write a function that maps between ids and integers…hint: id(n) = set1[n]
Why is this important? It means that a hacker can just enumerate through all the customer IDs and using the IDOR vulnerability get details for the 1st customer, then the 2nd, the 3rd all the way to the nth. For Optus, n was roughly 10 million…
A hacker doesn’t need to guess at the user IDs. He or she can just loop through them all.
If you use integer primary keys. This is important for you! Integer primary keys are enumerable!
What do you need to do, right now?
Secure the unsecured
The obvious one is to secure your endpoints, don’t have unnecessarily open endpoints. They introduce vectors of attack that are simply not needed. Review any endpoints that have no authentication and authorisation.
Can I just get rid of enumerable keys?
No. Apart from being quite a huge undertaking, it doesn’t guarantee that those primary keys are not exposed elsewhere.. A great example would be trying to split a fare through Uber, you need to search and select another user. This means Uber needs to expose some form of customer Identifier.
Just because your primary keys are not enumerable doesn’t mean they are not exposed, on purpose and by design.
Fix any Insecure Direct Object Reference Vulnerabilities
Unfortunately IDOR types of vulnerabilities are implementation mistakes and there’s not an easy security layer you can just adjust. Instead you’ll need to change the implementation of the endpoints with this vulnerability.
OWASP put together a proposal for a general solution to addressing this type of vulnerability.
You can find the full writeup here.
The gist is, don’t use the real ids. Instead hash them! Any time you want to expose a primary key, don’t! Instead use a hashed key and look it up on the server side.
There are various paths to implementation out there, including building a hashtable on login of the ID’s a user has access to and looking up the hashed ID in that table for it to resolve to an actual ID.
I highly recommend at least having a read of the OWASP proposal and the comments from Eric Sheridan.