Security Headers for Defense in Depth

Security Headers for Defense in Depth

Security headers provide browser-enforced protections that complement server-side SQL injection defenses:

# Nginx configuration with comprehensive security headers
server {
    listen 443 ssl http2;
    server_name api.example.com;
    
    # Content Security Policy - Prevents XSS that could lead to SQL injection
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://trusted-cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' https://api.example.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; report-uri /csp-report" always;
    
    # Prevent clickjacking attacks that might trick users into submitting malicious data
    add_header X-Frame-Options "DENY" always;
    
    # Disable MIME type sniffing
    add_header X-Content-Type-Options "nosniff" always;
    
    # Enable XSS protection (though modern browsers have this by default)
    add_header X-XSS-Protection "1; mode=block" always;
    
    # Referrer Policy to prevent leaking sensitive URLs
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    
    # Permissions Policy (formerly Feature Policy)
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), accelerometer=(), gyroscope=()" always;
    
    # Custom security headers for API protection
    add_header X-API-Version "2.0" always;
    add_header X-RateLimit-Limit "1000" always;
    
    # HSTS to ensure HTTPS usage
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}

Implement application-level security headers:

# Flask application with security headers
from flask import Flask, request, jsonify, make_response
from functools import wraps
import hashlib
import hmac

app = Flask(__name__)

def add_security_headers(response):
    """Add security headers to all responses"""
    response.headers['X-Content-Type-Options'] = 'nosniff'
    response.headers['X-Frame-Options'] = 'DENY'
    response.headers['X-XSS-Protection'] = '1; mode=block'
    response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'
    
    # Add CSP with nonce for inline scripts
    nonce = generate_nonce()
    response.headers['Content-Security-Policy'] = f"default-src 'self'; script-src 'self' 'nonce-{nonce}'"
    
    # Custom headers for API protection
    response.headers['X-Request-ID'] = generate_request_id()
    response.headers['X-RateLimit-Remaining'] = str(get_rate_limit_remaining(request))
    
    return response

@app.after_request
def after_request(response):
    return add_security_headers(response)

# API endpoint with additional injection protection
@app.route('/api/data', methods=['POST'])
@validate_api_signature  # Custom decorator to verify request signatures
def secure_api_endpoint():
    # Verify Content-Type to prevent injection via wrong parsing
    if request.content_type != 'application/json':
        return jsonify({'error': 'Invalid Content-Type'}), 400
    
    # Size limit to prevent large payload attacks
    if request.content_length > 1024 * 100:  # 100KB limit
        return jsonify({'error': 'Payload too large'}), 413
    
    # Process request safely
    try:
        data = request.get_json(force=False)
        # ... process with parameterized queries
    except Exception as e:
        logger.error(f"Request processing failed: {e}")
        return jsonify({'error': 'Invalid request'}), 400