Skip to content
View in the app

A better way to browse. Learn more.

Unraid

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

CSRF token discussion

Featured Replies

I am glad that unRAID has some CSRF protection built-in. Unfortunately, the token is so long-lived that its value is questionable. The token is generated at boot time and kept until a reboot... my 6.3.5 server has been up 57 days, so the same token has been used the entire time. This is far longer than industry recommendations of generating a new token for every session.

 

The dangers of long-lived tokens are exacerbated by the fact that tokens are used on some query strings as well, where they can show up in log files or referrer headers.

 

So... can we consider adding a cron job to generate a new token on a regular basis? Changing the token once a day at 2am should have minimal impact, although every 3 or 6 hours would be even better.

 

The downside to changing the token at regular intervals is that it might change in between the time a page loads and when you hit submit, thus invalidating a legitimate request.  To get around that the server could track the previous token in addition to the current one, and consider either token valid.

 

The other difficulty is that tokens are needed by javascript that is constantly polling the server to update the interface. Users may leave the dashboard open for days at a time, and expect it to work regardless. Perhaps a variation of this:
  https://github.com/limetech/webgui/pull/95 
could be used to let the javascript access the current token if it is trying to submit an old one.

The csrf must be generated new for every new browser session established at a minimum to have any meaningful security impact. A browser session in Chrome should never use the same CSRF Token as one in IE or Firefox or Edge. The same applies if you're running a second session in the browser.

 

This should be more doable in 6.4 since it has NGIX available, even if it will take some rework/refinement in the pages and javascript.

  • 1 month later...
On 7/23/2017 at 5:14 PM, BRiT said:

The csrf must be generated new for every new browser session established at a minimum to have any meaningful security impact. A browser session in Chrome should never use the same CSRF Token as one in IE or Firefox or Edge. The same applies if you're running a second session in the browser.

 

This should be more doable in 6.4 since it has NGIX available, even if it will take some rework/refinement in the pages and javascript.

 

Can you explain the technical reason for this, or post a link that does?

1 hour ago, limetech said:

 

Can you explain the technical reason for this, or post a link that does?

 

It took me a while to find external means for this, as its been years since I had to implement them, but the following should help you out. When I ran various security scanning software (such as IBMs AppScan or others) at major financial institutions, the tests would explicitly fail if the CSRF Token was the same between different client sessions. Using a GUID for the life of a user's session as CSRF was enough to pass the tests.

 

This is a link from the open software security community. Note the unique per user session characteristic.

 

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet

 

--------

Synchronizer (CSRF) Tokens

  • Any state changing operation requires a secure random token (e.g., CSRF token) to prevent CSRF attacks
  • Characteristics of a CSRF Token
    • Unique per user session
    • Large random value
    • Generated by a cryptographically secure random number generator
  • The CSRF token is added as a hidden field for forms or within the URL if the state changing operation occurs via a GET
  • The server rejects the requested action if the CSRF token fails validation

In order to facilitate a "transparent but visible" CSRF solution, developers are encouraged to adopt the Synchronizer Token Pattern (http://www.corej2eepatterns.com/Design/PresoDesign.htm). The synchronizer token pattern requires the generating of random "challenge" tokens that are associated with the user's current session. These challenge tokens are then inserted within the HTML forms and links associated with sensitive server-side operations. When the user wishes to invoke these sensitive operations, the HTTP request should include this challenge token. It is then the responsibility of the server application to verify the existence and correctness of this token. By including a challenge token with each request, the developer has a strong control to verify that the user actually intended to submit the desired requests. Inclusion of a required security token in HTTP requests associated with sensitive business functions helps mitigate CSRF attacks as successful exploitation assumes the attacker knows the randomly generated token for the target victim's session. This is analogous to the attacker being able to guess the target victim's session identifier. The following synopsis describes a general approach to incorporate challenge tokens within the request.

Thanks for looking that up and I'm very familiar with that doc but does not explain why they recommend changing the token for every session or not be shared between browsers.  That is, what is the attack vector?  In unRaid case we are guarding against a csrf attack where someone has embedded some malicious javascript that tells the server do do something (like shutdown for example).  But the POST operation to the server needs to include the proper csrf_token value.  How does the attacker know what this token value is (browser same-origin policy protects against script learning this)?  At present we use a 64-bit value which would take javascript a hell of a long time to "guess".  What I thought you were going to point out was that our token was not long enough, which is something I've wondered about but it's real easy to make it longer.

 

One thing I would like you to consider.  By making a blanket statement, "... to have any meaningful security impact " is a little alarmist on your part because you don't show this to be the case.

 

The OP said, "The dangers of long-lived tokens are exacerbated by the fact that tokens are used on some query strings as well, where they can show up in log files or referrer headers."  That is maybe a legit concern if we can think of a specific attack vector.

  • Author

The general idea of a CSRF token is to have an unguessable string that is generated by the server and submitted as part of any sensitive action.  It is essentially an automated second password, required in addition to the standard authentication, before action can be taken.

 

Unguessable is key, otherwise it adds no value. The main strategy to make it hard to guess/steal is to make it unique and short-lived. If the token expires with the session, then any work the bad guys put in to determine the token is lost when the session closes. That makes it a very tough target for an attack.

 

In our case, a single token is shared across all browsers, all sessions, all users (well, there is really only one "user"), all plugins, and all apps (such as ControlR), until a reboot. 

So clearly at this point we are not relying on uniqueness or a short lifetime to help keep the token secure.  But where a short lifetime would discourage hackers from looking for the token, our multiple-month lifetime would probably do the opposite. Admittedly, I'm having a hard time coming up with a concrete example of how they might take advantage of this, beyond the log files idea. But that doesn't mean there isn't a way!

 

Based on my (limited) understanding of how unRAID works, it seems like it would be difficult to move to a true session-based system that would allow unique tokens. That's why I was suggesting to come up with a way to change the global token on a regular basis. To minimize disruption, the system could accept the previous token and transparently send the current one back to the client.

 

Overall to me it just "feels" wrong to have a global CSRF token that doesn't expire until the server is rebooted. I realize security is done in layers, but this layer feels weak.

Archived

This topic is now archived and is closed to further replies.

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.