Audit logs stored in the same database as application data can be silently deleted or modified by a compromised admin account, eliminating the forensic record of the compromise itself. NIST 800-53 rev5 AU-9 (Protection of Audit Information) requires that log write access be restricted to the audit system only; AU-10 (Non-Repudiation) mandates a mechanism to prove log integrity. CMMC 2.0 AU.L2-3.3.2 extends this requirement to CUI systems. CWE-345 (Insufficient Verification of Data Authenticity) covers the specific failure of storing records without integrity protection. An attacker who can modify logs can rewrite or delete evidence of their own access.
Medium because tamper-evident logging does not prevent breaches but is required to detect them and preserve legally admissible forensic evidence — its absence is often discovered only during post-breach investigation.
Ship audit logs to a dedicated service outside the application database. For a self-managed option, implement a hash chain where each entry references its predecessor's digest.
// lib/tamper-evident-logger.ts
import crypto from 'crypto'
import { db } from './db'
export async function appendAuditLog(event: Record<string, unknown>) {
const prev = await db.auditLog.findFirst({ orderBy: { id: 'desc' } })
const prevHash = prev?.hash ?? '0'.repeat(64)
const payload = JSON.stringify({ ...event, ts: Date.now() })
const hash = crypto.createHash('sha256').update(prevHash + payload).digest('hex')
await db.auditLog.create({ data: { payload, hash, prevHash } })
}
Prefer a managed, append-only log service — AWS CloudWatch Logs (with log group retention and no delete IAM actions granted to the app role), Datadog, or Azure Monitor all provide tamper-resistance without custom code. Restrict DELETE on audit_logs tables at the database level so the application service role cannot issue it.
ID: gov-fisma-fedramp.audit-accountability.logs-tamper-evident
Severity: medium
What to look for: Examine how audit logs are stored and protected. Quote the actual storage configuration or service name used. Enumerate all log storage locations and for each classify whether it provides immutable or tamper-evident storage. Look for logging systems that support immutable log storage, write-once-read-many (WORM) configuration, or cryptographic checksums. Check whether logs are stored in a separate system from application data, whether log deletion is restricted, and whether there's a hash chain or signature mechanism to detect tampering.
Pass criteria: Audit logs are stored in a protected system (separate database, managed log service like AWS CloudWatch or Datadog, or file system with restricted permissions). Logs cannot be deleted by regular users; only administrators can modify logs, and modifications are themselves logged. At least 1 tamper-detection mechanism is present (checksums, digital signatures, or append-only storage).
Fail criteria: Logs are stored in the same application database as user data (easily modified), there's no audit trail for log modifications, or anyone can delete logs.
Skip (N/A) when: The site serves only public read-only content with no user actions.
Detail on fail: Specify the protection gaps. Example: "Audit logs stored in main PostgreSQL database in 'audit_logs' table. No special protection; app admins can DELETE FROM audit_logs. No checksums or signatures."
Remediation: Implement tamper-evident logging:
// lib/tamper-evident-logger.ts
import crypto from 'crypto'
let lastHash = '0'.repeat(64) // Initial hash
export async function logWithHash(event: any) {
const eventStr = JSON.stringify(event)
// Create hash chain: each log references the previous log's hash
const hash = crypto
.createHash('sha256')
.update(lastHash + eventStr)
.digest('hex')
const logEntry = {
...event,
hash,
previousHash: lastHash,
timestamp: new Date().toISOString()
}
// Store in immutable log service (e.g., AWS CloudWatch, Datadog, separate DB)
await fetch('https://logs.example.com/api/logs', {
method: 'POST',
body: JSON.stringify(logEntry)
})
lastHash = hash
}
Or delegate to a managed service: AWS CloudWatch, Azure Monitor, Datadog, or Splunk all provide tamper-evident logging out of the box.