How to stop hack/DOS attack on web API

JavaAndroidHttpSecurity

Java Problem Overview


My website has been experiencing a denial of service/hack attack for the last week. The attack is hitting our web API with randomly generated invalid API keys in a loop.

I'm not sure if they are trying to guess a key (mathematically impossible as 64bit keys) or trying to DOS attack the server. The attack is distributed, so I cannot ban all of the IP address, as it occurs from hundreds of clients.

My guess is that it is an Android app by the IPs, so someone has some malware in an Android app, and use all the installs to attack my server.

Server is Tomcat/Java, currently the web API just responds 400 to invalid keys, and caches IPs that have made several invalid key attempts, but still needs to do some processing for each bad request.

Any suggestions how to stop the attack? Is there any way to identify the Android app making the request from the HTTP header?

Java Solutions


Solution 1 - Java

Preventing Brute-Force Attacks:

There is a vast array of tools and strategies available to help you do this, and which to use depends entirely on your server implementation and requirements.

Without using a firewall, IDS, or other network-control tools, you can't really stop a DDOS from, well, denying service to your application. You can, however, modify your application to make a brute-force attack significantly more difficult.

The standard way to do this is by implementing a lockout or a progressive delay. A lockout prevents an IP from making a login request for X minutes if they fail to log in N times. A progressive delay adds a longer and longer delay to processing each bad login request.

If you're using Tomcat's authentication system (i.e. you have a <login-constraint> element in your webapp configuration), you should use the Tomcat LockoutRealm, which lets you easily put IP addresses on a lockout once they make a number of bad requests.

If you are not using Tomcat's authentication system, then you would have to post more information about what you are using to get more specific information.

Finally, you could simply increase the length of your API keys. 64 bits seems like an insurmountably huge keyspace to search, but its underweight by modern standards. A number of factors could contribute to making it far less secure than you expect:

  • A botnet (or other large network) could make tens of thousands of attempts per second, if you have no protections in place.
  • Depending on how you're generating your keys and gathering entropy, your de facto keyspace might be much smaller.
  • As your number of valid keys increases, the number of keys that need to be attempted to find a valid one (at least in theory) drops sharply.

Upping the API key length to 128 (or 256, or 512) won't cost much, and you'll tremendously increase the search space (and thus, the difficulty) of any brute force attack.

Mitigating DDOS attacks:

To mitigate DDOS attacks, however, you need to do a bit more legwork. DDOS attacks are hard to defend against, and its especially hard if you don't control the network your server is on.

That being said, there are a few server-side things you can do:

  • Installing and configuring a web-application firewall, like mod_security, to reject incoming connections that violate rules that you define.
  • Setting up an IDS system, like Snort, to detect when a DDOS attack is occurring and take the first steps to mitigate it
  • See @Martin Muller's post for another excellent option, fail2ban
  • Creating your own Tomcat Valve, as described here, to reject incoming requests by their User-Agents (or any other criterion) as a last line of defense.

In the end, however, there is only so much you can do to stop a DDOS attack for free. A server has only so much memory, so many CPU cycles, and so much network bandwidth; with enough incoming connections, even the most efficient firewall won't keep you from going down. You'll be better able to weather DDOS attacks if you invest in a higher-bandwidth internet connection and more servers, or if you deploy your application on Amazon Web Services, or if you bought one of many consumer and enterprise DDOS mitigation products (@SDude has some excellent recommendations in his post). None of those options are cheap, quick, or easy, but they're what's available.

Bottom Line:

If you rely on your application code to mitigate a DDOS, you've already lost

Solution 2 - Java

If it's big enough you just can't stop it alone. You can do all the optimisation you want at the app level, but you'll still go down. In addition to app-level security for prevention (as in FSQ's answer) you should use proven solutions leaving the heavy lifting to professionals (if you are serious about your business). My advise is:

  1. Sign-up for CloudFlare or Incapsula. This is day to day for them.
  2. Consider using AWS API gateway as the second stage for your API requests. You'll enjoy filtering, throttling, security,auto-scaling and HA for your API at Amazon scale. Then you can forward the valid requests to your machines (in or outside amazon)

Internet --> CloudFlare/Incapsula --> AWS API Gateway --> Your API Server

0,02

PS: I think this question belongs to Sec

Solution 3 - Java

Here are a couple ideas. There are a number of strategies in addition, but this should get you started. Also realize that amazon gets ddos'd on a frequent basis and their systems tend to have a few heuristics that harden them (and therefore you) from these attacks, particularly if you are using Elastic load balancing, which you should be using anyway.

  • Use a CDN -- they often have ways of detecting and defending against ddos. Akamai, mastery, or amazons own cloud front.

  • Use iptables to blacklist offensive ips. The more tooling you have around this, the faster you can blok/unblock

  • Use throttling mechanisms to prevent large numbers of requests

  • Automatically deny requests that are very large (say greater than 1-2mb; unless you have a photo uploading service or similar) before they get to your application

  • Prevent cascading failures by placing a limit on the total number of connections to other components in your system; for example, dont let your database server become overloaded by opening a thousand connections to it.

Solution 4 - Java

The best way is to prevent the access to your services entirely for those IP addresses who have failed let's say 3 times. This will take most of the load from your server as the attacker gets blocked before Tomcat even has to start a thread for this user.

One of the best tools to achieve this is called fail2ban (http://www.fail2ban.org). It is provided as a package in all major linux distributions.

What you have to do is basically log the failed attempts into a file and create a custom filter for fail2ban. Darryn van Tonder has a nice example on how to write your own filter on his blog: https://darrynvt.wordpress.com/tag/custom-fail2ban-filters/

Solution 5 - Java

If D-DOS is attack is severe, application level checks does not work at all. Entire bandwidth will be consumed by D-DOS clients and your application level checks won't be triggered. Practically your web service does not run at all.

If you have to keep your application safe from severe D-DOS attacks, you do not have any other option except relying on third party tools by paying money. One of the Clean pipe provider ( who sends only good traffic) tools I can bank on from my past experience : Neustar

If D-DOS attack is mild in your website, you can implement application level checks. For example, below configuration will restrict maximum number of connections from single IP as quoted in Restrict calls from single IP

<Directory /home/*/public_html> -- You can change this location
    MaxConnPerIP 1  
    OnlyIPLimit audio/mpeg video
</Directory>

For more insight into D-DOS attack, visit Wiki link. It provides list of preventive & responsive tools which includes : Firewalls, Switches, Routers, IPs Based Prevention, D-DOS based defences

and finally

Clean pipes (All traffic is passed through a "cleaning center" or a "scrubbing center" via various methods such as proxies, tunnels or even direct circuits, which separates "bad" traffic (DDoS and also other common internet attacks) and only sends good traffic beyond to the server)

You can find 12 distributors of Clean pipes.

Solution 6 - Java

For a targeted and highly distributed DOS attack the only practical solution (other than providing the capacity to soak it up) is to profile the attack, identify the 'tells' and route that traffic to a low resource handler.

Your question has some tells - that the request is invalid, but presumably there is too much cost in determining that. That the requests originate from a specific group of networks and that presumably they occur in bursts.

In your comments you've told us at least one other tell - the user agent is null.

Without adding any additional components, you could start by tarpitting the connection - if a request matching the profile comes in, go ahead and validate the key, but then have your code sleep for a second or two. This will reduce the rate of requests from these clients at a small cost.

Another solution would be to use log failures matching the tell and use fail2ban to reconfigure your firewall in real time to drop all packets from the source address for a while.

No, its unlikely you will be able to identify the app without getting hold of an affected device.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJamesView Question on Stackoverflow
Solution 1 - JavaF. Stephen QView Answer on Stackoverflow
Solution 2 - JavasdudeView Answer on Stackoverflow
Solution 3 - JavaPranavView Answer on Stackoverflow
Solution 4 - JavaMartin MüllerView Answer on Stackoverflow
Solution 5 - JavaRavindra babuView Answer on Stackoverflow
Solution 6 - JavasymcbeanView Answer on Stackoverflow