|
|
|
|
@ -1,4 +1,22 @@
|
|
|
|
|
<?php
|
|
|
|
|
// Check if we are serving HTTPS
|
|
|
|
|
function isHttps() {
|
|
|
|
|
// Check standard HTTPS indicators
|
|
|
|
|
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
// Check for proxy/load balancer headers
|
|
|
|
|
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] === 'on') {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Secure session configuration
|
|
|
|
|
ini_set('session.cookie_httponly', 1);
|
|
|
|
|
@ -10,10 +28,31 @@ if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
|
|
|
|
|
session_start();
|
|
|
|
|
|
|
|
|
|
// Security headers
|
|
|
|
|
header("X-Content-Type-Options: nosniff");
|
|
|
|
|
$isHttps = isHttps();
|
|
|
|
|
header("X-Frame-Options: SAMEORIGIN");
|
|
|
|
|
header("X-Content-Type-Options: nosniff");
|
|
|
|
|
header("X-XSS-Protection: 1; mode=block");
|
|
|
|
|
header("Referrer-Policy: strict-origin-when-cross-origin");
|
|
|
|
|
header("Permissions-Policy: geolocation=(), microphone=(), camera=()");
|
|
|
|
|
|
|
|
|
|
// Build CSP based on protocol
|
|
|
|
|
// Allow external images via both http: and https: since we can't control external links
|
|
|
|
|
$imgSrc = $isHttps ? "'self' data: https:" : "'self' data: http: https:";
|
|
|
|
|
|
|
|
|
|
$csp = "default-src 'self'; " .
|
|
|
|
|
"script-src 'self' 'unsafe-inline'; " .
|
|
|
|
|
"style-src 'self' 'unsafe-inline'; " .
|
|
|
|
|
"img-src {$imgSrc}; " .
|
|
|
|
|
"connect-src 'self'; " .
|
|
|
|
|
"frame-ancestors 'self'";
|
|
|
|
|
|
|
|
|
|
header("Content-Security-Policy: " . $csp);
|
|
|
|
|
|
|
|
|
|
// Only add HSTS if served over HTTPS
|
|
|
|
|
if ($isHttps) {
|
|
|
|
|
// HSTS: Force HTTPS for 1 year, but don't include subdomains (might be on local network)
|
|
|
|
|
header("Strict-Transport-Security: max-age=31536000");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (file_exists("./pgs/functions.php")) { require_once("./pgs/functions.php"); } else { die("functions.php does not exist."); }
|
|
|
|
|
if (file_exists("./pgs/config.inc.php")) { require_once("./pgs/config.inc.php"); } else { die("config.inc.php does not exist."); }
|
|
|
|
|
|