Skip to content
PN Scripts

Development

Web application security basics: a practical checklist

  • PN Scripts Team
  • 7 min read

Most web applications are not broken into through clever new attacks. They are broken into through a short list of known mistakes: weak login handling, a missing permission check on one endpoint, unvalidated input, a leaked password or API key, an outdated library, and no backup or log to recover with. Securing an application means closing each of those gaps on purpose and checking them again whenever the code changes. The checklist below is written for owners who need to know what to ask for and for developers who need to know what to verify.

#Authentication and sessions

Authentication answers one question: is this person who they claim to be? Most frameworks ship a solid implementation, and the safest choice is to use it rather than write your own.

  • Store passwords with a slow, salted hashing algorithm designed for passwords, such as bcrypt or Argon2. Never store them in plain text or with a fast general-purpose hash.
  • Offer two-factor authentication, and require it for administrators and anyone who can see customer data or move money.
  • Limit login attempts per account and per IP address, so passwords cannot be guessed at speed.
  • Keep password reset safe: single-use tokens that expire, and the same response whether or not the email address exists.
  • Protect session cookies with the Secure, HttpOnly and SameSite attributes, issue a new session ID after login, and end sessions on logout and after a period of inactivity.
  • Use CSRF protection on every form and state-changing request that relies on cookies.

#Authorization on every request

Authorization answers a different question: is this logged-in person allowed to do this particular thing to this particular record? This is where many real breaches happen, and the OWASP Top 10 lists broken access control among its most serious risks.

The typical bug is simple. A user opens /invoices/1042, changes the number to 1043 and sees another customer's invoice, because the code checked that the user was logged in and never checked that the invoice belonged to them. The same happens with API endpoints the interface never shows, and with admin actions protected only by hiding the button.

  • Check permissions on the server, on every request, for every record. Hiding a link in the interface is not a control.
  • Keep the rules in one place, such as policies or middleware, so a new endpoint cannot forget them.
  • Deny by default. A new role or route should have no access until someone grants it.
  • Write automated tests that try to read and change other users' data and expect a refusal.

#Input validation and output escaping

Treat everything that comes from outside as untrusted: form fields, URL parameters, headers, uploaded files, webhook payloads and data from partner APIs.

  • Validate on the server for type, length, format and allowed values. Browser validation helps the user and protects nothing.
  • Use parameterized queries or the framework's query builder for every database query. Building SQL by joining strings with user input is how SQL injection happens.
  • Escape output for its context. Template engines in modern frameworks escape HTML by default; the risk is in the places where a developer switches that off to print raw HTML. That is how cross-site scripting (XSS) gets in.
  • Handle uploads carefully: check the real file type, limit size, rename files, store them outside the public web root or on separate storage, and never execute them.
  • Do not fetch arbitrary URLs supplied by users from your server without an allow list, or the server can be used to reach internal systems.

#Secrets and third-party code

Secrets

Database passwords, API keys, payment provider credentials and signing keys are the most valuable things in your project.

  • Keep secrets out of the code repository. Load them from environment variables or a secrets manager, and commit only an example file with placeholder values.
  • If a secret was ever committed, treat it as leaked and rotate it. Deleting the line does not remove it from the repository history.
  • Give each environment its own credentials, so a leak from a test server does not open production.
  • Give each key the least access it needs: a read-only database user for reporting, an API key limited to the actions the integration uses.
  • Know who has access to what, and remove access when someone leaves the project. Our article on who owns the code and the accounts covers keeping those accounts in your name.

Dependencies and updates

A typical application contains far more third-party code than code written for it. Each library can carry a published vulnerability.

  • Commit the lock file (composer.lock, package-lock.json and similar), so every environment runs the same versions.
  • Run a vulnerability audit regularly, for example composer audit or npm audit, or switch on automated alerts in your code hosting service.
  • Apply security patches promptly and keep the framework, language runtime and database on versions that still receive security fixes.
  • Remove plugins and packages nobody uses. Unused code still has to be patched.

#Backups and logging

Security also covers recovery. When something goes wrong, you need to know what happened and be able to restore.

Backups:

  • Back up the database and uploaded files automatically, keep copies in a separate location from the server, and keep several generations, so a problem discovered late can still be undone.
  • Test restores on a schedule. A backup that has never been restored is an assumption.
  • Protect backups like production data. They contain the same personal information.

Logging and alerts:

  • Log security events: logins, failed logins, password changes, permission changes, admin actions and exports of data.
  • Never log passwords, full card numbers, tokens or session IDs.
  • Send errors and unusual patterns, such as a burst of failed logins, to someone who will act on them.
  • Keep logs long enough to investigate an incident that is noticed weeks later.

#Using the OWASP Top 10 as a reference

The OWASP Top 10 is a widely used list of the most critical security risks to web applications, published by the Open Worldwide Application Security Project and revised every few years. It is a good shared vocabulary for owners and developers and a sensible baseline for a code review. It is not a complete standard. For a deeper checklist, OWASP also publishes the Application Security Verification Standard (ASVS). Always check that you are reading the current edition of either document.

A few habits make the checklist stick:

  • Serve everything over HTTPS and set security headers such as Content-Security-Policy and Strict-Transport-Security.
  • Show generic error pages in production and keep debug mode off.
  • Include a security question in every code review: who can call this, with what input?
  • For applications that handle payments or sensitive personal data, commission an independent security test before launch and after major changes.

Security is ongoing work. The checks above belong in regular maintenance after launch, not in a single audit.

#How PN Scripts can help

PN Scripts builds web applications with automated tests on critical paths such as payments, logins and data, keeps documentation up to date and continues with updates after launch for as long as the client wants. When we take over existing code, a review comes first. To discuss an application you want built or checked, see our custom web development page.

Keep reading

Keep reading

Comments

Comments

Be the first to leave a comment.

Leave a comment

Next step

pnscripts.com/contact

Talk to the team

Ask about an article, or tell us about a project you want built. We reply within one business day.

Write to us

The PN Scripts family

Other PN Scripts sites

Hosting, games and the blog each have their own site, run by the same company.

  • pnscripts.com

    PN Scripts

    Software engineering

    Custom web, mobile, API and game development, plus our open-source products and plugins.

  • games.pnscripts.com

    Games

    Games and game servers

    The home for PN Scripts games and game servers. The catalog is empty for now and fills up as titles and servers go live.

  • hosting.pnscripts.com

    Hosting

    Hosting and infrastructure

    Shared hosting, KVM VPS, dedicated servers and domains, from the same company that builds your project.

  • blog.pnscripts.com

    Blog

    Articles and field notes

    Plain articles on hosting, servers, domains and security, written by the people who work with them.

    You are here