Sometimes you need a combination of persuasive and technical writing in the lovely land of bug bounty hunting.
Recently, I found and exploited a particularly juicy Broken Object Authorization issue in a web app which led to a sensitive data dump (including medical data).
Intended Use Case:
Users are allowed to view their records as long as they provide their last name and "secret number". For example, a normal use case might be a user entering "MacDonald" and "12345". If they don't provide the name, they receive an error that both fields are required. Likewise, if they only provide a number? Again, they receive an error.
The API transactions can be viewed by pausing the traffic in BurpSuite intercept, which looks something like:
/_api/web/lists/GetByTitle('_GET_THE_GOODS')/items?$filter=ID_NUM%20eq%20%2712345%27%20and%20NAME_LAST%20eq%20%27MacDonald%27
To me, that looks a whole lot like an OData query that is being used to control access to the records!
Unintended Use Case:
So, naturally, I paused the traffic and use something like a wildcard to see if I can return everything without the "required" number and last name... but the site couldn't return the data, or it was going too slowly. NOTE: be cautious about how you test wildcards in order to not accidentally DoS a web application!
For the proof-of-concept, I had to strategize: 1.) make sure I wasn't DoSing them by asking for to many records, and 2.) consider privacy and keep the exfiltrated to a minimum as part of responsible disclosure of vulnerabilities. So instead of a true wildcard in all fields (or removing all search clauses altogether), I used a common last name and removed ID_NUM field.
/_api/web/lists/GetByTitle('_GET_THE_GOODS')/items?$filter=NAME_LAST%20eq%20%27MacDonald%27
Success! It returned many different records for the given name, all associated with different reference numbers. It seemed like a cut and dry proof-of-concept...
Or Was It...
I wrote up the report, but unfortunately limiting the scope of my data dump caused a bit of confusion. They wanted to know "how I had gotten the reference number and name". I didn't. I explained again how the attack worked. So then they asked for a video. It still wasn't clear to them. Here, I started to question if my report was clear as mud. All the wording looked good, clear and reproducible step-by-step, so I exfiltrated a little more (again, very minimally to protect the innocent here), just enough to show that it could be any name or any number. Finally two months later, they understood the issue and acknowledged the exploit.
Unfortunately, instead of fixing the app (which likely would have required quite a lot of architecture-level redesign from what I'd seen), they decided to remove the functionality (at least for now). As of today, the look-up process is now done by emailing a human instead. I'm a big fan of automation wherever possible though, so I'm hoping that's the short-term "bandaid" ahead of an long-term deep architecture redesign.
Happy hacking, all!
No comments:
Post a Comment