DEV Community

Rizwan Saleem
Rizwan Saleem

Posted on

How to secure your web application: a practical guide for developers

How to secure your web application: a practical guide for developers

Below is a practical tutorial covering common web application security vulnerabilities aligned with OWASP Top Ten, with concrete patterns for prevention and real-world considerations. It emphasizes XSS, CSRF, SQL injection, authentication and authorization, security headers, HTTPS, CSP, secure cookies, dependency scanning, input validation, and real-world security patterns.

  • OWASP Top Ten overview
    • The OWASP Top Ten highlights the most critical web application security risks. While this guide touches on several, treat it as a practical starter kit: use it alongside a full security program, including threat modeling, secure SDLC practices, and regular testing.

XSS (Cross-Site Scripting)

  • What it is: Attackers inject malicious scripts into trusted websites, which execute in a user’s browser.
  • Real-world patterns:
    • Reflected XSS via user-supplied query parameters.
    • Stored XSS via content saved in a database (user profiles, comments).
    • DOM-based XSS when untrusted data is written into the DOM without proper escaping.
  • Prevention:
    • Output‑encode all untrusted data before rendering in HTML, JavaScript, CSS, or attributes. Use a library or framework’s escaping functions (e.g., React’s JSX automatically escapes, Angular’s templates, or server-side templating with proper escaping).
    • Use a Content Security Policy (CSP) to limit script sources and inline scripts.
    • Validate input on both client and server sides, but do not rely on client validation alone.
    • Use sane content-type headers and avoid injecting untrusted data into HTML contexts like innerHTML; prefer textContent or safe templating.
  • Concrete checks:
    • Ensure data rendered in HTML is escaped for the target context.
    • Disable or restrict inline event handlers and inline scripts; prefer external scripts with strict CSP.
  • Example pattern:
    • Server renders user-generated comments with proper escaping; client never writes raw user data into innerHTML.

CSRF (Cross-Site Request Forgery)

  • What it is: An attacker tricks a user into submitting a request to an application where they are authenticated.
  • Real-world patterns:
    • A logged-in user visits a malicious site that triggers a state-changing request to the target site (e.g., a bank transfer, profile change).
  • Prevention:
    • Use CSRF tokens tied to user sessions for state-changing requests; require token validation on the server for sensitive actions.
    • SameSite cookies: set cookies to SameSite=Lax or Strict to reduce cross-site request contexts.
    • Implement double-submit cookies or custom headers (where feasible) for critical actions.
  • Concrete checks:
    • Validate CSRF tokens for POST/PUT/DELETE requests, not just GET.
    • Ensure sensitive endpoints require a token in a hidden form field or header (e.g., X-CSRF-Token).
  • Example pattern:
    • Web forms include a hidden CSRF token; server verifies token matches user session before performing actions.

SQL Injection

  • What it is: Attackers manipulate SQL queries by injecting malicious input.
  • Real-world patterns:
    • Unsafely concatenated strings building SQL queries.
    • Dynamic queries based on user input without proper parameterization.
  • Prevention:
    • Use parameterized queries/prepared statements for all database interactions.
    • Use ORM safeguards and avoid string-building SQL; prefer bound parameters.
    • Validate input for type, length, and allowed patterns; reject unexpected values early.
    • Least privilege: database account with minimal privileges needed.
  • Concrete checks:
    • Scan all database access points for unparameterized queries.
    • Enable query logging to detect suspicious patterns.
  • Example pattern:
    • Instead of building SQL like "SELECT * FROM users WHERE username = '" + user + "'", use prepared statements: "SELECT * FROM users WHERE username = ?" with a bound value.

Authentication and Authorization

  • What it is:
    • Authentication: verifying identity (passwords, MFA, tokens).
    • Authorization: enforcing access controls (roles, permissions).
  • Real-world patterns:
    • Weak password policies, no MFA, password reuse.
    • Inadequate session management (short-lived tokens, improper revocation).
    • Vertical and horizontal access control gaps (users accessing data/areas they shouldn’t).
  • Prevention:
    • Use strong password policies; store salted hashes with a modern algorithm (e.g., Argon2, bcrypt, scrypt).
    • MFA as a standard option; require for sensitive actions.
    • Implement session management with secure, HttpOnly, SameSite cookies; rotate tokens; implement short session lifetimes with refresh tokens.
    • Implement role-based access control (RBAC) or attribute-based access control (ABAC); enforce at every endpoint.
    • Avoid security by obscurity; enforce authorization checks server-side for all resources.
  • Concrete checks:
    • Ensure authorization checks are enforced on the server for every request, not just on the UI.
    • Log and alert on anomalous access patterns (e.g., bulk data access, rapid permission changes).
  • Example pattern:
    • Users authenticate via a centralized identity provider; access tokens contain scoped permissions; the API validates tokens and enforces resource-based policies.

Security Headers

  • What they are: HTTP headers that help protect against common attacks.
  • Critical headers:
    • Strict-Transport-Security (HSTS): force HTTPS.
    • Content-Security-Policy (CSP): control sources for content to mitigate XSS and data injection.
    • X-Content-Type-Options: nosniff to prevent MIME-type misinterpretation.
    • X-Frame-Options: deny or sameorigin to prevent clickjacking.
    • Referrer-Policy: control the Referer header leakage.
    • Permissions-Policy (formerly Feature-Policy): restrict browser features.
  • Concrete checks:
    • Implement a robust CSP covering default-src, script-src, style-src, img-src, connect-src, font-src, object-src, frame-ancestors; consider nonce or hash in CSP for inline scripts if needed.
    • Enable HSTS with appropriate max-age and include subdomains.
  • Example pattern:
    • Response headers include:
    • Content-Security-Policy: "default-src 'self'; script-src 'self' https://cdn.example.com 'nonce-abc123'; object-src 'none'; connect-src 'self'".
    • X-Content-Type-Options: nosniff
    • X-Frame-Options: SAMEORIGIN
    • Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

HTTPS and TLS Practices

  • What it is: Encrypts data in transit to prevent eavesdropping and tampering.
  • Real-world patterns:
    • Serving over HTTP; weak TLS configurations; outdated protocols.
  • Prevention:
    • Enforce HTTPS everywhere; use TLS with strong ciphers; disable old protocols.
    • Implement certificate management (short-lived certs, automation with ACME/Let's Encrypt).
    • Implement HSTS to prevent downgrade attacks.
  • Concrete checks:
    • Regularly test TLS with scanners to detect weak ciphers, renegotiation vulnerabilities, and certificate expiry.
  • Example pattern:
    • Redirect all HTTP to HTTPS; configure TLS to prefer modern curves (e.g., secp256r1) and disable TLS 1.0/1.1.

Content Security Policy (CSP) Best Practices

  • What it is: A mechanism to declare trusted content sources.
  • Real-world patterns:
    • Inline scripts, eval usage, and mixed content weaken CSP effectiveness.
  • Prevention:
    • Prefer strict CSP without unsafe-inline; use nonce-based or hash-based inline scripts if necessary.
    • Regularly review and tighten allowed sources; remove unnecessary third-party scripts.
  • Concrete checks:
    • Validate CSP on every deployment; monitor CSP violation reports (if enabled).
  • Example pattern:
    • CSP header: "default-src 'self'; script-src 'self' cdnjs.cloudflare.com 'nonce-xyz'; style-src 'self' 'unsafe-inline' cdn.jsdelivr.net; object-src 'none'; img-src 'self' data: https:; connect-src 'self'".

Secure Cookie Configuration

  • What it is: Cookie attributes controlling how cookies behave.
  • Real-world patterns:
    • Session cookies without HttpOnly, Secure, or proper SameSite settings.
  • Prevention:
    • Mark session cookies HttpOnly to prevent access via JavaScript.
    • Use Secure so cookies are only sent over HTTPS.
    • Set SameSite to Lax or Strict to mitigate CSRF risks (in combination with other CSRF protections).
  • Concrete checks:
    • Ensure cookies are marked HttpOnly and Secure; set SameSite appropriately.
  • Example pattern:
    • Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax

Dependency Scanning and Software Supply Chain

  • What it is: Protecting against vulnerable libraries and dependencies.
  • Real-world patterns:
    • Incorporating third-party libraries with known CVEs; transitive dependencies with untracked risks.
  • Prevention:
    • Implement SBOMs (software bill of materials); run regular dependency scans for vulnerabilities.
    • Pin versions and use trusted registries; use automated remediation workflows.
    • Use minimal, actively maintained dependencies; consider software composition analysis.
  • Concrete checks:
    • Schedule nightly or CI-based scans of dependencies; fail builds on critical CVEs.
  • Example pattern:
    • Use a dependency scanning tool integrated into CI/CD to flag and block vulnerable updates.

Input Validation and Data Sanitization

  • What it is: Ensuring data conforms to expected formats before processing or storage.
  • Real-world patterns:
    • Accepting free-form input without validation; insufficient length checks; invalid types.
  • Prevention:
    • Validate on the server side for type, length, format, and range; whitelist allowed values where possible.
    • Normalize inputs and reject or sanitize unexpected data.
    • Use structured data formats (JSON schemas) for API payloads; leverage validation libraries.
  • Concrete checks:
    • Implement strict schemas for API endpoints; reject unknown fields.
  • Example pattern:
    • JSON payload with defined schema; reject any fields outside the schema; validate email, dates, and numeric ranges.

Real-World Security Patterns

  • Defense-in-depth:
    • Combine multiple controls (input validation, parameterized queries, CSRF protection, CSP, secure cookies, TLS, and regular scanning) to reduce the blast radius.
  • Least privilege:
    • Each component should run with the minimum permissions necessary; database accounts with restricted privileges; services with scoped access.
  • Secure defaults:
    • Security-first defaults in frameworks and platforms; require explicit opt-ins for risky features.
  • Automate security testing:
    • Integrate static and dynamic analysis, dependency scanning, and container security checks into CI/CD pipelines.
  • Incident response readiness:
    • Have runbooks for detected threats; monitor for anomalous behavior; test response drills.

Putting it together: a practical workflow

  • Design and threat modeling:
    • Identify critical data, high-risk endpoints, and trusted vs. untrusted data sources.
  • Implement layered defenses:
    • Start with secure defaults; add authentication/authorization, input validation, prepared statements, and secure headers.
  • Ensure secure deployments:
    • Enforce HTTPS, CSP, secure cookies, and HSTS; automate certificate management.
  • Ongoing security hygiene:
    • Regular dependency scans, code reviews with security checks, continuous monitoring, and rapid patching.
  • Validation and testing:
    • Use automated tests for XSS/CSRF/SQl injection scenarios; perform penetration testing and bug bounty programs where feasible.

Illustrative example: a single endpoint

  • Endpoint: POST /api/v1/orders to place an order
  • Security controls:
    • Authentication: verify access token with proper scopes.
    • Authorization: ensure user can place orders and only access their own cart data.
    • Input validation: validate order data (items, quantities, address) against a strict JSON schema.
    • SQL safety: use prepared statements for any database writes.
    • CSRF: require CSRF token for state-changing requests if cookies are used for auth; otherwise rely on token-based auth with proper anti-CSRF measures.
    • XSS prevention: sanitize any user-generated content displayed in order confirmations.
    • CSP: restrict scripts and resources used on the frontend; use nonce if inline scripts are necessary.
    • Cookies: set session cookies with HttpOnly, Secure, SameSite=Lax/Strict.
    • HTTPS: ensure transport encryption end-to-end with proper TLS config.
    • Dependency hygiene: scan dependencies used by the endpoint’s service for known CVEs.
    • Logging and monitoring: log authorization decisions and failed validation attempts; alert on unusual patterns.

If you’d like, I can tailor this into a checklist for your stack (language, framework, deployment platform) and propose concrete, step-by-step changes you can implement in your codebase and CI/CD pipeline.

Would you like this to be adapted to a specific tech stack or presented as a compact checklist you can print and pin to your team board?

-

Rizwan Saleem | https://rizwansaleem.co

Sources

Top comments (0)