agrafix / Spock

Another Haskell web framework for rapid development
https://www.spock.li
678 stars 56 forks source link

Request: a blog post about securing Spock apps #103

Open soupi opened 7 years ago

soupi commented 7 years ago

Hello!

I've been writing Haskell for some time now but I'm still a webdev beginner. For the last few weeks I've been working on gathering which is my first real attempt at building a complete website, and of course I chose Spock :)

First I'd like to say thank you for Spock, I enjoy working with it and for the most part I experienced very little friction using it.

However, one thing that bothers me about webdev is how easy it is to introduce vulnerabilities to your users if you don't know what you are doing, and I know I don't know what I'm doing.

So I'd really appreciate some expert advice on how to secure websites written in Spock. A blog post would be even better! (Also I'd really appreciate any review I can get on gathering. I think it can also help highlight common security pifalls as I'm sure I introduced some unintentionally)

Thanks again!

agrafix commented 7 years ago

Nice, thanks for the feedback! 👍

I'm pretty busy atm, but I took a quick look at your project. Note that this might not be exhaustive. From a security perspective, you should always include a CSRF protection in forms etc., which is possible in Spock using getCsrfToken. Read more about CSRF attacks: OWASP CSRF. Also, after a successful login, call sessionRegenerateId to prevent session fixation attacks. The database looks good since you are using prepared statements, although there's a race-condition in your newUser function as it's not a transaction and thus (although highly unlikely) someone could create a new account with the same name between your check and your insert-statement. Use hasql-transaction instead and don't prewrap all your statements with query for flexibility.

Hope that helps!

Speeking of a blog post - I really like the idea and hope to find time for it ... If any one else would like to write something please let me know I'd be happy to help.

soupi commented 7 years ago

Thank you very much for the feedback and help! I will read up and work on fixing those issues.

soupi commented 7 years ago

Hello again, I looked around but could not find any explanation or example on how to protect against CSRF attacks in Spock or how to use getCsrfToken.

I tried to enable csrf protection in the SpockConfig

  spockCfg <- (\cfg -> cfg { spc_csrfProtection = True })
          <$> defaultSpockCfg EmptySession (PCConn $ hasqlPool connstr) state

And then do the following before displaying a form to the use:

  csrfToken <- getCsrfToken
  setHeader "spc_csrfHeaderName" csrfToken

But I still get the following when submitting a form:

Broken/Missing CSRF Token

Also, anything related to csrf points for more information in spc_csrfHeaderName spc_csrfPostName but they aren't very helpful...

I'm probably missing something pretty simple and fundamental, but I've search a lot and couldn't find anything on the subject.

Thanks Again, Gil

codygman commented 7 years ago

Just a guess, but try setting csrfHeaderName and postName to some random text value.

On Jan 17, 2017 3:02 PM, "Gil Mizrahi" notifications@github.com wrote:

Hello again, I looked around but could not find any explanation or example on how to protect against CSRF attacks in Spock or how to use getCsrfToken .

I tried to enable csrf protection in the SpockConfig

spockCfg <- (\cfg -> cfg { spc_csrfProtection = True }) <$> defaultSpockCfg EmptySession (PCConn $ hasqlPool connstr) state

And then do the following before displaying a form to the use:

csrfToken <- getCsrfToken setHeader "spc_csrfHeaderName" csrfToken

But I still get the following when submitting a form:

Broken/Missing CSRF Token

Also, anything related to csrf points for more information in spc_csrfHeaderName http://hackage.haskell.org/package/Spock-0.11.0.0/docs/Web-Spock-Config.html#v:spc_csrfHeaderName spc_csrfPostName http://hackage.haskell.org/package/Spock-0.11.0.0/docs/Web-Spock-Config.html#v:spc_csrfPostName but they aren't very helpful...

I'm probably missing something pretty simple and fundamental, but I've search a lot and couldn't find anything on the subject.

Thanks Again, Gil

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/agrafix/Spock/issues/103#issuecomment-273298368, or mute the thread https://github.com/notifications/unsubscribe-auth/AANyNzdVmpaztYnH7VuOek6l5KnS-pnsks5rTSxSgaJpZM4LlUt7 .

soupi commented 7 years ago

@codygman can you elaborate please? I'm not sure what you're suggesting I should do.

agrafix commented 7 years ago

You have to include the csrfToken from getCsrfToken in your form as hidden input named __csrf_token (you can changes the name of the field in the configuration).

soupi commented 7 years ago

@agrafix thanks! this seems to have fixed the issue.

I did however had to fix the path for all runForm calls (example) because each field in it gets a prefix according to the form path and that was the only way i could think of to get a fixed name for the csrf input field consistently across all forms. This is an ok workaround for me, but I have to wonder if there's a better way.

agrafix commented 7 years ago

I'd move the CSRF token handling out of the digestive functor machinery, that way you don't need to do this. Just statically add the mentioned hidden input field to all forms.