Security is not optional. New vulnerabilities and attack techniques emerge every day. This comprehensive guide covers best practices and tools to protect your web applications in 2024.
OWASP Top 10: Critical Vulnerabilities
1. Broken Access Control
The #1 vulnerability according to OWASP 2021:
- Users accessing resources without authorization
- Privilege escalation
- IDOR (Insecure Direct Object References)
- Modifying URLs to access other data
Prevention:
- Deny by default, except public resources
- Implement centralized access control
- Validate ownership in every operation
- Disable directory listing
- Rate limiting on APIs
- Invalidate JWT tokens on logout
2. Cryptographic Failures
Failures in protecting sensitive data:
- Transmitting data in plain text
- Weak or deprecated cryptographic algorithms
- Default or weak encryption keys
- Not using HTTPS correctly
Best Practices:
- HTTPS everywhere with TLS 1.3
- Use modern algorithms: AES-256-GCM, ChaCha20-Poly1305
- Bcrypt or Argon2 for passwords (never MD5 or SHA1)
- Secrets in environment variables or vaults
- HSTS header to force HTTPS
- Perfect Forward Secrecy (PFS)
3. Injection
SQL, NoSQL, OS command injection:
- Malicious input interpreted as code
- SQL injection remains prevalent
- Command injection in shells
- LDAP, XPath injection
Defense:
- Prepared statements and parameterized queries ALWAYS
- Correctly configured ORMs
- Whitelist input validation (not blacklist)
- Escape special characters
- Least privilege in database users
- WAF for malicious pattern detection
4. Insecure Design
Fundamental flaws in architecture:
- Not applying threat modeling
- Lack of security requirements
- Not validating business logic
Solution:
- Shift left security - design with security from the start
- Threat modeling (STRIDE, PASTA)
- Security stories in every sprint
- Architecture review by security team
5. Security Misconfiguration
Insecure default configurations:
- Unnecessary open ports
- Verbose error messages in production
- Unused features enabled
- Default credentials
- Misconfigured CORS
Hardening:
- Disable unnecessary features
- Remove default accounts and passwords
- Security headers: CSP, X-Frame-Options, X-Content-Type-Options
- Automated security scanning in CI/CD
- Principle of least privilege
Modern Authentication and Authorization
JSON Web Tokens (JWT) - Best Practices
- Use RS256 or ES256 algorithm (not HS256 with weak secrets)
- Short tokens: 5-15 minutes for access tokens
- Refresh tokens with rotation
- Store in httpOnly, secure, SameSite cookies
- Never in localStorage (vulnerable to XSS)
- Validate iss, aud, exp claims
- Implement token revocation list if critical
OAuth 2.0 and OpenID Connect
- OAuth 2.0 for authorization (not direct authentication)
- OpenID Connect (OIDC) for authentication
- Authorization Code Flow with PKCE
- Never use Implicit Flow (deprecated)
- State parameter to prevent CSRF
Multi-Factor Authentication (MFA)
Essential for modern security:
- TOTP (Time-based One-Time Password) with apps like Authy, Google Authenticator
- WebAuthn for biometrics and security keys
- SMS as a last resort (vulnerable to SIM swapping)
- Encrypted recovery codes
Passwordless Authentication
- Magic links via email
- WebAuthn/FIDO2 with passkeys
- Biometrics on devices
- Reduces phishing attacks
Protection Against XSS (Cross-Site Scripting)
Types of XSS
- Stored XSS: Malicious script stored in DB
- Reflected XSS: Script in URL reflected in response
- DOM-based XSS: Client-side DOM manipulation
Multi-Layer Defense
- Input validation: Sanitize all user input
- Output encoding: HTML entity encoding in templates
- CSP (Content Security Policy): Restrictive header
- DOMPurify: Library to sanitize HTML
- Modern Frameworks: React, Vue, Angular escape by default
- Careful with dangerouslySetInnerHTML: Use only with sanitization
Content Security Policy Example
- default-src 'self'
- script-src 'self' 'nonce-{random}'
- style-src 'self' 'unsafe-inline' (ideally remove unsafe-inline)
- img-src 'self' data: https:
- connect-src 'self' https://api.yourapp.com
- frame-ancestors 'none'
CSRF Protection (Cross-Site Request Forgery)
How CSRF Works
Attacker tricks browser into sending authenticated requests:
- User authenticated on legitimate site
- Visits malicious site
- Malicious site sends request to legitimate site
- Browser automatically includes cookies
Prevention
- CSRF Tokens: Unique token per session/request
- SameSite cookies: SameSite=Strict or Lax
- Double Submit Cookie: Token in cookie and header
- Custom headers: X-Requested-With in AJAX
- Origin/Referer checking: Validate request origin
- GET requests should never modify state
HTTPS and TLS Configuration
SSL/TLS Certificates
- Let's Encrypt for free certificates
- Automatic renewal with certbot
- Wildcard certificates for subdomains
- Certificate pinning in mobile apps
Optimal TLS Configuration
- TLS 1.3 only (disable 1.0, 1.1, 1.2 if possible)
- Secure cipher suites: ECDHE+AESGCM, ChaCha20-Poly1305
- Perfect Forward Secrecy (PFS)
- HSTS with includeSubDomains and preload
- OCSP stapling for better performance
Essential Security Headers
- Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
- X-Frame-Options: DENY (prevent clickjacking)
- X-Content-Type-Options: nosniff
- Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy: Control browser features
Dependencies and Supply Chain Security
The Problem
- Modern projects have hundreds of dependencies
- Transitive dependencies multiplied
- Vulnerabilities discovered constantly
- Attacks on npm packages (typosquatting, compromised packages)
Scanning Tools
- npm audit / yarn audit: Built-in scanning
- Snyk: Continuous monitoring, automatic fix PRs
- Dependabot (GitHub): Automatic PRs for updates
- OWASP Dependency-Check: Open source scanner
- Socket.dev: Detects malware in packages
Best Practices
- Keep dependencies updated
- Review package-lock.json in code reviews
- Use package.json with specific versions or ~
- Avoid ^ which can bring breaking changes
- Audit new dependencies before adding
- Consider bundle size and security when choosing libs
- Use subresource integrity (SRI) for CDNs
API Security
Rate Limiting and Throttling
- Prevent DoS and brute force attacks
- By IP, by user, by API key
- Token bucket or leaky bucket algorithms
- Headers: X-RateLimit-Limit, X-RateLimit-Remaining
- 429 Too Many Requests with Retry-After
API Keys and Secrets
- Never in source code or repositories
- Environment variables
- Secrets managers: AWS Secrets Manager, Azure Key Vault, HashiCorp Vault
- Regular key rotation
- Minimum necessary scope
Input Validation
- Validate in backend ALWAYS (don't trust frontend)
- Schema validation: Joi, Yup, Zod
- Type checking in APIs (TypeScript, GraphQL)
- Reject unknown fields
- Validate data types, formats, ranges
API Versioning and Deprecation
- Versioning in URL: /api/v1/users
- Deprecation warnings in responses
- Sunset header to announce end of support
- Maintain old versions temporarily
Container Security
Docker Security
- Use official and verified images
- Distroless images for minimal attack surface
- Multi-stage builds for small images
- Do not run as root: USER directive
- Scan vulnerabilities: Trivy, Clair, Snyk
- Read-only filesystems when possible
- .dockerignore to not include secrets
Kubernetes Security
- Strict RBAC (Role-Based Access Control)
- Network policies to segment traffic
- Pod Security Standards/Admission
- Secrets in etcd encrypted
- Service mesh (Istio, Linkerd) for mTLS
- Falco for runtime threat detection
Security Logging and Monitoring
What to Log
- Authentication attempts (successful and failed)
- Authorization failures
- Input validation failures
- API abuse (rate limiting triggers)
- Changes in permissions/roles
- Administrative actions
What NOT to Log
- Passwords
- Tokens or API keys
- Full credit cards
- Sensitive PII without masking
SIEM and Alerting
- SIEM: Splunk, Elastic Security, Sumo Logic
- Real-time alerts for critical events
- Event correlation
- Security dashboards
Security Testing
SAST (Static Application Security Testing)
- Source code analysis
- Tools: SonarQube, Checkmarx, Semgrep
- Integrate in IDE and CI/CD
- False positives require tuning
DAST (Dynamic Application Security Testing)
- Runtime application testing
- Black box testing
- Tools: OWASP ZAP, Burp Suite, Acunetix
- Automated scanning in staging
Penetration Testing
- Manual testing by experts
- At least annually
- After major architectural changes
- Bug bounty programs for continuous testing
Compliance and Regulations
GDPR (Europe)
- Right to be forgotten
- Data portability
- Privacy by design
- Breach notification within 72 hours
PCI DSS (Payment Card Industry)
- Required if processing credit cards
- Better to use Stripe/PayPal to avoid PCI scope
- Never store CVV
- Card tokenization
Security Checklist for Launch
Pre-deployment
- HTTPS configured correctly
- Security headers implemented
- Secrets in vaults, not in code
- Dependencies updated, no critical vulnerabilities
- SAST and DAST executed
- Penetration testing completed
- Rate limiting on APIs
- Logging and monitoring configured
- Backup and disaster recovery plan
Post-deployment
- Active log monitoring
- Alerts configured
- Incident response plan documented
- Continuous security scanning
- Regular security updates
Conclusion
Security is an ongoing process, not a state. Threats evolve constantly and require permanent vigilance.
Implementing all these measures may seem overwhelming, but the key is to prioritize: start with the fundamentals (HTTPS, robust authentication, input validation) and build upon that foundation.
At Brixato, security is a priority from design. Every feature includes security considerations, we run automated testing on every commit, and maintain a continuous update program. Security is not just the responsibility of the security team - it is everyone's responsibility.