Search code examples
javascriptformscorscsrfstatic-site

How to securely cross domain submit a form from a static html site to a server side backend?


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!


Solution

  • 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.