2

I'm wanting to create a series of static HTML sites which will be hosted at on Amazon S3.

The static sites will have forms. My plan is to post/ajax submit the form data to a server side application hosted on a different domain. The server side application will store the data in a database for future reference as well as email the submitted data to the relevant person.

At face value this is simple, the HTML form just needs to POST the data to the server side script, similar to google forms/wufoo/formspree etc.

My concern is with the security implications of this. The post will be cross domain from the static site, which seems to make CSRF difficult to implement in popular web frameworks. I've read many blog posts on CSRF/CORS/Authentication but am no clearer.

From studying formspree.io's source code, it seems they check the referer and origin headers to verify the form submission is coming from the website it should be and a website that is registered. However I understand these can be spoofed?

As any javascript code on the static site can be read and reverse engineered, API style authentication seems difficult...

Or am I overthinking this, and if I post the form via SSL, validate the form data server side, check the referer/origin headers as per formspree it should be secure enough?

TLDR; For a static HTML site posting form data to a server side backend for storing in a DB and emailing, what security steps do I need to take?

Thanks in advance!

toyo
  • 23
  • 4
  • We have no idea what you are trying to prevent people from doing. – Quentin Sep 19 '18 at 18:06
  • That's a fair comment, I didn't specify this as I wasn't 100% sure I'd thought of every possible vulnerability so left the question generic. Normally I would follow the best practices of the web framework, i.e. CSRF tokens in forms but none of the frameworks documentation seems to cover this situation. As I cannot add the CSRF token to the static HTML, and the static HTML is on another domain (so the cookie method is out) I guess CSRF protection is the main issue? – toyo Sep 20 '18 at 08:56
  • I don't know if CSRF protection is the main issue. Are you doing anything that would make it a concern at all? – Quentin Sep 20 '18 at 08:58
  • I don't think so, it will just be forms to collect non sensitive information from site visitors so spam bots will probably be the biggest problem. I'm maybe overthinking this, as I said formspree doesn't appear to implement CSRF and just checks the origin/referer, but I wanted to check this will be secure enough and I'm not overlooking anything. – toyo Sep 20 '18 at 11:16

2 Answers2

2

Optimal Solution

It appears that the optimal solution in your case is doing the following:

  1. Implementing a Recaptcha.
  2. Sending the request to a script of your own first, that validates the captcha and then forwards the request.
  3. Adding Access-Control-Allow-Origin only your HTMLs' origins only. useful question

CSRF Protection

As a matter of fact, It's pretty difficult to build a secure application if you only have access to the client side. If the services you're posting to doesn't have a built-in CSRF system, It'd be a good solution if you add a recaptcha to your HTML page and create a simple php script that will receive the form fields, validate the recpatcha and submit the form fields to whatever destination you want.

A CSRF protection through a token would also do the trick and actually it's the clean-coding solution if you eventually submit to your own script first, still, it would be somehow difficult to implement it into static HTML pages. (You'll need to generate it through Javascript or a php script, store it in your session, then validate it in your backend script) but I'd recommend it if you are able to code it.

  • In both cases, you'll need to submit to your own script first and then forward the request through CURL.

Validating Headers

In your backend script, you can validate the referer and origin to make sure the requests aren't coming from a different source other than your HTML forms.

Summary

  1. The recaptcha will prevent anyone from doing a CSRF attack against your users.
  2. In case the attacker was trying to find a workaround the origin and referer checking, they might use something like CURL, the recaptcha will also prevent them from doing that.
  3. The Access-Control-Allow-Origin Implementation will prevent attackers from submitting data to your page through javascript.
  4. Submitting to your own script first will also prevent anyone from knowing where exactly you're submitting these data, which will make it harder for them to perform an attack.

Although the captcha isn't a very user-friendly solution, if you have the ability to code a CSRF protection system it needs to be done through either javascript, or sending an ajax request that generates a token unique to user's session then you can validate that token inside your other PHP page, but you'll need to implement the captcha to prevent spamming anyways.

Mostafa Kasem
  • 380
  • 4
  • 11
  • Thanks for your response, I was hoping to avoid requiring the user to solve a captcha as I don't want to impact conversion rates. I see that google now offer an invisible recaptcha which could be an option, although this link suggests it wont protect against CSRF: https://blog.detectify.com/2017/12/06/captcha-csrf/ The server side framework I will use can generate CSRF tokens, but I'm not sure how I can use it on the static HTML page (on a different domain)? I could issue an ajax request to the server side script on page load to retrieve the CSRF token but I'm not sure if this is secure... – toyo Sep 20 '18 at 09:02
  • If you code it the right way, it will be. It'll be session based, so the attacker will have no way of determining it. Just make sure that the page which generates the CSRF token can't be accessed except from your HTMLs' origins, otherwise it will be pointless. – Mostafa Kasem Sep 20 '18 at 09:07
  • OK thanks, so I could expose the CSRF token at an endpoint on the server side, but check the referrer/origin against a whitelist of the static sites before outputting the token? – toyo Sep 20 '18 at 11:22
  • Yes, the attacker will try to send an ajax request to get the token and then put it in a form, when you only allow requests coming from certain origins he won't be able to do that. – Mostafa Kasem Sep 20 '18 at 11:34
  • I've a feeling you're over-engineering and thinking this, before you decide to implement any security measurements, make sure you actually need them. – Mostafa Kasem Sep 20 '18 at 11:35
  • Thanks for clarifying, you're right I've got a feeling I am over-engineering this but wasn't sure on the correct approach. I think I will leave out the CSRF for now. – toyo Sep 22 '18 at 09:44
0

On your server, you need some middleware to make sure that the request origin is one that is trusted. So if your static html site is www.mysite.com, make sure that on the server www.mysite.com is allowed access to your apis. As far as authentication goes, if you don't want just anyone accessing your apis, you need some type of authentication. Basic flow kind of looks like this:

User posts login data, server authenticates, server generates token and sends back to client in response, token gets stored on the client and set in the header with any requests being made. Then on your routes, you will need some middleware to check if a token is present in the request header, if so, allow access, if not, deny it.

Hope that clears some stuff up.

Isaac Vidrine
  • 1,333
  • 1
  • 5
  • 20