Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I know that you use tokens to prevent CSRF, but how should the receiving page respond when it is attacked? Should it fail silently, pretending the transaction was successful? Display an error message? Log the attack?

Please explain your reasoning for your answer as I'd like to understand the why behind a best practice.

Edit:

Some of the answers so far seem to advocate giving the users an error message of some sort. One part that I didn't think of when I asked this question is the possibility of false positives. Maybe I'm just not being imaginative enough, but I'm having a hard time creating a scenario where a legitimate user would be mistaken as a CSRF attack in the course of normal use of a website. Can anyone explain how this could happen? How would the CSRF error message ever appear if a CSRF wasn't actually in progress?

If a user can accidentally trigger a visible CSRF error message, I guess I can see the point, but if they can't, I'm not sure why you would want to display one. Presumably the attacker would know that they are attacking, so giving them an error message seems either pointless or giving them more information than they should have. If someone could clarify, it would help me understand it more fully.

share|improve this question
    
It depends on how you issue anti csrf tokens, but the simplest example is when you generate new token (& invalidate old ones) when displaying form. As soon as your users start opening your website in additional browser tabs, they are unwillingly invalidating their tokens and will get error messages. Another possibility is when tokens time out. –  Krzysztof Kotowicz Nov 5 '11 at 8:37

3 Answers 3

I usually recommend all exceptions and errors show a standard error page, and it should not reveal why the error/exception happened - or what the error was. Log the error, and give the user the log transaction number.

The reason I wouldn't reveal what happened, i.e. this action was refused due to a potential CSRF-attack, is that the attacker gain information on how the site protects against such an attack. (Of course in the specific case of CSRF this is revealed by the occurence of tokens, but I believe you should not reveal more information than absolutely necessary in any case)

share|improve this answer
    
Displaying the specific error is a trade off between availability and confidentiality. Not displaying the specific error makes attacking harder, but it may make debugging harder. –  this.josh Oct 28 '11 at 23:13
2  
@this.josh: You can still log the errors. Just don't mix up technical error logging with useful user error messages. –  tdammers Oct 29 '11 at 9:15
    
I would go this route if there was a chance the behavior difference would act as a cartographic oracle, revealing the key/seed. –  makerofthings7 Nov 5 '11 at 4:47

In case you are using a secret token solution to counter CSRF attacks. There can be many response strategy in case you do not receive the secret token in your request where you expected it ( I will not go into when you should include/exclude the tokens). You need to keep a balance between usability and security

Some of possible response to user can be

  • Invalidate the session and take the user to the generic session expiry page. THis page can be common page for idle timeouot, use of back/refresh button etc. THis should be considered for web sites like transanctional, handling very sensitive data etc.

  • Do not invaldte the session, ask user to renter the password

  • Redirect user to a confirmation page before processing the request

In all cases you should log this as a security event.

share|improve this answer
    
Nice discussion of session instead of just the attack and mechanism. –  this.josh Oct 28 '11 at 23:09

There seem to be two driving forces here. What do you want to tell the end user, and what do you not want to tell the attacker. The most damaging piece of information you could disclose may be any timing information relating to the error output.

Then again, in some CSRF attacks the errors can be visible, while in other attacks the errors may be suppressed or hidden. That would make me want to take these actions in a high security site:

  • Terminate the session, and any "upstream" sessions that may be related to OpenID or federation.

  • If the user is signed on using multiple tabs, redirect them to a page that informs them:

    • This may be a result of a second browsing session / tab that is open.
    • Tell the user to o prevent this from happening again, close all browsers and only browse one site at a time ( or use a browser that supports this security natively )
    • What happened (bad guys tried to do xxxx to yyy) (Careful to not echo data from the attacker or else this opens you up to XSS)

At first I liked the proposal here to go to an "edit" screen that allows a user to verify the changes that are being attempted. Then I thought about the possibility of click-jacking and how that can remove any benefit of this. Then again, I don't want to enable a unsupported "feature" of my site where external users can pre-fill out a form on someone's behalf. I'll offer a dedicated endpoint for this purpose if it's desired.

Other actions I like so far when handling an error include:

  • Throttle (Thread.Sleep) connections that encounter any of the following trends

    • Errors by IP address source (Careful if the source is a NAT'd user with thousands of machines behind it)
    • Errors by Referrer (Careful to prevent a system wide DOS)
    • Target Page (Controller/View) (yes this can DOS as well)
    • Logged on user (or anonymous user)

    If you notice that a combination of those factors is causing many of your CSRF alerts, you can slow down and throttle or deny connections until conditions improve. One metric could be errors / time.

Although most implementations allow for a seed, ASP.NET MVC in particular makes it easy to implement a constant (compiled-in) seed throughout out site. This constant may encourage attackers to try to guess what your seed is. To prevent this I'm pasting in some ASP.NET MVC code that addresses a few issues

  • Enables a dynamic seed
  • A centralized place to initiate your logging and exception tracking from all controllers.
  • Cryptographic Oracle disclosure prevention by sleeping a fixed amount of time before an error is generated and sent to the client. This is of course inspired by Scott Gu's ASP.NET mitigation, with the added feature of sleeping for a fixed amount of time vs a random amount of time.

To start, look at this blog for the base implementation. Then modify the OnAuthorization method like this

    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        TimeSpan maxSleepDuration = new TimeSpan(0, 0, 0, 0, 700); //Errors will always take 700ms
        DateTime timeStart = DateTime.UtcNow;

        base.OnAuthorization(filterContext);

        string httpMethodOverride = filterContext.HttpContext.Request.GetHttpMethodOverride();
        if (this._verbs.Verbs.Contains(httpMethodOverride, StringComparer.OrdinalIgnoreCase))
        {
            try
            {
                this._validator.OnAuthorization(filterContext);
            }
            catch (HttpAntiForgeryException e)
            {
                //todo: Custom actions here?  Track the IP? Referrer? Do special actions based on IP?

                TimeSpan timespent = DateTime.UtcNow - timeStart;
                int sleepDuration = maxSleepDuration.Milliseconds - timespent.Milliseconds;
                if (sleepDuration > 0 && sleepDuration != System.Threading.Timeout.Infinite)
                    System.Threading.Thread.Sleep(sleepDuration);


                //todo: Error here, or redirect back to validation screen
                throw e;
            }
        }
    }

Lastly, you may want to verify your MachineKey is not set to autogenerate, and ensure rotation of this key in your ITOps schedule.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.