- Add comprehensive error handling system with custom error pages - Implement professional enterprise-style design with Tailwind CSS - Create modular HMVC architecture with clean separation of concerns - Add security features: CSRF protection, XSS filtering, Argon2ID hashing - Include CLI tools for development workflow - Add error reporting dashboard with system monitoring - Implement responsive design with consistent slate color scheme - Replace all emoji icons with professional SVG icons - Add comprehensive test suite with PHPUnit - Include database migrations and seeders - Add proper exception handling with fallback pages - Implement template engine with custom syntax support - Add helper functions and facades for clean code - Include proper logging and debugging capabilities
188 lines
4.9 KiB
PHP
188 lines
4.9 KiB
PHP
<?php
|
|
|
|
namespace App\Core;
|
|
|
|
/**
|
|
* NovaCore Security Helper
|
|
* XSS, CSRF, and other security features
|
|
*/
|
|
class Security
|
|
{
|
|
private string $appKey;
|
|
private string $csrfTokenName;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->appKey = getenv('APP_KEY') ?: 'default-key-change-in-production';
|
|
$this->csrfTokenName = getenv('CSRF_TOKEN_NAME') ?: '_token';
|
|
}
|
|
|
|
/**
|
|
* Initialize security features
|
|
*/
|
|
public function initialize(): void
|
|
{
|
|
// Set security headers
|
|
$this->setSecurityHeaders();
|
|
|
|
// Sanitize input
|
|
$this->sanitizeInput();
|
|
|
|
// Generate CSRF token if needed
|
|
$this->ensureCsrfToken();
|
|
}
|
|
|
|
/**
|
|
* Set security headers
|
|
*/
|
|
private function setSecurityHeaders(): void
|
|
{
|
|
// Prevent XSS
|
|
header('X-Content-Type-Options: nosniff');
|
|
header('X-Frame-Options: DENY');
|
|
header('X-XSS-Protection: 1; mode=block');
|
|
|
|
// Content Security Policy - Allow external CDNs for development
|
|
if (getenv('APP_ENV') === 'development' || getenv('APP_DEBUG') === 'true') {
|
|
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.tailwindcss.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self'");
|
|
} else {
|
|
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'");
|
|
}
|
|
|
|
// Strict Transport Security (HTTPS only)
|
|
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
|
|
header('Strict-Transport-Security: max-age=31536000; includeSubDomains');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sanitize all input data
|
|
*/
|
|
private function sanitizeInput(): void
|
|
{
|
|
$_GET = $this->sanitizeArray($_GET);
|
|
$_POST = $this->sanitizeArray($_POST);
|
|
$_REQUEST = $this->sanitizeArray($_REQUEST);
|
|
}
|
|
|
|
/**
|
|
* Sanitize array recursively
|
|
*/
|
|
private function sanitizeArray(array $data): array
|
|
{
|
|
foreach ($data as $key => $value) {
|
|
if (is_array($value)) {
|
|
$data[$key] = $this->sanitizeArray($value);
|
|
} else {
|
|
$data[$key] = $this->sanitizeString($value);
|
|
}
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Sanitize string input
|
|
*/
|
|
public function sanitizeString(string $input): string
|
|
{
|
|
// Remove null bytes
|
|
$input = str_replace(chr(0), '', $input);
|
|
|
|
// HTML encode special characters
|
|
$input = htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
|
|
|
return $input;
|
|
}
|
|
|
|
/**
|
|
* Generate CSRF token
|
|
*/
|
|
public function generateCsrfToken(): string
|
|
{
|
|
if (!isset($_SESSION['csrf_token'])) {
|
|
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
|
}
|
|
return $_SESSION['csrf_token'];
|
|
}
|
|
|
|
/**
|
|
* Verify CSRF token
|
|
*/
|
|
public function verifyCsrfToken(string $token): bool
|
|
{
|
|
if (!isset($_SESSION['csrf_token'])) {
|
|
return false;
|
|
}
|
|
|
|
return hash_equals($_SESSION['csrf_token'], $token);
|
|
}
|
|
|
|
/**
|
|
* Ensure CSRF token exists
|
|
*/
|
|
private function ensureCsrfToken(): void
|
|
{
|
|
if (!isset($_SESSION['csrf_token'])) {
|
|
$this->generateCsrfToken();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get CSRF token name
|
|
*/
|
|
public function getCsrfTokenName(): string
|
|
{
|
|
return $this->csrfTokenName;
|
|
}
|
|
|
|
/**
|
|
* Encrypt data using AES-256-GCM
|
|
*/
|
|
public function encrypt(string $data): string
|
|
{
|
|
$key = hash('sha256', $this->appKey, true);
|
|
$iv = random_bytes(16);
|
|
$ciphertext = openssl_encrypt($data, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
|
|
|
|
return base64_encode($iv . $tag . $ciphertext);
|
|
}
|
|
|
|
/**
|
|
* Decrypt data using AES-256-GCM
|
|
*/
|
|
public function decrypt(string $encryptedData): string
|
|
{
|
|
$data = base64_decode($encryptedData);
|
|
$key = hash('sha256', $this->appKey, true);
|
|
$iv = substr($data, 0, 16);
|
|
$tag = substr($data, 16, 16);
|
|
$ciphertext = substr($data, 32);
|
|
|
|
return openssl_decrypt($ciphertext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag);
|
|
}
|
|
|
|
/**
|
|
* Hash password securely
|
|
*/
|
|
public function hashPassword(string $password): string
|
|
{
|
|
return password_hash($password, PASSWORD_ARGON2ID);
|
|
}
|
|
|
|
/**
|
|
* Verify password
|
|
*/
|
|
public function verifyPassword(string $password, string $hash): bool
|
|
{
|
|
return password_verify($password, $hash);
|
|
}
|
|
|
|
/**
|
|
* Generate secure random string
|
|
*/
|
|
public function generateRandomString(int $length = 32): string
|
|
{
|
|
return bin2hex(random_bytes($length));
|
|
}
|
|
}
|