Pentesting an API for Fun and Learning
Let’s see how to pentest an API and what all to look for!
--
So today I spent most of the time (pen)testing an API just for FUN!
And I found out loads of issues with how it was built. So I thought to share that knowledge and maybe make you aware on how you can test an API, that is, what all to look for. I will mostly show you how to start and grab the low-hanging fruits that even I look out for. And then, depending on how things go in my pentests, I go deeper if I see any potential vulnerabilities.
Playing with the target
I got an API to (pen)test for potential issues and I was handed over the API spec as well, so therefore, I knew what all APIs are there and what parameters do they expect, etc, etc.
Tools of Trade
I chose Postman for this (pen)test, just because I could define the API collection there (with all the APIs that were in scope for this pentest assignment) and since it can also work well with BurpSuite, so why not!
Prep Work
I had setup Postman with all the APIs that were the part of this pentest:
- Created a collection for this project
- Added all the APIs in it
- Defined the API specific params and request payload
Initial Testing
Initially, when I test an API, I interact with it normally — sending the expected parameters and checking back the responses.
This helps me see if the APIs are returning any excessive data or not.
These bugs are quite easy to locate and thus they happen to be first on my list to look for.
But in this API, I hadn’t found any such issues. It was a platform API — think of it like an API powering NewRelic-like product used for internal purposes.
If I found anything interesting, I jot it down for reporting and also for updating these params in the other requests (for checking broken object level authorization).
Oh btw did I tell you that all the requests worked without an API token as well — broken authentication (except for the dashboard retrieval and deletion API)! Another easy one down the lane!
Now things became quite interesting! The API let’s anyone make requests. This already was quite a serious issue.
But I thought not to stop here and see how far I can go with it.
Then I decided to tamper with the parameters and see if sending wrong parameters works or returns error or worse — crashes the application code, sending back 500 errors!
And what I found was that all the API happily accepted the parameters sent by me, without any validation!
Also, when the input was something unexpected — for instance sending a string when an int was expected — returned back 500. That’s not a security issue but a UX issue!
As a developer you should handle all your errors properly! And it’s quite important to get notified of any errors that happen in production.
For that, you can use Sentry or Rollbar! Maybe there are more, but I was satisfied with Sentry and Rollbar and didn’t had to look much further :)
Anyways back to the pentester’s world!
Sweet! That’s another one of those dumb mistakes I see quite a lot.
So I now knew there’s a lot more juicy stuff I can get out of this API hopefully.
I thought to try out rate-limiting checks too, because why not! They are quite easy to carry out and I can see how the APIs handle that.
I opened the Postman Runner and ran all the APIs 200 times just for fun!
What I found was:
- There was no rate-limiting at all!
- A bunch of 500 errors occasionally.
- Arbitrary parameters get accepted by all APIs (already saw this one, nothing new)
Nothing very juicy, just got a point that rate-limiting should be added to avoid API abuse — DoW (Denial of Wallet), DoS (Denial of Service), or bruteforce attacks, but other than that I didn’t found any other issues here.
So I moved on to testing other APIs.
Going Pro!
Next I looked for authorization issues, including both broken object level authz and broken function level authz as well as Mass Assignment!
APIs relating to dashboard & alerts retrieval and deletion were interesting because those expected the user id and if I could export dashboard of other users or delete their assets, it could be much more fun!
So I tried to look for these issues and surprise surprise… the authorization checks were broken! All I had to do was — specify the user id of the victim and check the response. No magic. The user id’s were quite big — 10 characters (regex →[A-Za-z0–9]), so bruteforcing was not such a good option I suppose.
And therefore I left this out as is, since there wasn’t a way for me to leak someone’s user id in the first place.
Tried Mass Assignment too, but no luck there xP
Going Expert ;)
Now I was done with all the issues I wanted to try out except the last one — my favourite — Injections!
Command Injection looked impossible due to no such requirement of using OS interpreters, so I didn’t had to go down that road.
SQL Injections then? Yes I looked for this and surprise surprise, even in 2021, a developer was so naive to have added SQL Injections in their code!
It would definitely look something like I had shown here:
So I got the prelim checks all working:
- Added a single quote and things broke in the backend — got 500 errors
- Added a ’ OR 1=1 -- and it worked like a charm (ofcourse URL encode your payloads if they are passed as GET params!)
Now I thought to use sqlmap and see how far it can take this — I was expecting the dump of the DB — maybe some API tokens, password hashes (and credit cards too?? haha).
Things looked quite promising when sqlmap confirmed the SQLi, but then came the biggest hurdle — the database couldn’t be detected by sqlmap :/
This was bad. I checked online but didn’t found much to carry on this route. So I had to add the word “potential” to this bug — A “potential” SQLi! Not a huge fan of this drama but at the end of the day if someone finds out the DB and exploits this vulnerability, it’s an issue!
Going Full Force with last 2 tests
Lastly, I just thought why not try out Host Header Injection issues and some business logic flaws!
Host Header Injection issues are quite fun and if I found something, then I could probably have SSRF or web cache poisoning or maybe more.
Went that route but had no success there :/
Then my last hope was business logic flaws and guess what I found some — I was able to bypass they constraints that they had in the battle-tested APIs but not in these staging ones! So I was able to perform restricted actions without getting blocked and locked out. Sweet :)
Reporting The Issues
Btw the time was also limited for this assignment and thus I couldn’t go in all random directions.
So I stopped my testing as soon as I tested for the last set of issues mentioned above.
But all in all I think my findings were great and well received. This made my day :)
I also gave some remediation steps to avoid these issues in the first place. Looking forward to the patched APIs for further testing!
Closing Thoughts
How was this article? Fun? Boring? Insightful?
Let me know your thoughts! This is the first time, I am writing something like this.
I chose this style because to be honest, I myself am more interesting in knowing the procedures, not just knowing the bugs and sitting there!
I hope that this post ends up giving you some motivation and probably a set of definitive steps on how to go about hacking APIs!
The post doesn’t discloses the details because I am not allowed to talk about the intricacies. But I hope the idea is still reflected and the methodology is the main takeaway, not the API details.
Because at the end of the day, you might be pentesting a different API and thus you don’t need to know the API details but the details on how to hack one ;)
If this post gave you any insights or was fun to read, you can help me by sharing it with your friends and colleagues in the infosec and even developer communities.
Let me know your feedback in the comments below and feel free to connect on twitter: @_SecurityGOAT
You can also send any topic you wish to learn more about. Let me know in the comments :)
Lastly, the line which should mostly be a plain ol’ boring one which I have to copy from my previous post every single time!!!! — if you have been enjoying my work and would love to support me, consider checking my Patreon page or you can even Buy Me a Coffee :)
And also, get ready for more fun posts! I have more fun ideas lately and planning to expand more, with more technical content for your brain muscles!
So help me spread these posts around to help make infosec more approachable for the beginners and more fun for the GOATS ;)
See ya!
Until next time my friend, keep learning and happy hacking.