2025-02-17 13:52:46 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Security Headers Middleware
|
|
|
|
*
|
|
|
|
* Sets various security headers to protect against common web vulnerabilities:
|
|
|
|
* - HSTS: Force HTTPS connections
|
|
|
|
* - CSP: Content Security Policy to prevent XSS and other injection attacks
|
|
|
|
* - X-Frame-Options: Prevent clickjacking
|
|
|
|
* - X-Content-Type-Options: Prevent MIME-type sniffing
|
|
|
|
* - Referrer-Policy: Control referrer information
|
|
|
|
* - Permissions-Policy: Control browser features
|
|
|
|
*/
|
|
|
|
|
2025-02-19 09:08:42 +00:00
|
|
|
function applySecurityHeaders($testMode = false) {
|
|
|
|
$headers = [];
|
|
|
|
|
|
|
|
// Get current page
|
|
|
|
$current_page = $_GET['page'] ?? 'dashboard';
|
|
|
|
|
|
|
|
// Define pages that need media access
|
|
|
|
$media_enabled_pages = [
|
|
|
|
// 'conference' => ['camera', 'microphone'],
|
|
|
|
// 'call' => ['microphone'],
|
|
|
|
// Add more pages and their required permissions as needed
|
|
|
|
];
|
2025-02-17 13:52:46 +00:00
|
|
|
|
2025-02-19 09:08:42 +00:00
|
|
|
// Strict Transport Security (HSTS)
|
|
|
|
// Only enable if HTTPS is properly configured
|
|
|
|
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
|
|
|
|
$headers[] = 'Strict-Transport-Security: max-age=31536000; includeSubDomains; preload';
|
2025-02-17 14:03:59 +00:00
|
|
|
}
|
2025-02-19 09:08:42 +00:00
|
|
|
|
|
|
|
// Content Security Policy (CSP)
|
|
|
|
$csp = [
|
|
|
|
"default-src 'self'",
|
|
|
|
"script-src 'self' 'unsafe-inline' 'unsafe-eval'", // Required for Bootstrap and jQuery
|
|
|
|
"style-src 'self' 'unsafe-inline' https://use.fontawesome.com", // Allow FontAwesome CSS
|
|
|
|
"img-src 'self' data:", // Allow data: URLs for images
|
|
|
|
"font-src 'self' https://use.fontawesome.com", // Allow FontAwesome fonts
|
|
|
|
"connect-src 'self'",
|
|
|
|
"frame-ancestors 'none'", // Equivalent to X-Frame-Options: DENY
|
|
|
|
"form-action 'self'",
|
|
|
|
"base-uri 'self'",
|
|
|
|
"upgrade-insecure-requests" // Force HTTPS for all requests
|
|
|
|
];
|
|
|
|
$headers[] = "Content-Security-Policy: " . implode('; ', $csp);
|
|
|
|
|
|
|
|
// X-Frame-Options (legacy support)
|
|
|
|
$headers[] = 'X-Frame-Options: DENY';
|
|
|
|
|
|
|
|
// X-Content-Type-Options
|
|
|
|
$headers[] = 'X-Content-Type-Options: nosniff';
|
|
|
|
|
|
|
|
// X-XSS-Protection
|
|
|
|
$headers[] = 'X-XSS-Protection: 1; mode=block';
|
|
|
|
|
|
|
|
// Referrer-Policy
|
|
|
|
$headers[] = 'Referrer-Policy: strict-origin-when-cross-origin';
|
|
|
|
|
|
|
|
// Permissions-Policy
|
|
|
|
$permissions = [
|
|
|
|
'geolocation=()',
|
|
|
|
'payment=()',
|
|
|
|
'usb=()',
|
|
|
|
'accelerometer=()',
|
|
|
|
'autoplay=()',
|
|
|
|
'document-domain=()',
|
|
|
|
'encrypted-media=()',
|
|
|
|
'fullscreen=(self)',
|
|
|
|
'magnetometer=()',
|
|
|
|
'midi=()',
|
|
|
|
'sync-xhr=(self)',
|
|
|
|
'usb=()'
|
|
|
|
];
|
|
|
|
|
|
|
|
// Add camera/microphone permissions based on current page
|
|
|
|
$camera_allowed = false;
|
|
|
|
$microphone_allowed = false;
|
|
|
|
|
|
|
|
if (isset($media_enabled_pages[$current_page])) {
|
|
|
|
$allowed_media = $media_enabled_pages[$current_page];
|
|
|
|
if (in_array('camera', $allowed_media)) {
|
|
|
|
$camera_allowed = true;
|
|
|
|
}
|
|
|
|
if (in_array('microphone', $allowed_media)) {
|
|
|
|
$microphone_allowed = true;
|
|
|
|
}
|
2025-02-17 14:03:59 +00:00
|
|
|
}
|
|
|
|
|
2025-02-19 09:08:42 +00:00
|
|
|
// Add media permissions
|
|
|
|
$permissions[] = $camera_allowed ? 'camera=(self)' : 'camera=()';
|
|
|
|
$permissions[] = $microphone_allowed ? 'microphone=(self)' : 'microphone=()';
|
|
|
|
|
|
|
|
$headers[] = 'Permissions-Policy: ' . implode(', ', $permissions);
|
|
|
|
|
|
|
|
// Clear PHP version
|
|
|
|
if (!$testMode) {
|
|
|
|
header_remove('X-Powered-By');
|
|
|
|
}
|
2025-02-17 14:03:59 +00:00
|
|
|
|
2025-02-19 09:08:42 +00:00
|
|
|
// Prevent caching of sensitive pages
|
|
|
|
if (in_array($current_page, ['login', 'register', 'profile', 'security'])) {
|
|
|
|
$headers[] = 'Cache-Control: no-store, no-cache, must-revalidate, max-age=0';
|
|
|
|
$headers[] = 'Pragma: no-cache';
|
|
|
|
$headers[] = 'Expires: ' . gmdate('D, d M Y H:i:s', time() - 3600) . ' GMT';
|
|
|
|
}
|
2025-02-17 13:52:46 +00:00
|
|
|
|
2025-02-19 09:08:42 +00:00
|
|
|
if ($testMode) {
|
|
|
|
return $headers;
|
|
|
|
}
|
2025-02-17 13:52:46 +00:00
|
|
|
|
2025-02-19 09:08:42 +00:00
|
|
|
// Apply headers in production
|
|
|
|
foreach ($headers as $header) {
|
|
|
|
header($header);
|
|
|
|
}
|
2025-02-17 13:52:46 +00:00
|
|
|
}
|