1. Rate Limit every API
Your APIs are either public
or protected/private
. Irrespective of whether hey are public
or private
, they need to be Rate Limited
. Let’s consider a couple of scenarios why this is needed:
An Example
Let’s consider an API that accepts an email address and checks its internal database to see if the email address is a member. If the email is a member, then it sends an automated email and returns 200 OK
. If the email is not a member, it does not send an email and returns 404 Not Found
status.
An attacker can exploit this situation in two ways:
- If the attacker knows email address of a valid user, he would simply call this API in a loop thousands or millions of times. This floods your users inbox, increases your email service (sendgrid, SES) bills.
- If the attacker does not know a valid email address in the system, he could continue to guess until he finds one (basically an
Enumeration attack
.
Solution
Rate limiting
will alleviate this. You allow only certain number of API calls per minute (or per hour) from a specific IP address. Once the rate is exceeded, then your API should return 429 Too many requests.
Implementation of this solution can vary based on your stack. At the simplest level, this could simply be a per-API per-hour hashmap with client IP address as key and number of hits as value. At the top of every hour, simply clear out hashmap. Or you can depend on your web server. Apache has mod_ratelimit and Nginx has ngx_http_limit_req_module.
2. Validate every input
RESTful APIs accept input either via URL GET request parameters or via request body in case of POST/PUT or via HTTP headers. These allow opportunity for the attacker to inject scripts into your API tier.
A few guidelines
- Treat every single input coming from API client to be untrusted data. Even if it is the data sent by your API to the client in the previous API call.
- While validating inputs, prefer
whitelists
overblacklists
. - Strongly type every input parameter coming into your API.
- Look for validation libraries in your platform. Google for regex patterns that are readily available for most common inputs. Building your own input validation framework should be your last option.
- Test, test and test some more.
3. Use a WAF
Your REST APIs is a web application. Put it behind a Web Application Firewall (WAF). Though WAF will not solve all your security needs, it gets you closer. Plus it blocks a ton of annoying and malicious web requests (unwanted crawlers, port scanners etc.) reducing distractions
4. Restrict who can access the APIs
Based on who your API’s customers are, the following advanced options may be viable to you.
- IP Based Filtering: If your customers are calling you from their server side, you may be able to insist that they call you from a static IP address. You only allow known IP addresses and block everything else. Any basic firewall will let you do this.
- VPN: Insist on a VPN tunnel between API client and your API server.
- Certificate Based Authentication: Enable Certificate Based Authentication for your APIs. No client without the certificate will be able to call your APIs.