🔒 Security Measures · Sandy's Media Hub

Technical Report · 14 September 2025 · Version 1.0

This document explains the five core security measures implemented in the CMS, how they work technically, and how they align with UK GDPR requirements.

Measure Protects Against GDPR Articles
1. CSRF Tokens Cross-site request forgery Art. 5(1)(f), Art. 32
2. Login Throttling Brute force attacks Art. 5(1)(f), Art. 32
3. Session Rotation Session fixation/hijacking Art. 5(1)(f), Art. 32
4. Password Hashing (bcrypt) Credential theft Art. 5(1)(f), Art. 32
5. Activity Logging Unauthorised access, audit trail Art. 5(2), Art. 24, Art. 30

1. CSRF Tokens

GDPR Art. 5(1)(f), Art. 32

What It Is

Cross-Site Request Forgery (CSRF) protection ensures that forms can only be submitted from our own site, not from malicious external sites.

How It Works (from your code)

// On page load:
if (!isset($_SESSION['csrf'])) {
    $_SESSION['csrf'] = bin2hex(random_bytes(32));
}
$csrf = $_SESSION['csrf'];

// In form:
<input type="hidden" name="csrf" value="<?= htmlspecialchars($csrf) ?>">

// On submission:
$posted_csrf = $_POST['csrf'] ?? '';
if (!hash_equals($csrf, $posted_csrf)) {
    $error = 'Security token invalid';
}

Technical Details

GDPR Alignment

Article 32 requires "appropriate technical measures" to ensure security. CSRF tokens prevent attackers from using authenticated sessions to modify data without consent.

2. Login Throttling

GDPR Art. 5(1)(f), Art. 32

What It Is

Limits the number of failed login attempts to prevent brute-force password guessing.

How It Works (from your code)

$throttle_key = 'login_attempts';
$throttle_window = 300; // 5 minutes
$max_attempts = 8;

// Clean old attempts
$cutoff = time() - $throttle_window;
$_SESSION[$throttle_key] = array_filter($_SESSION[$throttle_key], fn($ts) => $ts > $cutoff);

// Check throttle
if (count($_SESSION[$throttle_key]) >= $max_attempts) {
    $error = 'Too many attempts. Please wait.';
}

// On failed login:
$_SESSION[$throttle_key][] = time();

// On success:
$_SESSION[$throttle_key] = []; // Clear attempts

Technical Details

GDPR Alignment

Prevents unauthorised access to personal data by blocking automated brute-force attacks. The attempt count is stored only temporarily and not linked to other personal data.

3. Session Rotation

GDPR Art. 5(1)(f), Art. 32

What It Is

Regenerates the session ID after successful login to prevent session fixation attacks.

How It Works (from your code)

// After password verification:
session_regenerate_id(true);

Technical Details

GDPR Alignment

Protects session integrity, ensuring that authenticated access to personal data cannot be hijacked using pre-set session IDs.

4. Password Hashing (bcrypt)

GDPR Art. 5(1)(f), Art. 32

What It Is

Passwords are never stored in plain text. They are hashed using bcrypt with automatic salting.

How It Works (from your code)

// Registration:
$hash = password_hash($password, PASSWORD_DEFAULT);

// Login:
if (password_verify($password, $user['password_hash'])) {
    // success
}

Technical Details

GDPR Alignment

Article 32 requires pseudonymisation and encryption of personal data where appropriate. Hashed passwords are a form of pseudonymisation - the original password cannot be retrieved, protecting users even in a data breach.

5. Activity Logging

GDPR Art. 5(2), Art. 24, Art. 30

What It Is

Every important action (login success/fail, registration, errors) is logged with metadata for audit trails.

How It Works (from your code)

// On login success:
logActivity('login_success', [
    'module'  => 'auth',
    'status'  => 'success',
    'details' => ['email' => $email, 'role' => $user['role']]
]);

// On login failure:
logActivity('login_failed', [
    'module'  => 'auth',
    'status'  => 'failed',
    'details' => ['email' => $email, 'reason' => $msg]
]);

// On registration:
logActivity('register_request', [
    'module'  => 'auth',
    'status'  => 'pending',
    'details' => ['email' => $email, 'profile_type' => $ptype]
]);

Technical Details

GDPR Alignment

Multiple GDPR requirements are satisfied:

Note: Logs are automatically pruned after 365 days, matching our Privacy Policy commitment.

Summary: Security & GDPR Alignment

Requirement How Sandy's Media Hub Meets It
Art. 5(1)(f) - Integrity & confidentiality All five measures work together to prevent unauthorised access to personal data
Art. 5(2) - Accountability Activity logging provides full audit trail of who accessed what and when
Art. 24 - Responsibility of controller Technical measures demonstrate appropriate security controls are in place
Art. 30 - Records of processing Activity logs serve as machine-readable records of processing activities
Art. 32 - Security of processing All five measures are explicitly listed as appropriate technical measures

This technical report is based on the actual codebase of Sandy's Media Hub and aligns with the Privacy Policy effective 14 September 2025.