What Every Junior Developer Should Learn About Software Security

May 1, 2020 · 6 min read

Silver MacBook turned on So Long And Thanks For All The Phishing” by Abraham Joel Pena Puelo / CC BY 4.0

Is your code secure?

Encryption, hashing, API security, SQL injections, CSRF, XSS, DoS, HSTS, RBAC, .... Oh, my.

When I started my programming journey, I didn't even know that I should care about software security. Then I got in contact with this entire area. And all those things blew my mind.

But with time, I learned what to look for when creating software.

This article targets software engineers in web, api, and app development, but most security measures apply to other application types, too!

I structured the security measures in three sections:

  • General Security Measures concern all engineers, frontend and backend.
  • Backend Security Measures are more interesting on the backend side. This is the server application where your API lives.
  • Frontend Security Measures apply to frontend developers, i.e. for web or mobile apps.

This article only gives you an overview of what is important. Take this as a starting point. Deep dive into each security measure and learn how to apply it in your code base.

General Security Measures

Keep dependencies up to date

This includes build and runtime dependencies, runtime engines (like Node.js), and OS versions. When you use Docker, also update that base image regularly.

Use HTTPS/TLS

APIs and websites should only be accessible via HTTPS. This secures your traffic from eavesdropping and certifies to your user they are talking to you.

Only offer recent versions of TLS (1.2 & 1.3). And don't offer TLS 1.1 or lower, or any version of SSL (those versions are insecure and end of life).

Expose web sockets only via “web socket secure” (wss). This is the TLS-secured version of web sockets.

On plain HTTP requests only allow redirect to HTTPS.

Never trust user input

You should sanitize user inputs (or not, depending on who you ask 😄).

Start with validating user input, both in the form fields and at the api endpoint. Be strict about the input you receive. Enforce the correct type (number, string, ...). Use input whitelist where possible (e.g. enums). Use variable binding when storing data in a database, to prevent SQL injection (more on that below).

An interesting rule is to "Filter Input" and "Escape Output".

Avoid user input in regex

Don't use dynamic user input in your regex. Learn how to avoid Regular Expression Denial of Service (ReDoS)

Learn about CSRF prevention

Learn about XSS prevention

Do not use dangerous functions

This one is simple. Never use dangerous functions like JS eval, unless you know what you're doing.

Verify file uploads

Make sure files have the correct content type (use a whitelist). Also, validate the content type, don't trust the content-type header. Set file size limits. Set the filename to something your application generates. Only allow authorized users to upload files.

Learn more about file upload verification in the OWASP cheat sheet for file upload security.

Backend Security Measures

Hash and salt passwords correctly

Use bcrypt unless you have a reason not to (see the OWASP password security cheat sheet). Or use an Auth Provider like auth0.com or Azure ADB2C (or whatever is available for you).

Use variable binding in SQL statements

Or at least use variable substitution. This prevents SQL injections.

Create a clean API

Offer concrete actions on defined resources. Only allow certain data manipulation, don't give users direct access to your database. Creat your API based on REST or GraphQL principles.

Never allow direct SQL queries via API

👉 This point is so important that I wanted to list it separately.

Store application secrets safely

This is data like database secrets or access keys for external APIs.

Use environment variables. Don't check these env variables into version control (no default or hard-coded credentials).

Locally, you can use something like .env files. Your app either reads these files, or they set your env when executed.

CI/CD always provide a way to set env securely.

In production, the setup of secure environment variables changes depending on your hosting environment.

You could be able to set env directly in your hosting environment (like Heroku). Hosting platforms often call these settings "secure environment variables". Kubernetes is somewhat more complicated. Check out Hashicorp Vault, Helm Secrets, and Sealed Secrets to find out what works for you.

When you manage your own server, research best practices for the OS + Language combination you use. Make sure that credentials:

  • are outside of the web root
  • have appropriate permissions so that only the required user(s) can read them
  • are not checked into source code repositories

Set request size limits

This helps to prevent Denial of Service (DoS) attacks.

Set rate limits

This also helps to prevent DoS attacks.

Develop good logging habits and set up monitoring and alerting

Receive notifications on events that should not happen.

Identify security incidents, like configuration changes. Monitor policy violations, like unauthorized errors. Log internal server errors (which should not happen).

Discuss what makes sense for your team and regularly improve your logging approach.

Reduce the attack surface

Don't keep unused software on your production machines and Docker images. Use the smallest possible version of your operating system, disable what you don't need and only install what you need.

Offer only the necessary API resources, not more. Disable debugging endpoints by default, only enable them when needed.

Learn how to set appropriate security headers

Do secure session management

There are two parts to session management: authentication and authorization.

When a user first uses your application, you don't know who they are. They must authenticate to answer the question "who are you?" This usually happens via your login form or a third party login provider.

You then give them a safe session identifier or a Json Web Token (JWT). Your backend service either stores a list of all currently valid session identifiers. With JWTs, it knows how to verify the JWT a user provides. For session management, it is crucial that you provide a way to invalidate or blacklist sessions, to handle, e.g., log outs or user permission changes.

On each subsequent request, your users provide their session identifier. Authorization then answers the question: "is this user allowed to do that?" General rules for authorization are: Authorize on the server, not the client. Deny by default. Authorize actions on resources. Use a concept like role-based access control (RBAC) or attribute-based access control (ABAC). Find out more about RBAC vs ABAC.

Frontend Security Measures

  • Encode html input.
    Every major frontend framework provides a way to use variables safely. This prevents html injection.
  • Only show users the actions they can perform (not more)
  • Use rel="noopener noreferrer" to prevent tabnabbing
  • Make sure password managers work with your login and sign up pages
  • Protect Personally Identifiable Information (PII) from being cached by the browser. Provide Credential and PII Input hints.
  • Enforce a minimum password length of 8 characters
  • Show users a password strength estimator like zxcvbn
  • Use the sandbox attribute for iframes when they are untrusted

Conclusion

Security errors can be very costly. Either for your company or for your client. Make sure you follow the basic best practices, to prevent the worst.

Software security is, like all security, the effort to make the cost-benefit analysis of the attacker negative.

For your run-off-the-mill web app, following the basics is more than most of the others do. The more valuable your application and its data are, the higher your efforts on security should be.

There are many more security best practices than I described here. This list serves as a starting point about what to look for when developing software. Go check out the OWASP Cheat Sheet Series. They provide a great "collection of high value information on specific security topics".

What to do next

Deep dive into the measures you know less about. Pick one or two and see if you already use them in your application. If not, plan how to do it. Then implement it. Repeat for other measures you're not familiar with.

Disclaimer: I am not a security specialist. Just a developer concerned with application and api security trying to teach some best practices. This list is not exhaustive. Always do your own research.