5 Easy to Miss Security Best Practices for Web Apps

 
This image represents web security tips Photo by Mick Haupt on Unsplash

Worrying about your app’s quantum resistance is a perfectly legitimate concern. But, in this blog post, I’ll take a step back and describe and few simple but easy-to-overlook security tips. In many cases, a single line of config can protect your web application from a range of attacks.

Of course, even having all the described solutions in place does not mean that your app is now secure. But, without them, the scope of a potential attack is significantly larger.

1. HTTP security headers

These headers are usually the first thing that I check when conducting my Rails performance and security audits:

HTTP security headers check

Sample security headers report from securityheaders.com


Most of them don’t have to be customized, so improving the app’s security is as simple as adding a config line to your NGINX or backend server.

One exception is Content-Security-Policy. It has to be fine-tuned to allow the external resources your website interacts with. It can be a bit tricky to do manually, but there’s a browser extension by Mozilla. It automatically generates a correct CSP header value when you click around your website.

You can check out the linked mdn web docs for more in-depth info about these headers.

Strict-Transport-Security

Referrer-Policy

X-Frame-Options

X-Content-Type-Options

2. Two-factor authentication

Implementing 2FA for your web application can be a challenging process. But, enabling it in services used by your development and support team is usually a matter of a few clicks in the UI. It could be the simplest way to protect your project from a range of account takeover attacks.

Check out the linked docs explaining how to enable and optionally enforce two-factor authentication in popular services used for web development:

Slack - enable 2FA, mandatory 2FA

GitHub - enable 2FA, mandatory 2FA

Heroku - enable 2FA

AWS - enable 2FA

Discord - enable 2FA

I usually recommend storing 2FA codes in 1Password and only using a separate device or a YubiKye as a second factor for 1Password itself. 1Password offers seamless login integration via browser extensions and also protects users from phishing attacks by verifying websites.

3. Email security features

If your domain is used to send emails, you should make sure that you’ve correctly configured SPF (Sender Policy Framework), DKIM (DomainKeys Identified Mail), and DMARC (Domain-based Message Authentication Reporting and Conformance). Correctly configuring them all will prevent your company from email spoofing, i.e., malicious actors and spammers trying to impersonate it. Explaining these security mechanisms in detail and how to configure them is beyond the scope of this blog post. Check out the linked Cloudflare docs for more info. But, here’s a one-sentence recap:

SPF works like an allowlist for sources that should be able to send emails from your domain. [More info]

DKIM allows to cryptographically verify that the email was generated by origin configured in the DNS records. [More info]

DMARC describes a policy on how other servers should treat emails originating from your domain. [More info]

Here you can verify if your domain is already protected:

SPF checker

DKIM checker

DMARC checker

All these security features are configured at the DNS level. For DKIM, an additional config is needed at the email provider, so check their respective docs.

Even, or especially, if your domain is not used to send emails, you can explicitly deny it using a correct DMARC policy.

4. Transfer files securely

Company chat is usually the go-to way to share data, unfortunately even sensitive one. Without a more sophisticated security policy around what 3rd party integrations can be connected to your chat app, it could be a source of a critical data leak. For example a malicious chat plugin could request read access to public channel messages, and your company policy did not enforce limits on who can connect similar tools. Chat apps are also not immune to security breaches, so distrusting them is a sensible default.

Even sharing sensitive data via email should probably be discouraged. Attachments stay forever on 3rd party servers, so any account takeover would grant attackers access to all the data.

Establishing a framework for securely sharing sensitive data could save your company from unnecessary trouble. One tool that serves this purpose is Magic Wormhole. It is relatively simple to use even by less technical members of a team. You can share files via a direct connection using a one-time passphrase, and data is not persisted anywhere.

A commercial alternative could be to sync files via shared 1Password vaults. But compared to Magic Wormhole, the shared files are kept in the vault unless explicitly removed.

5. AWS IAM policies

Many web apps use AWS just to interact with a single S3 bucket. Unfortunately, some tutorials recommend using AdministratorAccess or even AWS root user credentials as a quick and easy way to connect your web app to AWS. Granting your web app an admin AWS access could have critical consequences. Especially if the same AWS account is shared by multiple apps. A single compromised application could access or even irreversible remove data from different projects. Or your credit card could be drained by a Bitcoin mining bot.

If your app is talking to a single S3 bucket, then you should probably use IAM user credentials with a similar custom policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::your-bucket-name"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::your-bucket-name/*"
            ]
        }
    ]
}

Check out my other blog post for a step-by-step guide on configuring S3 IAM policies. It is written in the context of Ruby on Rails but is applicable to all the backend tech stacks.

Summary

Implementing any of the above tips should not take more than a few hours. Yet, they protect from attacks with potentially critical consequences.



Back to index