6

I've done some extensive research about how to secure your website from card fraud.

iFrames do a pretty good job of this, however, It can still be worked around from certain exploits.

Many payment providers have now moved away from 'Hosted Payment Pages' and typically offer iFrames as a quick drop unsecured method.

This got me thinking, how could I make a tight/secure payment page that is simple/lightweight

Below is my idea, I would like to hear of any flaws in this method. I like this simple approach as I typically work with many international developers on short contracts, the ability to separate it only my access is important here also. I'd like to remove developer access entirely from the payments page. (It will very rarely require amending)

For this example, I'll use Stripe (but any iFrame drop-in would work).


Simply Idea:

  • Stored in .html (Ensure nothing can be injected by the DB or exploitable server-side scripts, such as PHP).
  • File to only include HTML/CSS and some vanilla JS. With the exception of JS include from the payment provider. (No abundance of JS libraries that can't be easily checked for flaws also no dependency includes that could include malicious code).
  • Load iFrame on this page (the information is not getting posted to our site)
  • Retrieve payment amount from GET request in JS.
  • Post token (received from iFrame in JS) back to the functional website.
  • Host on separate AWS S3.
  • Enable version on the bucket for backward logs.
  • Ensure AWS account is protected with MFA.
  • Place Cloudfront with custom SSL certificate to ensure the page is protected.

I've given this much thought, and I can't understand why others have taken this simple approach to really lock down the payment process.

I am looking forward to your thoughts on how you could attack this and how I could further reduce the attack surface here.

  • "why others have taken" or "have not taken"? How many did you check? – Thomas Weller Jul 24 '18 at 20:19
  • @ThomasWeller I didn't explicitly check this, however I take interest on the structure while paying online. My question however, was how I could further reduce the attack surface with this configuration. – Matt The Ninja Jul 24 '18 at 21:08
  • 1
    retrieve payment amount from GET request in JS makes me feel uncomfortable. – forest Jul 25 '18 at 2:21
  • @forest I agree, I will need to ensure that this can’t be exploited. I didn’t want to use post as I can avoid server side scripting. Also this page is kind of throw away, I’ll check the amount when it is passed back to my site. – Matt The Ninja Jul 25 '18 at 6:12
6
+50

Stored in .html (Ensure nothing can be injected by the DB or exploitable server-side scripts, such as PHP).

For this I would break everything down into modular components and work from there:

  • Harden your web server. An Apache Web Server Hardening Guide to get you started.
  • Restrict your web server directory (usually /var/www/):

    • # chown www-data:www-data /var/www/ -R
    • # chmod 555 /var/www/ -R
      • Most suggest using # chmod 750, and I agree, but do not give write permissions when not necessary.
  • Hardening your PHP client
    • OWASP PHP Configuration Cheat Sheet
    • While not comprehensive, it's a place to start.
    • PHP configuration hardening boils down to the same idea "If you do not need access (execute, read and/or write), do not give access"
  • Ensure PHP files cannot be loaded directly. E.g. the browser client cannot request example.com/login.php, but rather must go through example.com/login.html which performs an action.
  • Mitigating PHP inciting an SQL injection attack.
  • Use an appropriate secure password hashing algorithm with respect to your hardware and database (hash rate per second) with a salt. Personally, for my usage, I am fond of Argon2id.

File to only include HTML/CSS and some vanilla JS. With the exception of JS include from the payment provider. (No abundance of JS libraries that can't be easily checked for flaws also no dependency includes that could include malicious code).

Not much can be added to this, it is a good model, avoiding libraries ensures you vet the code, as you wrote everything. Although, take that with a grain of salt, Why is writing your own encryption discouraged?. I would suggest when a requirement can be achieved in either CSS or JavaScript, e.g. opt for a CSS slideshow of images or CSS hover selector, instead of using JavaScript where possible.

Load iFrame on this page (the information is not getting posted to our site)

I cannot foresee this being a problem as you will be using HTTPS and will be using a domain owned by you. However, it would be amiss to not suggest it. Why are iframes considered dangerous and a security risk? and 3 Reasons You Should Never Use Iframes

I like the idea of loading more information on the client-side. With ProtonMail it not only increases security for the client but also reduces server resources.

Retrieve payment amount from GET request in JS.

Why not use a POST request?

POST is more secure than GET for a couple of reasons.

GET parameters are passed via URL. This means that parameters are stored in server logs, and browser history. When using GET, it makes it very easy to alter the data being submitted the the server as well, as it is right there in the address bar to play with.

The problem when comparing security between the two is that POST may deter the casual user, but will do nothing to stop someone with malicious intent. It is very easy to fake POST requests, and shouldn't be trusted outright.

The biggest security issue with GET is not malicious intent of the end-user, but by a third party sending a link to the end-user. I cannot email you a link that will force a POST request, but I most certainly can send you a link with a malicious GET request. I.E: http://www.example.com/changepassword.php?newpass=Welcome123

GET vs POST which is more secure?

Post token (received from iFrame in JS) back to the functional website.

Why? HTML supports iFrame.

Host on separate AWS S3.

Anything Concerning AWS S3 I may make mistakes, as I am still new to this system. Merely a disclaimer!

So long as AWS S3 matches your OpSec, then this is fine. Just ensure your remote access to the server is hardened with strong passwords and 2FA where possible.

Ensure AWS account is protected with MFA.

As discussed above, using two-factor authentication (2FA) is advisable. Although, if MFA is available enable it.

I have seen SSH botnets have an OpenSSH server with the following parameters below simultaneously enabled:

  • Password authentication
  • Public key authentication
    • Risk of compromise: stealing the corresponding private key.
  • Google Authenticator
    • Risk of compromise: stealing the device authenticator is stored on.

Unless it impedes usability, the stronger authentication the better.

Place Cloudfront with custom SSL certificate to ensure the page is protected.

By custom SSL certificate I presume you are referring to issuing your own root CA with will sign the server certificate. If so, Jamie Linux has a very good article OpenSSL Certificate Authority, for configuring a public key infrastructure (PKI).

Amazon CloudFront seems like a good option for your requirements.

For deploying HTTPS on your web server consider the following parameters:

  • TLS 1.2 (or better)
  • HSTS
  • HSTS Preloading
  • RSA 2048 (or better)
    • Preferably if you can afford the performance impact use RSA 4096
  • AES-128 GCM (or better)
    • Again, preferably if you can afford the performance impact use AES-256
  • Allow (or enforce exclusively) forward secrecy (PFS)

Review your website using SSL Labs - Server Test

This is not a comprehensive review of attack vectors to produce a threat model. However, I hope it can serve to give a broader perspective. For further reading consider How do I deal with a compromised server?.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.