Available for day contractsFrom 21st September I have availability for day and half day contracts. Please contact for more information.

Contact →
mikepreston.org

Security Best Practices

A comprehensive guide to implementing robust security patterns and practices across software development and infrastructure operations.

Security Best Practices Cheatsheet

A comprehensive guide to implementing robust security patterns and practices across software development and infrastructure operations.


Overview

Security best practices encompass a holistic approach to protecting systems, data, and users from threats through proactive measures, continuous monitoring, and rapid incident response.

Defence in DepthSecurity ArchitectureSecurity GovernancePreventive ControlsDetective ControlsCorrective ControlsAccess ControlEncryptionSecure CodingMonitoringAuditingVulnerabilityScanningIncident ResponsePatch ManagementDisaster RecoveryPerimeterNetworkHostApplicationDataDefence in DepthSecurity ArchitectureSecurity GovernancePreventive ControlsDetective ControlsCorrective ControlsAccess ControlEncryptionSecure CodingMonitoringAuditingVulnerabilityScanningIncident ResponsePatch ManagementDisaster RecoveryPerimeterNetworkHostApplicationData

Principle of Least Privilege

Key Concepts

Concept Description
Minimal Access Users and services receive only the permissions necessary to perform their tasks
Need-to-Know Basis Access to information is restricted to those who require it for their role
Separation of Duties Critical tasks are divided among multiple individuals to prevent fraud and errors
Time-Limited Access Elevated privileges are granted temporarily and automatically revoked
Role-Based Access Control (RBAC) Permissions are assigned based on roles rather than individual users

Common Patterns

Linux/Unix Permission Management

# View current permissions
ls -la /path/to/resource

# Set restrictive file permissions (owner read/write only)
chmod 600 sensitive-file.txt

# Set directory permissions (owner only)
chmod 700 /secure/directory

# Remove group and other access
chmod go-rwx /path/to/resource

# Set ownership
chown appuser:appgroup /var/app/data

# Use ACLs for fine-grained control
setfacl -m u:specificuser:r /path/to/file
getfacl /path/to/file

AWS IAM Policy Example

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "LeastPrivilegeS3Access",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::specific-bucket/specific-prefix/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "192.168.1.0/24"
                }
            }
        }
    ]
}

Kubernetes RBAC

# Role with minimal permissions
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
---
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: production
subjects:
- kind: ServiceAccount
  name: monitoring-sa
  namespace: production
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Database Access Control

-- Create role with specific permissions
CREATE ROLE app_readonly;
GRANT SELECT ON schema_name.* TO app_readonly;

-- Create user with limited privileges
CREATE USER 'app_service'@'localhost' IDENTIFIED BY 'secure_password';
GRANT SELECT, INSERT ON app_db.transactions TO 'app_service'@'localhost';

-- Revoke unnecessary privileges
REVOKE ALL PRIVILEGES ON *.* FROM 'app_service'@'localhost';

-- View granted privileges
SHOW GRANTS FOR 'app_service'@'localhost';

Examples

Service Account Best Practice:

# Kubernetes: Disable automounting of service account token
apiVersion: v1
kind: ServiceAccount
metadata:
  name: restricted-sa
automountServiceAccountToken: false
---
# Pod using restricted service account
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  serviceAccountName: restricted-sa
  automountServiceAccountToken: false
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    readOnlyRootFilesystem: true

Regular Security Audits

Key Concepts

Concept Description
Vulnerability Assessment Systematic review of security weaknesses in systems
Penetration Testing Simulated attacks to identify exploitable vulnerabilities
Compliance Auditing Verification against regulatory and policy requirements
Configuration Review Analysis of system configurations against security baselines
Log Analysis Review of audit trails for suspicious activities

Common Commands and Tools

System Auditing

# Linux audit system
sudo auditctl -l                           # List current rules
sudo ausearch -k failed_login              # Search audit logs
sudo aureport --auth                       # Authentication report

# Check for SUID/SGID files
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} \; 2>/dev/null

# Find world-writable files
find / -type f -perm -002 -exec ls -l {} \; 2>/dev/null

# Check listening ports
ss -tulpn
netstat -tulpn

# Review failed login attempts
grep "Failed password" /var/log/auth.log | tail -20
lastb | head -20

# Check user accounts
awk -F: '($3 == 0) {print $1}' /etc/passwd  # Find users with UID 0
cat /etc/passwd | grep -v nologin | grep -v false  # Users with shell access

Vulnerability Scanning

# Nmap security scanning
nmap -sV --script=vuln target.example.com
nmap -sS -sV -O -p- target.example.com

# OpenVAS/GVM scanning
gvm-cli --gmp-username admin --gmp-password pass socket \
  --socketpath /var/run/gvmd.sock \
  --xml "<get_tasks/>"

# Lynis security audit
sudo lynis audit system
sudo lynis audit system --quick

# Trivy container scanning
trivy image myapp:latest
trivy fs --security-checks vuln,config /path/to/project

# OWASP ZAP API scanning
zap-cli quick-scan --self-contained --spider -r https://target.example.com

Cloud Security Auditing

# AWS Security Hub
aws securityhub get-findings --filters '{"SeverityLabel": [{"Value": "CRITICAL", "Comparison": "EQUALS"}]}'

# AWS Config compliance
aws configservice get-compliance-summary-by-config-rule

# Scout Suite (multi-cloud)
scout aws --profile production

# Prowler (AWS)
prowler -c check11,check12,check13
prowler -g cislevel1

# CloudSploit
cloudsploit scan --config config.js

Audit Checklist Example

## Monthly Security Audit Checklist

### Access Control
- [ ] Review user accounts and remove unused accounts
- [ ] Verify service account permissions
- [ ] Check for orphaned resources
- [ ] Review API key rotation status

### Network Security
- [ ] Review firewall rules
- [ ] Check security group configurations
- [ ] Verify VPN access logs
- [ ] Scan for open ports

### Data Protection
- [ ] Verify encryption at rest
- [ ] Check certificate expiration dates
- [ ] Review backup integrity
- [ ] Test data recovery procedures

### Logging and Monitoring
- [ ] Verify log retention policies
- [ ] Review alerting thresholds
- [ ] Check SIEM rule effectiveness
- [ ] Analyse anomaly detection reports

Incident Response Planning

Key Concepts

Phase Description
Preparation Establishing policies, procedures, and tools before incidents occur
Identification Detecting and determining whether an event is a security incident
Containment Limiting the scope and impact of the incident
Eradication Removing the threat from the environment
Recovery Restoring systems to normal operation
Lessons Learned Documenting findings and improving processes

Incident Response Flow

NoYesCriticalHighMediumLowSecurity EventDetectedIs it an Incident?Document and CloseClassify SeveritySeverity LevelImmediate EscalationUrgent ResponseStandard ResponseScheduled ResponseContainment ActionsEvidence CollectionThreat EradicationSystem RecoveryPost-Incident ReviewUpdate ProceduresClose IncidentNoYesCriticalHighMediumLowSecurity EventDetectedIs it an Incident?Document and CloseClassify SeveritySeverity LevelImmediate EscalationUrgent ResponseStandard ResponseScheduled ResponseContainment ActionsEvidence CollectionThreat EradicationSystem RecoveryPost-Incident ReviewUpdate ProceduresClose Incident

Common Patterns and Scripts

Initial Response Script

#!/bin/bash
# incident-response-initial.sh
# Initial incident response data collection

INCIDENT_ID="IR-$(date +%Y%m%d-%H%M%S)"
OUTPUT_DIR="/var/incident-response/${INCIDENT_ID}"

mkdir -p "${OUTPUT_DIR}"

echo "Collecting incident data for ${INCIDENT_ID}..."

# System information
uname -a > "${OUTPUT_DIR}/system_info.txt"
uptime >> "${OUTPUT_DIR}/system_info.txt"

# Network connections
ss -tulpn > "${OUTPUT_DIR}/network_connections.txt"
netstat -rn > "${OUTPUT_DIR}/routing_table.txt"

# Process information
ps auxwww > "${OUTPUT_DIR}/process_list.txt"
lsof -i > "${OUTPUT_DIR}/open_files_network.txt"

# User information
who > "${OUTPUT_DIR}/logged_in_users.txt"
last -100 > "${OUTPUT_DIR}/recent_logins.txt"

# Recent file modifications
find /etc -mtime -1 -type f > "${OUTPUT_DIR}/recently_modified_etc.txt"
find /var/log -mtime -1 -type f > "${OUTPUT_DIR}/recently_modified_logs.txt"

# Copy relevant logs
cp /var/log/auth.log "${OUTPUT_DIR}/"
cp /var/log/syslog "${OUTPUT_DIR}/"

# Create hash of collected files
find "${OUTPUT_DIR}" -type f -exec sha256sum {} \; > "${OUTPUT_DIR}/file_hashes.txt"

echo "Initial data collection complete: ${OUTPUT_DIR}"

Containment Actions

# Network isolation
# Block specific IP
iptables -A INPUT -s <malicious_ip> -j DROP
iptables -A OUTPUT -d <malicious_ip> -j DROP

# Isolate compromised host
iptables -A INPUT -i eth0 -j DROP
iptables -A OUTPUT -o eth0 -j DROP

# AWS Security Group isolation
aws ec2 modify-instance-attribute \
  --instance-id i-1234567890abcdef0 \
  --groups sg-isolation-group

# Kubernetes pod isolation
kubectl label pod compromised-pod quarantine=true
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: quarantine-policy
spec:
  podSelector:
    matchLabels:
      quarantine: "true"
  policyTypes:
  - Ingress
  - Egress
EOF

# Disable user account
usermod -L suspicious_user
passwd -l suspicious_user

# Revoke AWS credentials
aws iam update-access-key --access-key-id AKIA... --status Inactive --user-name compromised-user

Incident Report Template

# Incident Report: [INCIDENT_ID]

## Executive Summary
Brief description of the incident, impact, and resolution status.

## Timeline
| Time (UTC) | Event |
|------------|-------|
| YYYY-MM-DD HH:MM | Initial detection |
| YYYY-MM-DD HH:MM | Incident declared |
| YYYY-MM-DD HH:MM | Containment complete |
| YYYY-MM-DD HH:MM | Eradication complete |
| YYYY-MM-DD HH:MM | Recovery complete |

## Impact Assessment
- Systems affected:
- Data compromised:
- Business impact:
- Users affected:

## Root Cause Analysis
Description of how the incident occurred.

## Actions Taken
1. Containment measures
2. Eradication steps
3. Recovery procedures

## Recommendations
- Immediate actions
- Long-term improvements

## Lessons Learned
Key takeaways and process improvements.

Secure Coding Practices

Key Concepts

Concept Description
Input Validation Verify all input data meets expected format and constraints
Output Encoding Encode data appropriately for its output context
Parameterised Queries Use prepared statements to prevent SQL injection
Authentication & Session Management Implement secure identity verification
Error Handling Handle errors without exposing sensitive information
Cryptography Use strong, well-tested cryptographic implementations

Common Patterns

Input Validation

# Python input validation
import re
from typing import Optional

def validate_email(email: str) -> bool:
    """Validate email format."""
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))

def validate_username(username: str) -> bool:
    """Validate username: alphanumeric, 3-20 characters."""
    pattern = r'^[a-zA-Z0-9_]{3,20}$'
    return bool(re.match(pattern, username))

def sanitise_input(user_input: str) -> str:
    """Remove potentially dangerous characters."""
    # Remove null bytes
    sanitised = user_input.replace('\x00', '')
    # Limit length
    sanitised = sanitised[:1000]
    return sanitised

# Using Pydantic v2 for validation
from pydantic import BaseModel, EmailStr, Field, field_validator

class UserInput(BaseModel):
    email: EmailStr
    # Pydantic v2: Field(regex=...) was renamed to pattern=
    username: str = Field(..., min_length=3, max_length=20, pattern=r'^[a-zA-Z0-9_]+$')
    age: int = Field(..., ge=0, le=150)

    # Pydantic v2: @validator is deprecated in favour of @field_validator
    @field_validator('username')
    @classmethod
    def username_must_not_contain_spaces(cls, v):
        if ' ' in v:
            raise ValueError('Username must not contain spaces')
        return v

SQL Injection Prevention

# WRONG - Vulnerable to SQL injection
cursor.execute(f"SELECT * FROM users WHERE username = '{username}'")

# CORRECT - Parameterised query
cursor.execute("SELECT * FROM users WHERE username = %s", (username,))

# SQLAlchemy ORM (safe by default)
from sqlalchemy.orm import Session
from models import User

def get_user(db: Session, username: str):
    return db.query(User).filter(User.username == username).first()

# Raw SQL with SQLAlchemy (parameterised)
from sqlalchemy import text

result = db.execute(
    text("SELECT * FROM users WHERE username = :username"),
    {"username": username}
)

Cross-Site Scripting (XSS) Prevention

# Python - HTML encoding
from markupsafe import escape

user_input = "<script>alert('xss')</script>"
safe_output = escape(user_input)
# Result: &lt;script&gt;alert('xss')&lt;/script&gt;

# Django template (auto-escapes by default)
# templates/user_profile.html
# {{ user.name }}  <!-- Automatically escaped -->

# Jinja2 with autoescape
from jinja2 import Environment, select_autoescape

env = Environment(
    autoescape=select_autoescape(['html', 'xml'])
)
// JavaScript - DOM manipulation
// WRONG - innerHTML with user input
element.innerHTML = userInput;

// CORRECT - textContent for text
element.textContent = userInput;

// CORRECT - Use DOMPurify for HTML
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);

Secure Password Handling

# Python password hashing with bcrypt
import bcrypt

def hash_password(password: str) -> bytes:
    """Hash password with bcrypt."""
    salt = bcrypt.gensalt(rounds=12)
    return bcrypt.hashpw(password.encode('utf-8'), salt)

def verify_password(password: str, hashed: bytes) -> bool:
    """Verify password against hash."""
    return bcrypt.checkpw(password.encode('utf-8'), hashed)

# Using passlib (recommended)
from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def hash_password(password: str) -> str:
    return pwd_context.hash(password)

def verify_password(plain_password: str, hashed_password: str) -> bool:
    return pwd_context.verify(plain_password, hashed_password)

Secure API Design

# FastAPI with security best practices
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
import jwt  # PyJWT — prefer over python-jose, which has unpatched CVEs (CVE-2024-33663/33664)
from datetime import datetime, timedelta, timezone

app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

SECRET_KEY = "your-secret-key"  # Use environment variable
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

def create_access_token(data: dict) -> str:
    to_encode = data.copy()
    expire = datetime.now(timezone.utc) + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
    except jwt.InvalidTokenError:
        raise credentials_exception
    return username

@app.get("/protected")
async def protected_route(current_user: str = Depends(get_current_user)):
    return {"message": f"Hello {current_user}"}

Security Headers

# FastAPI security headers middleware
from fastapi import FastAPI
from starlette.middleware.base import BaseHTTPMiddleware

class SecurityHeadersMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        response = await call_next(request)
        response.headers["X-Content-Type-Options"] = "nosniff"
        response.headers["X-Frame-Options"] = "DENY"
        response.headers["X-XSS-Protection"] = "1; mode=block"
        response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
        response.headers["Content-Security-Policy"] = "default-src 'self'"
        response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
        return response

app = FastAPI()
app.add_middleware(SecurityHeadersMiddleware)

Dependency Management

Key Concepts

Concept Description
Software Composition Analysis (SCA) Identifying and analysing third-party components
Vulnerability Scanning Detecting known vulnerabilities in dependencies
License Compliance Ensuring dependencies meet licensing requirements
Version Pinning Locking dependencies to specific versions
Supply Chain Security Protecting against compromised packages

Common Commands and Tools

Python Dependency Security

# pip-audit for vulnerability scanning
pip install pip-audit
pip-audit
pip-audit --requirement requirements.txt

# Safety check
pip install safety
safety check
safety check -r requirements.txt

# Generate locked requirements
pip freeze > requirements.txt

# Use pip-tools for better dependency management
pip install pip-tools
pip-compile requirements.in
pip-sync requirements.txt

# Bandit for security linting
pip install bandit
bandit -r ./src
bandit -r ./src -f json -o bandit-report.json

JavaScript/Node.js Dependency Security

# npm audit
npm audit
npm audit --json
npm audit fix
npm audit fix --force  # Use with caution

# Snyk
npm install -g snyk
snyk test
snyk monitor

# Generate package-lock.json
npm install --package-lock-only

# Check for outdated packages
npm outdated

# Yarn audit
yarn audit
yarn audit --json

Container Image Scanning

# Trivy
trivy image myapp:latest
trivy image --severity HIGH,CRITICAL myapp:latest
trivy image --format json --output results.json myapp:latest

# Grype
grype myapp:latest
grype myapp:latest --output json

# Docker Scout
docker scout cves myapp:latest
docker scout recommendations myapp:latest

# Anchore/Syft
syft myapp:latest -o json > sbom.json
grype sbom:sbom.json

Dependabot Configuration

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10
    groups:
      development-dependencies:
        dependency-type: "development"
      production-dependencies:
        dependency-type: "production"

  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    ignore:
      - dependency-name: "aws-sdk"
        update-types: ["version-update:semver-patch"]

  - package-ecosystem: "docker"
    directory: "/"
    schedule:
      interval: "weekly"

  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

Software Bill of Materials (SBOM)

# Generate SBOM with Syft
syft ./project -o spdx-json > sbom.spdx.json
syft ./project -o cyclonedx-json > sbom.cyclonedx.json

# Generate SBOM for container
syft myapp:latest -o cyclonedx-json > container-sbom.json

# Python SBOM
pip install cyclonedx-bom
cyclonedx-py --format json --output sbom.json

# Node.js SBOM
npx @cyclonedx/cyclonedx-npm --output-format JSON --output-file sbom.json

Patch Management

Key Concepts

Concept Description
Vulnerability Assessment Identifying systems requiring patches
Patch Prioritisation Ranking patches by criticality and risk
Testing Validating patches in non-production environments
Deployment Rolling out patches with minimal disruption
Verification Confirming successful patch application

Common Commands

Linux Patch Management

# Ubuntu/Debian
sudo apt update
sudo apt list --upgradable
sudo apt upgrade -y
sudo apt dist-upgrade -y

# Check for security updates only
sudo apt list --upgradable 2>/dev/null | grep -i security

# Unattended upgrades for security patches
sudo apt install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades

# View update history
cat /var/log/apt/history.log

# RHEL/CentOS/Rocky
sudo dnf check-update
sudo dnf update -y
sudo dnf update --security

# List security advisories
sudo dnf updateinfo list security

# Check kernel version
uname -r

Container Image Updates

# Rebuild with latest base image
docker build --no-cache -t myapp:latest .

# Pull latest base images
docker pull python:3.11-slim
docker pull node:20-alpine

# Update base image in Dockerfile
# FROM python:3.11-slim@sha256:abc123...  # Pin to digest

# Kubernetes rolling update
kubectl set image deployment/myapp container=myapp:v2.0.1
kubectl rollout status deployment/myapp
kubectl rollout undo deployment/myapp  # Rollback if needed

Automated Patch Pipeline

# GitLab CI pipeline for patch management
stages:
  - scan
  - patch
  - test
  - deploy

vulnerability-scan:
  stage: scan
  image: aquasec/trivy:latest
  script:
    - trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:latest
  allow_failure: true

update-dependencies:
  stage: patch
  script:
    - pip install pip-tools
    - pip-compile --upgrade requirements.in
    - pip-audit -r requirements.txt
  artifacts:
    paths:
      - requirements.txt

test-patches:
  stage: test
  script:
    - pip install -r requirements.txt
    - pytest tests/
  needs:
    - update-dependencies

deploy-patches:
  stage: deploy
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  only:
    - main
  needs:
    - test-patches

Patch Management Process

NoYesIdentifyVulnerabilitiesAssess RiskPrioritise PatchesTest in StagingTests Pass?Investigate IssuesSchedule DeploymentDeploy to ProductionVerify & MonitorDocument ChangesNoYesIdentifyVulnerabilitiesAssess RiskPrioritise PatchesTest in StagingTests Pass?Investigate IssuesSchedule DeploymentDeploy to ProductionVerify & MonitorDocument Changes

Multi-Factor Authentication

Key Concepts

Factor Type Examples
Something You Know Knowledge Password, PIN, security questions
Something You Have Possession Hardware token, mobile device, smart card
Something You Are Inherence Fingerprint, facial recognition, voice

Implementation Patterns

TOTP (Time-based One-Time Password)

# Python TOTP implementation with pyotp
import pyotp
import qrcode
from io import BytesIO

def generate_totp_secret() -> str:
    """Generate a new TOTP secret."""
    return pyotp.random_base32()

def get_totp_uri(secret: str, user_email: str, issuer: str) -> str:
    """Generate provisioning URI for authenticator apps."""
    totp = pyotp.TOTP(secret)
    return totp.provisioning_uri(name=user_email, issuer_name=issuer)

def generate_qr_code(uri: str) -> bytes:
    """Generate QR code for TOTP URI."""
    qr = qrcode.QRCode(version=1, box_size=10, border=5)
    qr.add_data(uri)
    qr.make(fit=True)
    img = qr.make_image(fill_colour='black', back_colour='white')
    buffer = BytesIO()
    img.save(buffer, format='PNG')
    return buffer.getvalue()

def verify_totp(secret: str, token: str) -> bool:
    """Verify TOTP token."""
    totp = pyotp.TOTP(secret)
    return totp.verify(token, valid_window=1)

# Usage example
secret = generate_totp_secret()
uri = get_totp_uri(secret, "user@example.com", "MyApp")
qr_code = generate_qr_code(uri)

# Verify user's token
user_token = "123456"
is_valid = verify_totp(secret, user_token)

WebAuthn/FIDO2 Implementation

# FastAPI WebAuthn implementation
from fastapi import FastAPI, HTTPException
from webauthn import (
    generate_registration_options,
    verify_registration_response,
    generate_authentication_options,
    verify_authentication_response,
)
from webauthn.helpers.structs import (
    AuthenticatorSelectionCriteria,
    UserVerificationRequirement,
)

app = FastAPI()

RP_ID = "example.com"
RP_NAME = "Example Application"
ORIGIN = "https://example.com"

@app.post("/webauthn/register/begin")
async def registration_begin(user_id: str, username: str):
    options = generate_registration_options(
        rp_id=RP_ID,
        rp_name=RP_NAME,
        user_id=user_id.encode(),
        user_name=username,
        user_display_name=username,
        authenticator_selection=AuthenticatorSelectionCriteria(
            user_verification=UserVerificationRequirement.PREFERRED,
        ),
    )
    # Store challenge in session
    return options

@app.post("/webauthn/register/complete")
async def registration_complete(credential: dict, expected_challenge: bytes):
    try:
        verification = verify_registration_response(
            credential=credential,
            expected_challenge=expected_challenge,
            expected_rp_id=RP_ID,
            expected_origin=ORIGIN,
        )
        # Store credential in database
        return {"status": "success", "credential_id": verification.credential_id}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))

SSH Key-based Authentication with MFA

# /etc/ssh/sshd_config
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

# Install Google Authenticator PAM
sudo apt install libpam-google-authenticator

# Configure PAM for SSH
# /etc/pam.d/sshd
auth required pam_google_authenticator.so

# User setup
google-authenticator -t -d -f -r 3 -R 30 -w 3

AWS MFA Enforcement

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowViewAccountInfo",
            "Effect": "Allow",
            "Action": [
                "iam:GetAccountPasswordPolicy",
                "iam:ListVirtualMFADevices"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowManageOwnMFA",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:ResyncMFADevice"
            ],
            "Resource": [
                "arn:aws:iam::*:mfa/${aws:username}",
                "arn:aws:iam::*:user/${aws:username}"
            ]
        },
        {
            "Sid": "DenyAllExceptListedIfNoMFA",
            "Effect": "Deny",
            "NotAction": [
                "iam:CreateVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:GetUser",
                "iam:ListMFADevices",
                "iam:ListVirtualMFADevices",
                "iam:ResyncMFADevice",
                "sts:GetSessionToken"
            ],
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        }
    ]
}

Quick Reference

Practice Key Actions Tools
Least Privilege Minimal permissions, RBAC, regular access reviews IAM policies, Kubernetes RBAC, ACLs
Security Audits Vulnerability scanning, compliance checks, log analysis Lynis, Trivy, Prowler, OpenVAS
Incident Response Detection, containment, eradication, recovery SIEM, forensic tools, runbooks
Secure Coding Input validation, parameterised queries, output encoding SAST tools, linters, security libraries
Dependency Management SCA, vulnerability scanning, SBOM pip-audit, npm audit, Snyk, Dependabot
Patch Management Assessment, testing, staged rollout, verification Package managers, CI/CD pipelines
MFA Multiple factors, hardware tokens, TOTP pyotp, WebAuthn, hardware keys

Common Issues and Solutions

Issue Cause Solution
Excessive permissions granted Default to permissive access Implement least privilege by default; use permission boundaries
Outdated dependencies with vulnerabilities No regular scanning or updates Automate dependency scanning in CI/CD; enable Dependabot
Slow incident response Lack of preparation and runbooks Create and rehearse incident response plans regularly
SQL injection vulnerabilities String concatenation in queries Use parameterised queries and ORM frameworks
Weak authentication Passwords only, no MFA Implement MFA for all accounts; enforce strong password policies
Unpatched systems Manual patching processes Automate patch management; use infrastructure as code
Hardcoded secrets Secrets in source code Use secret managers (Vault, AWS Secrets Manager); scan for secrets
Missing security headers Default server configuration Configure security headers in reverse proxy or application
Inadequate logging Logs not captured or retained Centralise logging; set appropriate retention periods
Shadow IT and unknown assets No asset inventory Maintain comprehensive asset inventory; regular discovery scans

Related Topics

The following topics complement this security best practices cheatsheet:

  1. Network Security and Firewalls - Deep dive into network segmentation, firewall rules, VPNs, and zero-trust architecture
  2. Encryption and Cryptography - Comprehensive coverage of encryption at rest, in transit, key management, and certificate management
  3. Container Security - Detailed practices for securing Docker, Kubernetes, and container orchestration platforms
  4. Cloud Security Posture Management - AWS, GCP, and Azure security configurations, compliance frameworks, and cloud-native security tools
  5. DevSecOps Practices - Integrating security into CI/CD pipelines, security testing automation, and shift-left security
  6. Identity and Access Management (IAM) - SSO, OAuth2, OpenID Connect, directory services, and federation