Backend Security: Everything You Need to Know
This video lecture presents a detailed exploration of critical security concepts that backend engineers must understand and implement to protect their applications from common threats. It emphatically highlights the importance of adopting a security-first mindset, assuming attacker perspectives, and applying strong defensive programming techniques, especially in the context of injection attacks, authentication, and session management.
1. The Scope and Importance of Application Security
Security is a multifaceted domain encompassing browser, network, server (OS-level), and backend application security. For backend engineers, the focus lies on safeguarding the application code and infrastructure against vulnerabilities that could cause financial, reputational, and operational damages.
- Security breaches often translate into financial losses and resource drain.
- Complete security is impossible; vulnerabilities evolve with technology.
- The goal is to adopt a paranoid mindset: always question assumptions about user input, identities, and request origins.
- Attackers exploit developer assumptions, e.g., trusting user input as clean or trusting front-end origins.
- Security discussions are trimmed here to backend vulnerabilities and practical defensive strategies.
2. Mental Model for Understanding Attacker Techniques
Instead of listing abstract vulnerabilities, the video promotes thinking like an attacker:
- Attackers do not care about programming languages or frameworks.
- They seek developer assumptions that trust user input or internal consistency.
- Attacker behavior: probing boundaries, manipulating inputs, altering requests.
- The security mindset is: “What could go wrong here?” in every code piece involving user input or external data.
3. Injection Attacks and Their Root Cause
Injection attacks arise when untrusted user input crosses language boundaries within an application ecosystem—this leads to data being misinterpreted as code.
Key Concept: Applications Speak Multiple Languages
- Backend apps interact with:
- Databases (SQL)
- Browsers (HTML, JavaScript, CSS)
- Operating Systems (Shell commands, system calls)
- Each language has its own grammar, special characters, and command/data boundaries.
- Injection occurs when user input from one language context is treated as executable code in another.
Example: SQL Injection
- Simple login flow includes backend constructing SQL queries from user input (email, password).
- Naive construction uses string concatenation:
- If the user input is malicious, e.g.,
it closes the current string and injects a condition that's always true, bypassing authentication.
- This results in returning all users' data or worse, executing destructive database operations (e.g., dropping tables).
Demonstration
Defense: Parameterized Queries (Prepared Statements)
- Query and user data are sent separately to the database driver.
- User inputs are treated strictly as data, not code.
- The database driver inserts parameters safely, preventing injections.
- This model applies broadly across languages and database frameworks.
Injection Beyond SQL: Command Injection
- Backend may execute OS commands (e.g., image processing with
ffmpeg). - Dangerous if user input is concatenated into shell commands.
- Malicious inputs like:
can lead to destructive commands executing.
- Defense: Use language-native APIs where the command and arguments are passed separately, bypassing shell parsing. This ensures arguments are treated as data, not executable code.
Summary Table: Injection Attack Principles
4. Authentication and Authorization Essentials
Authentication ensures users are properly identified, preventing impersonation and unauthorized access.
Authentication Complexity in Production
- Authentication includes email/password, OAuth flows (Google, GitHub), and session management.
- Fully featured systems require stateful authentication to handle:
- Multi-device session tracking
- Session revocation across devices
- Permission management and caching
- OAuth Provider services (e.g., Clerk) handle these complexities, offering:
- Dedicated security teams
- Quick response to new threats
- Improved developer efficiency
Advice
- Use OAuth providers where possible, especially during early development.
- Implement own authentication only after scaling and revenue support justify it.
5. Secure Password Storage
Do NOT Store Plaintext Passwords
- Database breaches are common.
- Plaintext passwords allow attackers full account takeover, correlated site breaches (due to password reuse), and insider threats from staff.
Use Hashing Functions
-
Hash functions:
- Take variable-length input, produce fixed-size output.
- Are deterministic and one-way (hard to invert).
-
Common algorithms: bcrypt, Argon2id (modern industry standard).
-
Workflow:
- Store hashed password on signup.
- On login, hash input and compare.
-
Breached databases expose only password hashes, protecting raw passwords.
Threat: Rainbow Table Attacks
- Precomputed tables map common passwords to hashes.
- Attackers can quickly reverse many hashes if no other defense is applied.
Defense: Salting
- Add a unique, cryptographically strong random salt per user.
- Concatenate salt with password before hashing.
- Store salt alongside hashed password.
- Salting breaks rainbow table effectiveness: same passwords generate different hashes.
Defense: Use Slow Hash Functions
- Use password-specific slow hash functions like bcrypt or Argon2id.
- They slow down brute force attacks by increasing computation for each guess.
- Select a cost/work factor to balance delay/performance (e.g., 400ms hash time).
- Slows down attempts from billions per second to a handful per second, drastically reducing attack feasibility.
6. Session Management & Security
Stateful Sessions
- Generate a cryptographically secure random session ID per login (128-256 bits).
- Store session ID + metadata (user ID, creation time, IP, user agent) in a persistent store (Redis, database).
- Set session ID in a cookie sent to the client.
- Subsequent requests send the cookie, allowing the server to identify the authenticated user.
Cookie Security Flags
Stateless Sessions: JSON Web Tokens (JWTs)
- Self-contained tokens storing user/session data signed cryptographically.
- No server-side session store needed, easing horizontal scaling.
- JWT consists of:
- Header (algorithm info)
- Payload (claims: user ID, issued at, custom info)
- Signature (header+payload signed with server secret)
JWT Security Considerations
- Integrity: Signature prevents tampering.
- Payload: Base64 encoded (not encrypted) — do not store sensitive info.
- Revocation: Difficult, since tokens are stateless and stored by client.
- Mitigations:
- Use short-lived access tokens (5-10 mins).
- Use refresh tokens with server validation and expiry.
- Maintain blacklists for revoked tokens.
- Storage: Avoid localStorage (XSS risk); prefer HttpOnly Secure cookies.
Verdict on Auth Methods
- Prefer stateful authentication unless scaling requires stateless JWT.
- Stateful sessions support easy revocation and simpler handling.
- JWTs are powerful but require additional complexities to manage revocation and token expiration securely.
7. Rate Limiting for Authentication Endpoints
- Prevent brute force by limiting login attempts per IP and per account.
- Layered rate limiting helps:
- IP-based limits (e.g., 10 attempts/minute)
- Account-based locking after repeated failed attempts (e.g., lock for 24 hours).
- IP-based limits have downsides:
- Shared IP addresses (universities, organizations) false positives.
- Attackers can circumvent using bots, VPNs, proxies.
- Rate limiting is essential to avoid credential guessing attacks and prevent denial of service.
Summary of Core Recommendations for Backend Security
- Always question assumptions about input and trust boundaries.
- Use parameterized queries and avoid raw string concatenation to prevent injection attacks.
- For OS command execution, invoke shell commands via APIs that isolate code and data.
- Prefer trusted OAuth providers for authentication at scale.
- Store passwords using salted, slow hash algorithms (Argon2id, bcrypt).
- Implement stateful session management with secure cookies (HttpOnly, Secure, SameSite).
- If using JWT, enforce short expiry, refresh tokens, and token blacklists.
- Apply rate limiting at multiple layers, focusing heavily on authentication endpoints.
- Maintain a mindset of "What if this input is malicious?" and architect systems to treat all user data as untrusted by default.
This structured approach enables backend developers to build more resilient applications and minimize common security vulnerabilities affecting modern web services.