Securing Web Applications: OWASP Top 10 and Beyond
Comprehensive guide to web application security covering the OWASP Top 10 vulnerabilities, defense strategies, and modern security practices.
Table of Contents
Securing Web Applications: OWASP Top 10 and Beyond
Web application security is critical in today's threat landscape. Understanding and mitigating the most common vulnerabilities is essential for protecting user data and maintaining trust.
OWASP Top 10 Overview
The Open Web Application Security Project (OWASP) maintains a list of the most critical web application security risks.
1. Broken Access Control
Prevent unauthorized access to resources:
// Proper authorization middleware
const requireRole = (role: string) => {
return (ctx: Context) => {
const user = getCurrentUser(ctx);
if (!user || !user.roles.includes(role)) {
ctx.response.status = 403;
ctx.response.body = { error: "Forbidden" };
return;
}
};
};
// Usage
router.get("/admin/users", requireRole("admin"), getUsersHandler);2. Cryptographic Failures
Use strong encryption and proper key management:
import { createHash } from "crypto";
// Secure password hashing
export async function hashPassword(password: string): Promise<string> {
const salt = crypto.randomBytes(32);
const hash = await crypto.pbkdf2(password, salt, 100000, 64, "sha256");
return `${salt.toString("hex")}:${hash.toString("hex")}`;
}
// Secure token generation
export function generateSecureToken(): string {
return crypto.randomBytes(32).toString("hex");
}3. Injection
Prevent SQL injection and other injection attacks:
// Safe parameterized queries
const getUserById = async (userId: string) => {
const query = "SELECT * FROM users WHERE id = ?";
const [rows] = await db.execute(query, [userId]);
return rows[0];
};
// Input validation
import { z } from "zod";
const userSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
age: z.number().min(0).max(150),
});
const validateUser = (data: unknown) => {
return userSchema.parse(data);
};4. Insecure Design
Implement security by design principles:
// Defense in depth
class SecurityService {
async authenticateUser(credentials: LoginCredentials) {
// 1. Rate limiting
await this.checkRateLimit(credentials.email);
// 2. Input validation
this.validateCredentials(credentials);
// 3. Credential verification
const user = await this.verifyCredentials(credentials);
// 4. Session creation
const session = await this.createSecureSession(user);
return session;
}
}5. Security Misconfiguration
Secure configuration management:
# production.yaml
security:
headers:
contentSecurityPolicy: "default-src 'self'"
strictTransportSecurity: "max-age=31536000"
xFrameOptions: "DENY"
xContentTypeOptions: "nosniff"
database:
ssl: true
connectionPool:
min: 2
max: 10
authentication:
jwt:
secret: "${JWT_SECRET}"
expiresIn: "1h"
bcrypt:
rounds: 12Advanced Security Practices
Zero Trust Architecture
Never trust, always verify:
class ZeroTrustAuth {
async authorizeRequest(request: Request): Promise<boolean> {
// 1. Verify identity
const identity = await this.verifyIdentity(request);
// 2. Check context
const context = await this.evaluateContext(request);
// 3. Assess risk
const risk = await this.assessRisk(identity, context);
// 4. Make authorization decision
return this.makeDecision(identity, context, risk);
}
}API Security
Secure your APIs with proper authentication and authorization:
// JWT authentication middleware
const authenticateJWT = async (ctx: Context, next: Next) => {
const token = ctx.request.headers.get("Authorization")?.replace(
"Bearer ",
"",
);
if (!token) {
ctx.response.status = 401;
ctx.response.body = { error: "No token provided" };
return;
}
try {
const payload = await verifyJWT(token);
ctx.state.user = payload;
await next();
} catch (error) {
ctx.response.status = 401;
ctx.response.body = { error: "Invalid token" };
}
};Rate Limiting
Protect against abuse and DoS attacks:
import { rateLimit } from "express-rate-limit";
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: "Too many requests from this IP, please try again later.",
standardHeaders: true,
legacyHeaders: false,
});
app.use("/api/", limiter);Security Monitoring and Logging
Security Information and Event Management (SIEM)
Centralized security monitoring:
class SecurityLogger {
async logSecurityEvent(event: SecurityEvent) {
const logEntry = {
timestamp: new Date(),
level: "security",
event: event.type,
userId: event.userId,
ip: event.ip,
userAgent: event.userAgent,
details: event.details,
};
// Send to SIEM system
await this.siemClient.send(logEntry);
// Alert on critical events
if (event.severity === "critical") {
await this.alertTeam(event);
}
}
}Intrusion Detection
Monitor for suspicious activities:
class IntrusionDetector {
async analyzeRequest(request: Request): Promise<RiskLevel> {
const riskFactors = await Promise.all([
this.checkIPReputation(request.ip),
this.checkUserBehavior(request.userId),
this.checkRequestPatterns(request),
this.checkAnomalyDetection(request),
]);
return this.calculateRiskLevel(riskFactors);
}
}Compliance and Auditing
GDPR Compliance
Handle personal data responsibly:
class GDPRCompliance {
async handleDataSubjectRequest(request: DataSubjectRequest) {
switch (request.type) {
case "access":
return await this.provideDataAccess(request.userId);
case "rectification":
return await this.rectifyData(request.userId, request.data);
case "erasure":
return await this.eraseData(request.userId);
case "portability":
return await this.exportData(request.userId);
}
}
}Security Audits
Regular security assessments:
class SecurityAuditor {
async performSecurityAudit() {
const results = {
vulnerabilityScan: await this.runVulnerabilityScan(),
configurationReview: await this.reviewConfiguration(),
accessControlAudit: await this.auditAccessControls(),
complianceCheck: await this.checkCompliance(),
};
await this.generateReport(results);
await this.notifyStakeholders(results);
}
}Incident Response
Incident Response Plan
Preparedness for security incidents:
class IncidentResponse {
async handleSecurityIncident(incident: SecurityIncident) {
// 1. Assess the situation
const assessment = await this.assessIncident(incident);
// 2. Contain the breach
await this.containBreach(assessment);
// 3. Investigate thoroughly
const investigation = await this.investigateIncident(incident);
// 4. Recover systems
await this.recoverSystems(investigation);
// 5. Learn and improve
await this.postMortemAnalysis(incident, investigation);
}
}Conclusion
Web application security is an ongoing process that requires vigilance, regular updates, and a security-first mindset. Implementing the OWASP Top 10 protections and following security best practices will significantly reduce your application's attack surface.