Application Security

Contents

Security Principles

OWASP Top 10

  • Injection Flaws
  • Broken Authentication
  • Sensitive Data Exposure
  • XML External Entities (XXE)
  • Broken Access Control
  • Security Misconfiguration
  • Cross-Site Scripting (XSS)
  • Insecure Deserialization
  • Using Components with Known Vulnerabilities
  • Insufficient Logging & Monitoring

Input Validation

SQL Injection Prevention

# Python - Using Parameterized Queries import mysql.connector def safe_query(user_input): conn = mysql.connector.connect( host="localhost", user="user", password="password", database="mydb" ) cursor = conn.cursor(prepared=True) # Safe: Using parameterized query sql = "SELECT * FROM users WHERE username = %s" cursor.execute(sql, (user_input,)) return cursor.fetchall()

XSS Prevention

// JavaScript - Input Sanitization function sanitizeHTML(str) { return str.replace(/[&<>"']/g, function(match) { const escape = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return escape[match]; }); } // Example usage const userInput = ""; const safeOutput = sanitizeHTML(userInput);

Authentication & Authorization

Password Hashing

// Node.js - Using bcrypt const bcrypt = require('bcrypt'); async function hashPassword(password) { const saltRounds = 12; const hash = await bcrypt.hash(password, saltRounds); return hash; } async function verifyPassword(password, hash) { const match = await bcrypt.compare(password, hash); return match; }

JWT Implementation

// Node.js - JWT Authentication const jwt = require('jsonwebtoken'); function generateToken(user) { return jwt.sign( { id: user.id, role: user.role }, process.env.JWT_SECRET, { expiresIn: '24h' } ); } function verifyToken(req, res, next) { const token = req.headers.authorization?.split(' ')[1]; if (!token) { return res.status(401).json({ message: 'No token provided' }); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; next(); } catch (err) { return res.status(401).json({ message: 'Invalid token' }); } }

Data Protection

Encryption

// Node.js - AES Encryption const crypto = require('crypto'); class Encryption { constructor(encryptionKey) { this.algorithm = 'aes-256-gcm'; this.key = crypto.scryptSync(encryptionKey, 'salt', 32); } encrypt(text) { const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv(this.algorithm, this.key, iv); let encrypted = cipher.update(text, 'utf8', 'hex'); encrypted += cipher.final('hex'); const authTag = cipher.getAuthTag(); return { iv: iv.toString('hex'), encrypted: encrypted, authTag: authTag.toString('hex') }; } decrypt(encrypted) { const decipher = crypto.createDecipheriv( this.algorithm, this.key, Buffer.from(encrypted.iv, 'hex') ); decipher.setAuthTag(Buffer.from(encrypted.authTag, 'hex')); let decrypted = decipher.update(encrypted.encrypted, 'hex', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } }

Session Management

Secure Session Configuration

// Express.js - Session Configuration const session = require('express-session'); app.use(session({ secret: process.env.SESSION_SECRET, name: 'sessionId', // Don't use default connect.sid cookie: { httpOnly: true, secure: true, // Requires HTTPS sameSite: 'strict', maxAge: 1000 * 60 * 60 // 1 hour }, resave: false, saveUninitialized: false }));

Session Rotation

// Express.js - Session Rotation Middleware function rotateSession(req, res, next) { if (req.session.user) { // Clone current session data const userData = { ...req.session.user }; // Regenerate session req.session.regenerate((err) => { if (err) return next(err); // Restore user data in new session req.session.user = userData; req.session.lastRotated = Date.now(); next(); }); } else { next(); } }

Secure Coding Practices

Error Handling

// Node.js - Safe Error Handling class AppError extends Error { constructor(message, statusCode) { super(message); this.statusCode = statusCode; this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error'; this.isOperational = true; Error.captureStackTrace(this, this.constructor); } } // Global Error Handler app.use((err, req, res, next) => { err.statusCode = err.statusCode || 500; if (process.env.NODE_ENV === 'production') { // Send generic error message in production if (err.isOperational) { return res.status(err.statusCode).json({ status: err.status, message: err.message }); } // Programming or unknown errors return res.status(500).json({ status: 'error', message: 'Something went wrong' }); } // Development error handling return res.status(err.statusCode).json({ status: err.status, error: err, message: err.message, stack: err.stack }); });

Security Testing

SAST Tools

Popular Static Analysis Tools:

  • SonarQube
  • ESLint Security Plugin
  • Bandit (Python)
  • FindSecBugs (Java)

Penetration Testing

Key Areas to Test:

  • Authentication Bypass
  • Authorization Controls
  • Input Validation
  • Session Management
  • API Security
  • File Upload Vulnerabilities