Does Arachni support session long anti-CSRF tokens

Steven Phillips's Avatar

Steven Phillips

17 Jul, 2017 01:57 PM

Hi Tasos,

First let me thank you again for the nested cookies feature, its working perfectly - you closed the other thread before I could feedback on my larger tests which have found some problems that I would never have found without this feature, so thanks again!

I have one remaining issue that I'm not making any progress on and that's with the anti-CSRF check. I have a randomly generated 32 byte hex string which is generated once per session (not the most secure but I believe still deemed adequate and about the best I can do without severely compromising performance or usability, or probably both) and Arachni is claiming all but one form as being susceptible to CSRF attacks.

So I've created a simple test harness which has a 'home' page with a link to a simple 'Set name' page using a session variable to store the 32 byte random anti-CSRF token - this site reportedly works fine with no issues (only running csrf check). If I then duplicate the 'Set name' page (i.e. just copy to a new file name) so the home page has 2 link, one to each page that does exactly the same thing I then trigger a CSRF error for one of them but not the other.

The CSRF check reports the Vector information as:

name 
mems   Save changes 
sk         608da8d8d0dffcd696696d6e41d44613e

The 'sk' input is the anti-csrf token and I've tried renaming the input to 'csrf_token' but nothing I've tried avoids the 2nd page triggering a CSRF issue.

Is a session long anti-CSRF token still considered an acceptable security measure? Does Arachni support session long CSRF tokens? If so what am I doing wrong?

I can send you the test harness if it would help.

Thanks,

Steve

  1. Support Staff 1 Posted by Tasos Laskos on 31 Jul, 2017 07:32 AM

    Tasos Laskos's Avatar

    For forms Arachni will check whether or not the token gets changed after every refresh, if not then the form is deemed to have no nonce.

  2. 2 Posted by Steven Phillips on 31 Jul, 2017 04:27 PM

    Steven Phillips's Avatar

    Hi Tasos,

    Thanks for responding, I've been digging into this a lot more and also reading older threads such as 'CLI identifies XSS but not CSRF' which help explain the way Arachni's CSRF test has evolved etc. In the process of doing this I think I've found a bug in Arachni and the result of my research is that believe my approach to safeguarding against CSRF attacks is reasonable but Arachni can't currently be used to verify it - which is disappointing and I hope I'm wrong.

    Potential bug in Arachni first - to understand Arachni better I created a test harness with a Home page containing 6 links, 3 pairs, each pair edits 2 values and each pair having a different implementation of an Anti-CSRF solution. I found that which ever link I put first Arachni will not explore the sub-page fully and as a result it will not submit the 'Save changes' button and never discover the hidden page that it calls to 'save' the changes - this is why I had to initially duplicate the page because the first one is never followed properly.

    The main reason I really think this is an Arachni bug is because the page that is not fully processed is always, and only, determined by the link order, if I change the order the new first link page is the one not processed and any problems that page has (well CSRF at least) will not be found.

    I have verified the first page's form action page is never called by the server side logging and I'm using the latest overnight build. I can sent you this test harness or I can run tests etc.

    Now to CSRF - I can understand Arachni's move to require nonces to cut down on false-positives but this requirement seems to contradict Arachni's own 'Remediation guidance' which states:

    These tokens can be configured in such a way that each session generates a new anti-CSRF token or such that each individual request requires a new token.
    

    In my case I have a site with multiple objects that can be edited by multiple users at the same time using multiple tabs (i.e. one user can edit many objects at once using multiple browser tabs), trying to support individual request based anti-CSRF tokens is therefore difficult and thus I have gone for the much simpler session based solution which I believe is still considered secure as long as the site has no XXS vulnerability (and if the site has an XXS vulnerability then CSRF is probably the least of your problems?)

    But there appears to be no support for this approach in Arachni which is a shame as I think it could still do a lot without risk of false-positives. The simplest first step I can think of is to have a 'Session Anti-CSRF token name' parameter (or this could be a separate csrf_session check which requires a parameter) and if used the CSRF check changes to simply verifying this one input parameter exists and its value is suitably long and reasonable.

    For example if session_csrf_token_name was set to 'csrf_token' it would verify that every state changing form (or URL) had this parameter and set to a suitable value, making it easy to identify any unprotected forms.

    Does this seem reasonable and feasible?

  3. 3 Posted by Steven Phillips on 01 Aug, 2017 07:21 AM

    Steven Phillips's Avatar

    Hi Tasos,

    Thanks for responding, I've been digging into this a lot more and also reading older threads such as 'CLI identifies XSS but not CSRF' which help explain the way Arachni's CSRF test has evolved etc. In the process of doing this I think I've found a bug in Arachni and the result of my research is that believe my approach to safeguarding against CSRF attacks is reasonable but Arachni can't currently be used to verify it - which is disappointing and I hope I'm wrong.

    Potential bug in Arachni first - to understand Arachni better I created a test harness with a Home page containing 6 links, 3 pairs, each pair edits 2 values and each pair having a different implementation of an Anti-CSRF solution. I found that which ever link I put first Arachni will not explore the sub-page fully and as a result it will not submit the 'Save changes' button and never discover the hidden page that it calls to 'save' the changes - this is why I had to initially duplicate the page because the first one is never followed properly.

    The main reason I really think this is an Arachni bug is because the page that is not fully processed is always, and only, determined by the link order, if I change the order the new first link page is the one not processed and any problems that page has (well CSRF at least) will not be found.

    I have verified the first page's form action page is never called by the server side logging and I'm using the latest overnight build. I can sent you this test harness or I can run tests etc.

    Now to CSRF - I can understand Arachni's move to require nonces to cut down on false-positives but this requirement seems to contradict Arachni's own 'Remediation guidance' which states:

    These tokens can be configured in such a way that each session generates a new anti-CSRF token or such that each individual request requires a new token.
    

    In my case I have a site with multiple objects that can be edited by multiple users at the same time using multiple tabs (i.e. one user can edit many objects at once using multiple browser tabs), trying to support individual request based anti-CSRF tokens is therefore difficult and thus I have gone for the much simpler session based solution which I believe is still considered secure as long as the site has no XXS vulnerability (and if the site has an XXS vulnerability then CSRF is probably the least of your problems?)

    But there appears to be no support for this approach in Arachni which is a shame as I think it could still do a lot without risk of false-positives. The simplest first step I can think of is to have a 'Session Anti-CSRF token name' parameter (or this could be a separate csrf_session check which requires a parameter) and if used the CSRF check changes to simply verifying this one input parameter exists and its value is suitably long and reasonable.

    For example if session_csrf_token_name was set to 'csrf_token' it would verify that every state changing form (or URL) had this parameter and set to a suitable value, making it easy to identify any unprotected forms.

    Does this seem reasonable and feasible?

    Thanks,

    Steve

  4. 4 Posted by Steven Phillips on 21 Aug, 2017 11:21 AM

    Steven Phillips's Avatar

    Hi Tasos,

    Not seen a response to this and hoping I've not missed it (and sorry about the double post).

    Fundamentally I can see the need for the current csrf test and accept that this is checking for a more secure solution to the CSRF vulnerability, but this approach is not open to me and currently there is no way I can find to use Arachni to validate my session based anti-CSRF token is present and correct.

    How hard, and how would I go about, creating a new csrf_session check which verified that for all state changing submissions the given csrf token has been included and set to a suitable value?

    Thanks,

    Steve

  5. Support Staff 5 Posted by Tasos Laskos on 21 Aug, 2017 04:48 PM

    Tasos Laskos's Avatar

    Sorry I've been going back and forth for a while, summer vacations and whatnot.

    If I understand you correctly, you believe you've also found a bug in the crawl and audit irrespective of the anti-CSRF check situation?
    If so could you please open a bug on GitHub with a link to your test case?

    About the anti-CSRF check you propose, I don't see how that could be automated effectively. I'll give it some more thought and see if I can figure something out and keep you posted.
    I'm open to ideas btw.

  6. 6 Posted by Steven Phillips on 21 Aug, 2017 05:52 PM

    Steven Phillips's Avatar

    Hi Tasos,

    Yes I do think I've found an issue with the crawl and will cut the example down to as small as I can make it. I hope Classic ASP example is okay for you.

    I think I may not have explained my idea very well because I think it should be very easy to implement. I'm suggesting that when an Arachni configuration option is set/used it changes the way the xss check works - rather than trying to identify a nonce parameter (which I can't do for my site) it will look for the presence of a specific, pre-configured form parameter and check its value is reasonable.

    For example, lets first consider the current behaviour (as I understand it):

    a. Arachni determines if a site submission is state changing - if not End
    b. Arachni looks for a nonce - if not found report CSRF Error

    I'm suggesting that, given the new parameter is called 'anti_csrf_token', this is changed to:

    a. Arachni determines if a site submission is state changing - if not End
    b. If 'anti_csrf_token' is set then:
    b.1. Arachni looks for a parameter with the name of what 'anti_csrf_token' is set to with a suitable anti-csrf value - if not found or it has a trivial value then report CSRF Error
    c. Else if 'anti_csrf_token' is not set then:
    c.1. Arachni looks for a nonce - if not found report CSRF Error

    So if I don't set 'anti_csrf_token' there is no change in behaviour, however if I do set 'anti_csrf_token' to say "csrf_token" in my Arachni config then every state changing form Arachni simply needs to check for the presence of a "csrf_token" parameter a its value is good (i.e. long and random).

    I think this is good enough to give Arachni basic session-based CSRF support, which for me would be excellent.

    I have also got an Idea on how to further extend the xss check to give Arachni the ability to verify that the CSRF token is being checked, avoiding false positives, however this does requires sites to be implemented in a certain way (like mine is :-). Happy to document if you're interested...

  7. 7 Posted by Steven Phillips on 25 Aug, 2017 04:58 PM

    Steven Phillips's Avatar

    Hi Tasos,

    I have submitted a bug for the crawler issue. I was hoping to cut it down smaller but the issue seems a bit random and my attempts to simplify made the issue disappear :-(

    Shout if you have any problems reproducing the problem.

    Steve

  8. Support Staff 8 Posted by Tasos Laskos on 26 Aug, 2017 05:35 PM

    Tasos Laskos's Avatar

    Thanks for opening the GH issue.

    Btw, I'm confused again, you mentioned the XSS check in your second to last response, how is that related to this issue?

    Also, Arachni works much simpler than that, if there's a form and the form has an input value that changes after every refresh, then that value is considered a nonce and the form passes the anti-CSRF check, if not an issue is logged -- this doesn't work for cases such as yours.

    Regarding your suggestion, you really can't reliably and automatically test whether or not a form submission is state-changing and neither can you check if a nonce is actually being taken into consideration (lots of different and irrelevant input validations could be going on).

    Some things are impossible or impractical to automate and can create a lot more problems than they solve, I think this is one of them.

    In your case, the input name doesn't need to be configured as the specs for a good nonce are known and any input value (or even name) that matches them can allow the form to pass the check.
    Problem is, how do you check for those specs? A long value is of course easy to check, but randomness is trickier, you'd probably need to perform millions of requests just to gather enough data in order to perform any sort of meaningful statistical analysis (not that I have the necessary math skills to actually do that anyways).
    Add to that the fact that your nonce is session based, which means that for every datum gathered, a new session would need to be established, so multiply the requests by...probably a lot, I don't know, depends on the login procedure.

    Bottom line, I think that the system is now using a simple heuristic that sometimes fails to work (as heuristics sometimes do), but your proposal would require some very complicated heuristics that would again fail to work a lot of the time and would also require a lot of testing and debugging and refining and the end-result wouldn't be anywhere close to good enough to justify the effort.

    Your approach is correct, in theory, and I was thinking of the same thing when I was developing the check, but after a while I realized all of the above and gave up -- with a very heavy heart I might add.

    Don't let me shut you down though, this is basically my version of thinking out loud (over the Internet), so if you have any more feedback please do share.

  9. 9 Posted by Steven Phillips on 29 Aug, 2017 08:21 AM

    Steven Phillips's Avatar

    Hi Tasos,

    In my second to last post (6) please read csrf rather than xss - sorry about that.

    For a fully automated system I agree with everything in your last post - but what if your system doesn't, and cannot have a nonce? Currently the best I can do is switch off the csrf test which is a real shame.

    I agree that you could not possibly use heuristics to auto-detect a session-based anti-csrf token so either we do nothing, in which case csrf vulnerability is not checked at all, or we give Arachni some help.

    By telling Arachni the name of the anti-csrf token it can simply check the token is given in the form - this means it can identify forms with absolutely no csrf protection which is a lot better than nothing! And as I have to configure Arachni to do this, no false-positives as such.

    This could be wrapped up into the existing csrf check or a new csrf_session check could be created - I would be happy to a attempt to implement this as I really don't think this bit is difficult and it would really help me to identify vulnerable pages.

    A small improvement to this would be to check the value of the anti-csrf token - for a session-based anti-csrf token it needs to be reasonably long and random, i.e. 6 digit number is not good enough as it could be brute-forced.

    I also think it is possible to semi-auto check that the anti-csrf parameter is checked properly by the site - like autologin, this could never be done automatically and is not appropriate for some sites, but I believe that if the site being tested conforms to 2 pre-conditions Arachni could provide this invaluable service.

    Pre-condition 1: The anti-csrf token (nonce or session-based) is checked very early on in the site's submission process, preferably before any other submitted parameter values are checked.

    Pre-condition 2: If the anti-csrf token has been tampered with the resultant error handling always leads to an output with a known, testable content (i.e. like the 'check' string for the autologin plugin).

    If these two pre-conditions are met and this feature is enabled (by setting the 'check' string?) then Arachni can submit a form as normal, but with a tampered anti-csrf token and check that the resultant output page contains the configured anti-csrf error message - if not raise an error.

    As this is not auto-enabled and cannot work without some help (like the autologin plugin) hopefully only people who read the docs and understand the pre-conditions will attempt to use this. My site would be able to and this would be a great addition for me.

    Does this sound plausible?

    Steve

  10. Support Staff 10 Posted by Tasos Laskos on 06 Sep, 2017 03:21 PM

    Tasos Laskos's Avatar

    The problem with this is that checks aren't configurable, they don't have options like plugins do.
    Maybe I should remove the csrf check completely and add a plugin to handle this.

    I'll need to think about this.

  11. 11 Posted by Steven Phillips on 07 Sep, 2017 02:38 PM

    Steven Phillips's Avatar

    Hi Tasos,

    I like Arachni's plugin/check separation, it would be a shame to lose that as people may start missing the 'csrf' plugin and think Arachni doesn't check for this issue.

    Would a simpler, more generic solution be to start using carefully named global parameters, i.e. check__

    so you can easily slip an option in for any check? This way every check could document it's options (e.g. 'check_csrf_session_token') and you can expand any check without having to break it out.

    The other potential benefit of this approach would be that other checks (and the Arachni core itself) might also benefit from using these options. For example, there are multiple xss & sql checks, if in the future you introduced a second csrf check to test for a certain aspect of this issue it could still use the standard check_csrf_session_token option.

    Hope this helps and please let me know if I can be of any help...

    Steve

  12. 12 Posted by Steven Phillips on 07 Sep, 2017 02:40 PM

    Steven Phillips's Avatar

    Sorry, the formatting broke the 'carefully named global parameters', it was meant to be:

    check_<check-name>_<option-name>
    

    Steve

  13. Support Staff 13 Posted by Tasos Laskos on 12 Sep, 2017 04:29 PM

    Tasos Laskos's Avatar

    It would be easier to just enable options for checks as well, just like plugins have. Although checks are not supposed to accept special configuration, it should be a fire-and-forget kind of situation.
    If something more specialised is required for any given app, then a plugin needs to step in and extend/adjust the system functionality.

  14. 14 Posted by Steven Phillips on 13 Sep, 2017 09:01 AM

    Steven Phillips's Avatar

    Hi Tasos,

    Sorry for causing you additional problems - especially as I think we are all looking forward to trying the new engine!!

    As a new user I really liked the current separation of checks from plugins as it made it easy to see what Arachni was capable of testing for. If this was changed so that some like csrf became plugins users may miss them which would be a shame.

    I don't know for certain but I have assumed that other checks do effectively have settings, for example I suspect that setting your platform to 'mssql' changes the behaviour of the sql_injection* checks. Is this so different?

    Ultimately a flexible solution requiring the least work would be ideal :-)

    Steve

  15. Support Staff 15 Posted by Tasos Laskos on 13 Oct, 2017 09:33 AM

    Tasos Laskos's Avatar

    Hm, I could theoretically add a generic set of quirks options, allowing for those sort of grey area webapp specific adjustments.
    Things that could give an edge to all kinds of heuristics used throughout the system.

Reply to this discussion

Internal reply

Formatting help / Preview (switch to plain text) No formatting (switch to Markdown)

Attaching KB article:

»

Attached Files

You can attach files up to 10MB

If you don't have an account yet, we need to confirm you're human and not a machine trying to post spam.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac