29

I have created a login module on my website. I was able to deal with simple brute force attacks since I can identify the user based on username/email and throttle their login based on failed login attempts per user account.

But when it comes to user-enumerated brute-force attacks (a.k.a. Reverse brute force attacks), identifying the user becomes pretty hard. Throttling the login based on failed attempts per IP address might not work well and annoy the users connected to the Internet through a local network since they'll have same external IP address, as they might face throttle due to failed attempts made by someone else on the network.

Is there a way to uniquely identify such users?

ashu
  • 457
  • 1
  • 6
  • 12
  • 6
    I don't think that the collateral damage caused to other users from the same IP (and hence likely from more or less the same locality) is necessarily a disadvantage. Instead, it might even be an incentive for these legitimate users to grab their torches and pitchforks and deal with the root cause of the attack – Hagen von Eitzen Feb 10 '15 at 13:08
  • 12
    I don't think it is possible for legitimate users to actually grab their torches and pitchforks on many networks. Large universities, WiFi access points (like at coffee shops), and certain ISPs are not likely to take effective action unless *everybody* on the network notices the rate limiting. In addition, it doesn't strike me as a good UX practice. – James Mishra Feb 10 '15 at 14:12
  • 1
    What's the chance an attacker who knows a valid username and tries to brute-force the password online using the same IP address as the legitimate user, and the legitimate user trying to login simultaneously, again from the same IP address, within a 10-minute window? I would say the impact is pretty small, but it's most probably something the user would like to be aware of. – Damon Feb 11 '15 at 10:49
  • You can use the system time transmitted in the HTTP header to find whether calls stem from the same computer or from different computers behind a NAT IP. – Alexander Feb 11 '15 at 14:09

5 Answers5

37

How to uniquely identify users with the same external IP address? Is there any way to uniquely identify such users?

Yes, there are lots of ways:

  • Cookies
  • Evercookies (JavaScript code that uses lots of different techniques to store identifying information, among them flash cookies, the various HTML5 storage options, the browsers visited links history, etc)
  • Device fingerprinting: use the HTTP header (mainly User Agent, but the other headers and their order can help as well)
  • Device fingerprinting with JavaScript: with JavaScript, you can get a lot of information, such as screen resolution, timezone, plugins, system fonts, etc.
  • Behavior: how fast do the users fill in forms, where on a button do they click, etc.

But most of these are not useful in defending against brute-force attacks, since the program doing them will probably not accept cookies or run JavaScript.

In your case, you might try:

  • HTTP header: these might actually already be enough to differentiate between users using the same IP address (of course, an attacker can just randomly switch them, but I would assume most currently don't).
  • Light throttling: you don't have to block IP addresses, you could just slow down the login process for them. That way, brute forcing becomes a lot less feasible, but real users using the same IP address can still login.
  • CAPTCHAs: these will annoy legitimate users, but hopefully not too many users actually use an IP address from which brute-force attacks originate (of course, there are tools to automatically solve CAPTCHAs, but it's still harder than no CAPTCHA).
  • You could require a user to accept cookies, and to send various identifying information before being allowed to login (such as the screen resolution, timezone, etc.). Of course, an attacker can do this as well, but I don't think any currently existing bruteforce tools can do this, so they would have to write a custom script. But this might also annoy legitimate users.
tim
  • 29,018
  • 7
  • 95
  • 119
  • I think HTTP headers will do the job of identification. Thanks! – ashu Feb 10 '15 at 10:48
  • 4
    I'd go with captchas -- if an IP or a subnet fails to log in too often, require a captcha before each login. – CodesInChaos Feb 10 '15 at 11:30
  • 3
    HTTP headers can be easily be changed by the attack. Captchas are annoying. I would recommend light throttling. – PiTheNumber Feb 10 '15 at 12:20
  • 3
    "the program doing [brute force attacks] will probably not accept cookies or run JavaScript.". That is of course a positive thing, not a negative. You can throttle clients without Javascript or cookies. – MSalters Feb 10 '15 at 12:55
  • @MSalters yes, that's what I tried to express (maybe badly :) ) in my last point. But then you reject/annoy users who disable javascript, and an attacker can of course also write a brute-force script that does accept cookies/runs javascript. But this does require extra work. As with all these methods, it's a trade-off between causing more work for an attacker and causing annoyance for legitimate users. – tim Feb 10 '15 at 13:10
  • 4
    With captchas, ReCaptcha's new method of just clicking a checkbox is very simple to use – Cole Tobin Feb 10 '15 at 19:56
  • @tim : Using Google's V8 rendering engine to write spambots is very easy. – user2284570 Feb 11 '15 at 11:32
22

You can get users' internal IP address even from the Internet by using HTML5 & WebRTC. You can check out the article Local IP discovery with HTML5 WebRTC: Security and privacy risk? for more information and try it on http://net.ipcalf.com/.

The website that serves the article seems down now. However, I think this artice WebRTC Found Leaking Local IP Adresses can give some information too.

Batuhan
  • 672
  • 4
  • 17
  • 6
    Interesting, didn't know this. – Michael Feb 10 '15 at 10:52
  • 2
    Keep in mind that this is self-reported by the client. It's not very useful for identifying normal users. (I am behind 2 NATs so many computers at my dorm think they are "192.168.1.2") – Navin Feb 11 '15 at 00:39
  • Your second link is a 502 (I'd edit but not sure what it was supposed to be) – James Oct 25 '15 at 15:38
  • @James thanks for noticing. It seems like website having some issues and I couldn't find any cached version because of the robots.txt of the website. I found another article and added to my answer. – Batuhan Oct 26 '15 at 12:22
5

There isn't a non-spoofable method to my knowledge. If you already throttle the max amount of attempts to eight tries per minute with a one minute time-out. A one minute time out is generally not considered annoying as long as you give enough information to the user.

Make sure to actively review these occurences where there are suspected bruteforces from an IP address as it might be interesting to investigate who's trying to bruteforce you.

Lucas Kauffman
  • 54,169
  • 17
  • 112
  • 196
  • +1 for throttling the max amount. But you mean 8 failed attempts per IP per minute? Right? – ashu Feb 10 '15 at 10:50
  • 2
    Lammas with hats? I love that show! But I disagree with ` one minute time out is generally not considered annoying.`. It is **VERY** annoying! And scares users away, thinking the code is broken or the website is a crap and slow and poorly made. – Ismael Miguel Feb 10 '15 at 10:53
  • That's what HTTP Status codes are for. – Lucas Kauffman Feb 10 '15 at 11:06
  • 4
    *'A one minute time out is not considered annoying'* as long as the developer proactively gives feedback to the user of what is going on. Much unlike how BitLocker doesn't even give you symptoms until you attempt after said timeout has triggered, and even then doesn't tell you what is going on, and ***any*** attempt during the timeout resets the timeout, and *still* doesn't explain to the user what is going on. So it can certainly be annoying as hell if implemented lazily. – Andrew Hoffman Feb 10 '15 at 14:29
4

Most other methods mentioned here are easily defeated and/or significantly reduce performance.

That is why web application firewalls (WAF) don't rely on them.

2 reliable methods are:

  • Analyze the packet sequence in the IP header: Most TCP/IP stacks number packets sequentially, so if the number is random, then the client is probably behind NAT (a shared Internet connection with other clients). There is some RAM overhead to remember the previous packet ID, but it's comparable to a session cookie. This is harder to spoof since the attacker needs to rewrite the packet at a low level, but not impossible, so it should be combined with rate limiting: allow NATted public IPs to have more hits/second.
  • Session cookies with cryptographic authentication: Normal session cookies are not enough. They aren't encrypted with HTTP, and even with HTTPS, they may not be part of an HTTPS-encrypted payload, and therefore not authenticated either. http://blog.teamtreehouse.com/how-to-create-totally-secure-cookies Do it properly. Make sure it's not just encrypted, but authenticated/"signed". http://spring.io/blog/2014/01/20/exploiting-encrypted-cookies-for-fun-and-profit If you only have access to the web app code, this is the better option. Obviously if cookies are disabled, then run a client-side JavaScript that distinguishes between browsers and bots (call for screen resolution, etc. that a bot would not support, and return bot status if the script fails). Combine this with rate limiting by authenticated session cookie or, if cookies are disabled, IP-based rate limiting ("throttling") or blocking. This accepts/rejects the request early in the IP/HTTP parser's routine, conserving future CPU cycles, since a brute force attacker may retry thousands of times. Due to DHCP/PPPoE/new session cookies, bans should expire after a few minutes. Keep in mind you should white list non-spoofed IPs of search engine crawlers like Google and Baidu. Otherwise your search rankings may suffer.

If you combine your solution with rate limiting, the correct rate limit should be 1-2 times the number of URLs per page. For example, if login.php includes 2 CSS files, 4 JavaScript files, and 10 images plus the 1 page itself, you must allow at least a total of 17 hits per client session cookie, per second. Otherwise you may be blocking/limiting normal requests.

For persistent attacks, you should ask your ISP to block/blackhole the route upstream.

Why not use the other solutions?

'User-Agent:' is very trivial to spoof:

wget -O index.html --user-agent="My Fake Browser"

Session cookies, 'X-Forwarded-For:' HTTP header, and other headers are also trivial to steal/spoof. Google 'Firesheep' or 'Cookies Manager+' or 'Modify Headers plugin' or 'LiveHeaders plugin' etc. for proof.

Rate limiting is not enough alone, either, because a stealth attack will randomize or increase wait time between requests:

wget --limit-rate=10 http://example.com/index.php

Brute force is usually not your only problem. https://www.owasp.org/index.php/Top_10_2013-Top_10 Coding and testing effective protection takes time, too. To save you time and/or CPU cycles on your web servers -- it's multiplied waste if you have a server farm -- your web host should offer a front-end WAF with this configured for you. That is the best solution -- don't do it server-side. Do it upstream.

3

Unique identification might be difficult, but there is the possibility to add server variables like User Agent and local variables like cookies (both of which can be spoofed and/or circumvented, but at least adds some variation alongside the IP address). If JavaScript is an option you could try browser fingerprinting (JavaScript or HTML5 Canvas)

Alasjo
  • 973
  • 6
  • 10