0

Setup

  • Restful API and thin JS web client
  • Login POST Endpoint using parameters email and password
  • Access-Control-Allow-Origin is set, so responses can only be retrieved from non attacker website. However, as per specs, a pre-flight request is not issued to the Login endpoint.

The Attack

A malicious website can make requests to the Login endpoint without the user knowing. The response can not be retrieved by the browser, however the requests still go through.

Why is this bad? At the very least the attacker can rate limit the users IP address. If they target a specific email, they can make it look like a DDOS using many (real user) ip addresses and lock out the email. If they have access to the network traffic they can even analyse the response package size to determine if a login attempt was successful (Distributed Brute Force).

Sort-of-solution

What we've done so far is adding a xss token that is tied to the requesting IP address. The token is first retrieved through a separate endpoint and then required to be submitted to the login endpoint. The login attempt is made only if the token is valid and matches the requesting IP. This prevents the above attack.

This unfortunately only works if the users IP doesn't change between requests. This is now becoming a problem as some users are using services like Tor or Onavo. These users can no longer use our system.

Additional Information

  • We can't use browser cookies or browser local storage
  • Browser might not send referrer if so configured by user
  • Here is an attack that would work if the token was not tied to the IP address: enter image description here

Question

Should we worry about this attack or just drop the xss token requirement? Is there a better way to prevent this attack? How do other services solve this?

19
  • 1
    XSS tokens? You mean XSRF (CSRF) tokens? Even if your users use Tor, the IP is not changed in every request because it will use one exit node until the Tor user decides to change this.
    – Jeroen
    Commented Sep 12, 2017 at 17:16
  • Sure, name of the token isn't that important. It's not to prevent a Csrf attack, so calling it Csrf token is misleading.
    – vincent
    Commented Sep 12, 2017 at 17:18
  • Ok, can you please elaborate a little bit more on what you mean by an XSS token? Session token?
    – Jeroen
    Commented Sep 12, 2017 at 17:20
  • 1
    IP change on every request is exactly what we are seeing from Onavo. So this is not a theoretical use case. I'm pretty sure you can configure Tor to do the same.
    – vincent
    Commented Sep 12, 2017 at 17:22
  • 1
    Let us continue this discussion in chat.
    – Jeroen
    Commented Sep 12, 2017 at 18:31

2 Answers 2

1

tl/dr Your setup assumes that an attacker can't read requests from your server. This is only true for in-browser requests. However, a login endpoint doesn't use cookies so is not authenticated and therefore an attacker has no reason to be making requests in browser. As a result a core assumption you are making (that the attacker can't read responses from your endpoint) is invalid, and this security step is largely useless. Now that it is causing trouble for your end users, you should ditch it all and stick with more common brute-force monitoring. Off-the-cuff security measures tend to create more problems than they solve - stick to the basics. I don't think anyone attempts the kinds of attacks you are worried about anyway. A full site DDoS is probably easier, so no one would bother trying what you are worried about.

There is definitely some confusion of terminology going around that I think is worth addressing. Most importantly, you keep using the term XSS but this is not an XSS attack. I agree, your concern isn't exactly a CSRF attack, but it definitely isn't an XSS attack either. The reason is because you seem to be under the assumption that such malicious attacks would come from a browser: in a case like this they absolutely wouldn't (which is why this isn't a XSS attack).

This is more than just me being pedantic. You mention in your original question that about Access-Control-Allow-Origin and other CORS settings, and state that a malicious user could hit your endpoint but not read the response. Again, this is only true from requests made from a different domain in a browser, but in a case like this there is absolutely no reason why a malicious user would be using a browser. The only reason you would work from inside a browser is if you are trying to take advantage of a user's cookies for authentication (which is the case for CSRF attacks). however, this is a login endpoint, which means there are no cookies, and presumably therefore no reason why the attacker needs to be doing anything from inside a browser. That is to say:

A malicious attacker could use any HTTP client to make these login request, they wouldn't be affected by CORS rules, and would absolutely be able to see the response from your server

As we'll see, this fact invalidates the assumptions you are making about your security, and the end result is that your chosen security step is not actually securing anything. A malicious attacker hitting a login endpoint doesn't need to worry about pre-flight responses, CORS, access control headers, or anything else, because those are only relevant to HTTP requests made by javascript running in a browser, and they would most likely be using scripting tools making HTTP calls from outside of the browser.

Back to your question

So you have this extra security step in place to (effectively) try to prevent malicious attackers from attempting various DoS attacks on your login page. You specifically mention these concerns:

At the very least the attacker can rate limit the users IP address. If they target a specific email, they can make it look like a DDOS using many (real user) ip addresses and lock out the email. If they have access to the network traffic they can even analyse the response package size to determine if a login attempt was successful (Distributed Brute Force).

As stated, your current step is not actually protecting against most of this. In particular, there is absolutely nothing stopping a malicious hacker from setting up scripts on dozens of different of ip addresses (even just rent-a-vps from a cheap hosting provider), hitting up your GET endpoint to get an access code, and then (with the same IP of course) hitting up your login endpoint with that access code and a chose user's email address. This will look like a DDoS of a user's email address (because it is) and from the sounds of it will result in that email address being locked. They don't need to bother analyzing network traffic to see if the response is successful because they will be able to read the response themselves. Again, it sounds like you were assuming no responses from your server could be read, but this is only true for browsers, and does not impact HTTP requests from any other HTTP client.

Your security will prevent a malicious attacker from performing a DoS with the user's IP address (which could happen if the attacker can get the user to visit a page that has javascript they control), but that doesn't matter. At that point in time you are talking about a malicious attacker that is clearly targeting your system and/or users, and as such the attacker will have no trouble figuring out how your login flow works and performing the above attack to lock out an email address or even brute force the password.

All that to say: regardless of whether or not this attack is a general concern on the web, the method you have chosen to defend against it and which is causing trouble for your customers is not actually providing any real protection for your system at all. As a result, the overall answer is easy:

Ditch this security step and make life easier for your users

You also asked:

Should we worry about this attack?

The answer is a simple no. Technically things are rarely yes/no in security, and the answer is always "It depends on the level of risk you are willing to accept and your expected threat model". However, unless you have reason to specifically expect this kind of attack in the near future, I would say that it is not a concern at all. I've never heard of such an attack happening in practice.

You should have monitoring to try to detect and block brute force attempts against your login page, and you should tie that protection to IP addresses (the details vary, but in essence it is very reasonable to start blocking repeated failed login attempts for the same ip address). However, I don't think you have to worry about a malicious attacker getting javascript in front of a user to get them to black-list their own IP address (which is essentially the attack you are worried about). While that is certainly possible, I don't think I've ever heard of such an attack happening in practice - it would have to be a targeted attack and the gains would be so minimal, I doubt anyone would bother. If someone really wanted to lock people out of your system they would probably have better luck (and an easier time) just doing a rent-a-DDoS and completely shutting down your entire site anyway.

2
  • 1
    @JoshuaJones Done - sorry, I forgot that I can be very long-winded Commented Jun 29, 2018 at 14:27
  • Excellent answer. It could also be worth explaining to the OP what an XSS attack exactly is, since he misuses the term, but as you brilliantly explain it has really nothing to do with the question asked.
    – BgrWorker
    Commented Jun 29, 2018 at 15:36
0

The attack you are describing seems to be a CSRF attack. And the token you describe seems to be a CSRF token. These tokens are generally not tied to an IP address (for reasons you describe) but rather they are associated with a session (or session / page request).

Even login pages generally have CSRF protection to protect against Login CSRF.

1
  • Take a look at the difference between Csrf and xss attack. The browser has no information stored in our case, so this is not a Csrf attack. I agree there is a strong analogy between our approach and how Csrf attacks are prevented. However this does not mean that this is a Csrf attack. Session information is never stored in our case so it's (a) not part of an attack vector but can also (b) not used in any prevention mechanisms.
    – vincent
    Commented Sep 15, 2017 at 14:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .