What made Citi’s hack much worse? How to avoid the same mistake?

Note: This series simplifies and analyze breach/exploit reports which are usually cryptic and legal led and to help other enterprises avoid the same mistake.

Hackers were able to acquire over 350K customer’s personal data from Citi’s web application. Citi managed over 21M customers when the breach happened. This breach exposed just over 1% of the customer data.

What was exposed?

How was this hack perpetrated?

Through an exploit known as parameter tampering for web applications and APIs.

How does the parameter tampering works?

For example, let’s take this simple scenario.

Let’s assume the vulnerable app had these endpoints.

GET: /customers/{account-number} // return customer info e.g. name etc
GET: /customers/{account-number}/accounts // returns customer account info etc
GET: /customers/{account-number}/contacts // returns customer contact info etc

Note: The {account-number} param can be a path param like the above one or could have been a query or body params like the example below. This exploit will still works across all the scanarios.

GET: /customers?account-number=val // return customer info e.g. name etc

Criteria for a successful attack?

This exploit will work if there is a flaw in the app’s business logic. A missing validation or a missing role assignment can allow any user in the app to request information belonging to any other user/customer just by knowing the other customer’s account numbers.

What made it much worse?

Predictable account numbers e.g. incremental numbers 100034567, 100034568, etc. This will allow an attacker to automate and steal large continuous numbers without having to fish specific numbers on the web.

What won’t work in thwarting these kinds of attacks

It doesn’t matter if these endpoints were secured. Attackers will usually use stolen credentials to access these paths.

It doesn’t matter if these endpoints were not disclosed on the customer web apps. There are several ways to identify non-disclosed endpoints.

Fuzz testing doesn’t detect these exploits.

Web scanners won’t help detect these exploits either, they focus more on injection and on fuzzing attacks rather than tailored scenarios like these.

Static code analysis won’t help either. These scenarios require live testing.

How to protect your Apps and APIs against these attacks?

Design best practice: never use Incremental IDs for record identifications in your database. Instead, use random UID’s. This will slow down the attack as it will be much harder to guess and fish UID’s.

Continuously scan & validate access-controls logic on all endpoints. As the product grows these vulnerabilities become a commonplace.

A Type-2 Scanner which looks in addition to injection attacks and looks for business logic vulnerabilities including RBAC, ABAC, Hijack, Sensitive Data Exposure attacks, etc.