Security Hardening Guide¶
Version: 1.0 Last Updated: 2026-01-18
Overview¶
This guide provides comprehensive security hardening recommendations for Cesivi Server in production environments. It covers authentication, network security, data protection, and operational security practices.
Related Documentation: - SECURITY_BEST_PRACTICES.md - General security best practices - SECURITY_DEPLOYMENT_CHECKLIST.md - Security deployment checklist - PRODUCTION_DEPLOYMENT_CHECKLIST.md - Production deployment guide
Table of Contents¶
- Authentication Security
- Transport Security (HTTPS/TLS)
- API Security
- Database Security
- Network Security
- Security Headers
- Secret Management
- Logging and Auditing
- Security Monitoring
- Hardening Checklist
Authentication Security¶
1.1: Disable Basic Authentication in Production¶
Risk: Basic authentication sends credentials in Base64 (easily decoded). Vulnerable to credential theft over unencrypted connections.
Recommendation: Disable Basic authentication in production environments.
Configuration:
{
"Cesivi": {
"Authentication": {
"EnableBasicAuth": false,
"EnableNtlm": true,
"EnableBearer": true
}
}
}
Alternative: Use Windows Authentication (NTLM/Kerberos) or Bearer tokens with OAuth2/OIDC.
1.2: Implement Strong Password Policies¶
Requirements: - Minimum 12 characters - Mix of uppercase, lowercase, numbers, symbols - No dictionary words or common patterns - Password expiration every 90 days - Password history (prevent reuse of last 5 passwords)
Implementation:
// Add to authentication middleware
services.Configure<PasswordPolicy>(options =>
{
options.MinimumLength = 12;
options.RequireUppercase = true;
options.RequireLowercase = true;
options.RequireDigit = true;
options.RequireSymbol = true;
options.PasswordExpirationDays = 90;
options.PasswordHistoryCount = 5;
});
1.3: Enable Multi-Factor Authentication (MFA)¶
Recommendation: Require MFA for administrative accounts and sensitive operations.
Integration Options: - Azure AD (supports MFA out of the box) - TOTP-based (Google Authenticator, Microsoft Authenticator) - SMS-based (less secure, use as fallback) - Hardware tokens (YubiKey, etc.)
Configuration Example:
{
"Cesivi": {
"Authentication": {
"MFA": {
"Enabled": true,
"RequireForAdmins": true,
"RequireForAll": false,
"Provider": "AzureAD"
}
}
}
}
1.4: Implement Account Lockout Policy¶
Protection: Prevents brute-force attacks on user accounts.
Recommendation: - Lock account after 5 failed login attempts - Lockout duration: 15-30 minutes - Alert admins on repeated lockouts
Configuration:
{
"Cesivi": {
"Authentication": {
"AccountLockout": {
"Enabled": true,
"MaxFailedAttempts": 5,
"LockoutDurationMinutes": 30,
"AlertOnLockout": true
}
}
}
}
1.5: API Key Rotation¶
Best Practice: Rotate API keys every 90 days or immediately after potential compromise.
Implementation: 1. Generate new API key 2. Distribute to clients with 30-day migration window 3. Monitor usage of old key 4. Revoke old key after migration complete
Example Rotation Script:
# Generate new API key
$newKey = New-Guid
$expirationDate = (Get-Date).AddDays(30)
# Update database
Invoke-SqlCmd -Query @"
UPDATE ApiKeys
SET IsActive = 0,
ExpirationDate = '$expirationDate',
RevokedDate = NULL
WHERE KeyValue = '$oldKey';
INSERT INTO ApiKeys (KeyValue, IsActive, CreatedDate, ExpirationDate)
VALUES ('$newKey', 1, GETDATE(), NULL);
"@
# Notify clients
Send-MailMessage -To $clients -Subject "API Key Rotation Required" `
-Body "Your API key will expire on $expirationDate. New key: $newKey"
Transport Security (HTTPS/TLS)¶
2.1: Enforce HTTPS¶
Requirement: All production traffic MUST use HTTPS (TLS 1.2 or higher).
Configuration:
{
"Cesivi": {
"Security": {
"RequireHttps": true,
"HttpsPort": 443,
"RedirectHttpToHttps": true
}
}
}
ASP.NET Core Middleware:
// In Program.cs or Startup.cs
app.UseHttpsRedirection();
app.UseHsts(); // HTTP Strict Transport Security
// Kestrel configuration
builder.WebHost.ConfigureKestrel(options =>
{
options.AddServerHeader = false; // Hide server version
options.Limits.MaxRequestBodySize = 52428800; // 50 MB max
});
2.2: TLS Configuration¶
Minimum TLS Version: TLS 1.2 (TLS 1.3 preferred if supported by clients)
Cipher Suites: Use only strong, modern cipher suites.
Recommended Cipher Suites:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
Disable Weak Ciphers: - No SSL v2/v3 - No TLS 1.0/1.1 - No RC4, MD5, DES, 3DES
Windows Server Configuration:
# Disable TLS 1.0 and 1.1
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server' -Force
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server' -Name 'Enabled' -Value 0 -PropertyType 'DWord'
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server' -Force
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server' -Name 'Enabled' -Value 0 -PropertyType 'DWord'
# Enable TLS 1.2 and 1.3
New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Force
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server' -Name 'Enabled' -Value 1 -PropertyType 'DWord'
# Restart required
Restart-Computer -Force
2.3: SSL Certificate Management¶
Best Practices: - Use certificates from trusted CA (Let's Encrypt, DigiCert, etc.) - Enable automatic renewal (Let's Encrypt: 60-day renewal) - Use wildcard certificates for multiple subdomains - Store private keys securely (hardware security module preferred)
Certificate Validation:
# Verify certificate
openssl s_client -connect cesivi.example.com:443 -showcerts
# Check expiration
openssl x509 -in cert.pem -noout -enddate
# Test SSL configuration
curl -I https://cesivi.example.com
API Security¶
3.1: Rate Limiting¶
Protection: Prevent API abuse and DDoS attacks.
Recommendation: - 100 requests/minute per IP for anonymous users - 1000 requests/minute per IP for authenticated users - 10,000 requests/minute per IP for trusted API clients
Implementation:
// Add to Program.cs
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("api", config =>
{
config.Window = TimeSpan.FromMinutes(1);
config.PermitLimit = 100;
config.QueueLimit = 10;
});
});
app.UseRateLimiter();
3.2: Input Validation¶
Requirement: Validate all user input to prevent injection attacks.
Common Attacks: - SQL Injection - Cross-Site Scripting (XSS) - XML External Entity (XXE) - LDAP Injection - Command Injection
Validation Rules:
// Example: List title validation
public class ListTitleValidator
{
private static readonly Regex ValidTitlePattern = new Regex(@"^[a-zA-Z0-9\s\-_]{1,255}$");
public static bool IsValid(string title)
{
if (string.IsNullOrWhiteSpace(title)) return false;
if (title.Length > 255) return false;
if (!ValidTitlePattern.IsMatch(title)) return false;
// Reject known malicious patterns
var blacklist = new[] { "<script", "javascript:", "onerror=", "../../" };
return !blacklist.Any(pattern => title.Contains(pattern, StringComparison.OrdinalIgnoreCase));
}
}
3.3: Output Encoding¶
Requirement: Encode all output to prevent XSS attacks.
Encoding Types:
- HTML encoding: <, >, &, "
- JavaScript encoding: \x3c, \x3e, \x27, \x22
- URL encoding: %3C, %3E, %27, %22
ASP.NET Core Automatic Encoding:
// Razor views automatically HTML-encode
@Model.UserInput // Safe by default
// Explicit encoding
@Html.Encode(Model.UserInput)
3.4: CORS Configuration¶
Requirement: Restrict Cross-Origin Resource Sharing to trusted domains only.
Production Configuration:
{
"Cesivi": {
"Cors": {
"AllowedOrigins": [
"https://intranet.example.com",
"https://portal.example.com"
],
"AllowedMethods": ["GET", "POST", "PUT", "DELETE"],
"AllowedHeaders": ["Authorization", "Content-Type", "Accept"],
"AllowCredentials": true,
"MaxAge": 3600
}
}
}
DO NOT use wildcards in production:
{
"AllowedOrigins": ["*"] // ❌ INSECURE - allows any origin
}
Database Security¶
4.1: Connection String Encryption¶
Requirement: Never store database credentials in plain text.
Options: 1. Environment Variables (basic) 2. Azure Key Vault (recommended for Azure deployments) 3. Windows DPAPI (Windows servers) 4. HashiCorp Vault (multi-cloud)
Using Environment Variables:
# Set environment variable
export CESIVI_DB_CONNECTION="Server=localhost;Database=CesiviDB;User=cesivi_app;Password=STRONG_PASSWORD"
# Reference in appsettings
{
"ConnectionStrings": {
"DefaultConnection": "${CESIVI_DB_CONNECTION}"
}
}
Using Azure Key Vault:
// Program.cs
builder.Configuration.AddAzureKeyVault(
new Uri("https://cesivi-keyvault.vault.azure.net/"),
new DefaultAzureCredential()
);
// appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "#{ConnectionString}#" // Retrieved from Key Vault
}
}
4.2: Principle of Least Privilege¶
Database User Permissions:
Application User (cesivi_app):
- SELECT, INSERT, UPDATE, DELETE on application tables only
- EXECUTE on stored procedures
- NO DROP, CREATE, ALTER permissions
- NO sa or db_owner role
Migration User (cesivi_migration):
- CREATE, ALTER, DROP on application schema
- Used only during deployment
- Credentials not accessible to application
SQL Example:
-- Create application user with limited permissions
CREATE USER cesivi_app WITH PASSWORD = 'STRONG_PASSWORD';
-- Grant only required permissions
GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::cesivi TO cesivi_app;
GRANT EXECUTE ON SCHEMA::cesivi TO cesivi_app;
-- Deny dangerous permissions
DENY CREATE TABLE TO cesivi_app;
DENY DROP TO cesivi_app;
DENY ALTER TO cesivi_app;
4.3: Database Encryption¶
Recommendation: Enable encryption at rest and in transit.
SQL Server TDE (Transparent Data Encryption):
-- Enable TDE
USE master;
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'STRONG_PASSWORD';
CREATE CERTIFICATE TDECert WITH SUBJECT = 'TDE Certificate';
USE CesiviDB;
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE TDECert;
ALTER DATABASE CesiviDB SET ENCRYPTION ON;
Connection Encryption:
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=CesiviDB;Encrypt=true;TrustServerCertificate=false;"
}
}
Network Security¶
5.1: Firewall Rules¶
Principle: Deny all traffic by default, allow only required traffic.
Inbound Rules:
# Allow HTTPS (443)
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Allow HTTP (80) for redirect to HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# Allow database (only from application server)
iptables -A INPUT -p tcp -s 10.0.1.5 --dport 5432 -j ACCEPT
# Allow SSH (admin only, non-standard port)
iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 2222 -j ACCEPT
# Deny all other traffic
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
Windows Firewall:
# Allow HTTPS
New-NetFirewallRule -DisplayName "Cesivi HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
# Allow HTTP for redirect
New-NetFirewallRule -DisplayName "Cesivi HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
# Block all other inbound by default
Set-NetFirewallProfile -DefaultInboundAction Block
5.2: IP Whitelisting¶
Recommendation: Restrict administrative endpoints to known IP ranges.
Configuration:
{
"Cesivi": {
"Security": {
"IpWhitelist": {
"Enabled": true,
"AdminEndpoints": [
"/_diagnostics/*",
"/_health/*",
"/admin/*"
],
"AllowedIpRanges": [
"10.0.0.0/8", // Internal network
"203.0.113.0/24" // Admin VPN
]
}
}
}
}
Middleware Implementation:
app.Use(async (context, next) =>
{
var path = context.Request.Path.Value;
var isAdminEndpoint = adminEndpoints.Any(pattern => path.StartsWith(pattern));
if (isAdminEndpoint)
{
var remoteIp = context.Connection.RemoteIpAddress;
if (!IsIpAllowed(remoteIp, allowedRanges))
{
context.Response.StatusCode = 403;
await context.Response.WriteAsync("Access denied");
return;
}
}
await next();
});
5.3: Reverse Proxy Configuration¶
Recommendation: Use reverse proxy (nginx, IIS ARR) for additional security layer.
Nginx Configuration:
server {
listen 443 ssl http2;
server_name cesivi.example.com;
# SSL configuration
ssl_certificate /etc/ssl/certs/cesivi.crt;
ssl_certificate_key /etc/ssl/private/cesivi.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/m;
limit_req zone=api burst=20 nodelay;
# Proxy to application
location / {
proxy_pass http://localhost:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Block malicious requests
location ~* /(wp-admin|phpmyadmin|admin\.php) {
return 404;
}
}
Security Headers¶
6.1: HTTP Strict Transport Security (HSTS)¶
Purpose: Force browsers to use HTTPS for all requests.
Configuration:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload");
await next();
});
6.2: Content Security Policy (CSP)¶
Purpose: Prevent XSS attacks by controlling resource loading.
Configuration:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Content-Security-Policy",
"default-src 'self'; " +
"script-src 'self' 'unsafe-inline'; " +
"style-src 'self' 'unsafe-inline'; " +
"img-src 'self' data: https:; " +
"font-src 'self' data:; " +
"connect-src 'self'; " +
"frame-ancestors 'none';");
await next();
});
6.3: X-Frame-Options¶
Purpose: Prevent clickjacking attacks.
Configuration:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
await next();
});
6.4: X-Content-Type-Options¶
Purpose: Prevent MIME-type sniffing.
Configuration:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
await next();
});
6.5: X-XSS-Protection¶
Purpose: Enable browser XSS filters (legacy, CSP preferred).
Configuration:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-XSS-Protection", "1; mode=block");
await next();
});
Secret Management¶
7.1: Never Commit Secrets to Git¶
Common Mistakes: - Hardcoded passwords in code - Connection strings in appsettings.json - API keys in configuration files - Private keys in repository
Prevention:
# Add to .gitignore
appsettings.Production.json
appsettings.*.json
*.key
*.pfx
secrets/
7.2: Use Secret Management Tools¶
Options: 1. Azure Key Vault (Azure cloud) 2. AWS Secrets Manager (AWS cloud) 3. HashiCorp Vault (multi-cloud, on-prem) 4. ASP.NET Core Secret Manager (development only)
Development (Secret Manager):
# Initialize secrets
dotnet user-secrets init --project Cesivi.Server
# Set secret
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=CesiviDB;User=sa;Password=DevPassword123"
# Secrets stored in user profile, not in repository
7.3: Rotate Secrets Regularly¶
Rotation Schedule: - Database passwords: Every 90 days - API keys: Every 90 days - SSL certificates: Every 365 days (automate with Let's Encrypt) - Service account passwords: Every 180 days
Logging and Auditing¶
8.1: Security Event Logging¶
Events to Log: - Failed login attempts (with IP, username, timestamp) - Successful logins (with IP, username, timestamp) - Permission changes (who changed, what changed, when) - API key usage (key ID, endpoint, timestamp) - Administrative actions (user creation, deletion, config changes) - Database schema changes - Suspicious activity (SQL injection attempts, XSS attempts)
Example:
_logger.LogWarning("Failed login attempt: User={Username}, IP={IpAddress}, Timestamp={Timestamp}",
username, remoteIp, DateTime.UtcNow);
_logger.LogInformation("Successful login: User={Username}, IP={IpAddress}, Timestamp={Timestamp}",
username, remoteIp, DateTime.UtcNow);
_logger.LogWarning("Suspicious activity detected: Type={AttackType}, IP={IpAddress}, Payload={Payload}",
"SQLInjection", remoteIp, sanitizedPayload);
8.2: Log Retention¶
Recommendation: - Security logs: 1 year minimum - Audit logs: 7 years (compliance requirements) - Application logs: 90 days - Debug logs: 7 days
Storage: - Use centralized logging (ELK, Splunk, Azure Monitor) - Encrypt logs at rest - Restrict access to logs (need-to-know basis)
8.3: Log Sanitization¶
Requirement: Never log sensitive data (passwords, credit cards, PII).
Example:
// ❌ BAD: Logs password
_logger.LogInformation("User login: {Username}, Password: {Password}", username, password);
// ✅ GOOD: Sanitized
_logger.LogInformation("User login: {Username}", username);
// ✅ GOOD: Redacted sensitive fields
var sanitized = new
{
request.Username,
Password = "***REDACTED***",
request.IpAddress
};
_logger.LogInformation("Login request: {Request}", sanitized);
Security Monitoring¶
9.1: Intrusion Detection¶
Recommendation: Deploy intrusion detection system (IDS) to monitor network traffic.
Tools: - Snort (open-source) - Suricata (open-source) - Azure Sentinel (cloud) - AWS GuardDuty (cloud)
9.2: Security Metrics¶
Monitor: - Failed login attempts (alert if > 10/minute from single IP) - API error rate (alert if > 5%) - Unusual traffic patterns (alert if traffic spikes > 200%) - Certificate expiration (alert 30 days before expiration) - Database connection failures (alert if > 5/minute)
Alerting Example:
# Prometheus alerting rule
groups:
- name: security
rules:
- alert: HighFailedLoginRate
expr: rate(failed_logins_total[5m]) > 10
for: 5m
annotations:
summary: "High failed login rate detected"
description: "{{ $value }} failed logins/second from IP {{ $labels.ip }}"
9.3: Vulnerability Scanning¶
Recommendation: Run vulnerability scans monthly (or after each deployment).
Tools: - OWASP ZAP (web app scanner) - Nessus (network scanner) - Qualys (cloud scanner) - Snyk (dependency scanner)
CI/CD Integration:
# GitHub Actions example
- name: Security Scan
uses: zaproxy/action-full-scan@v0.4.0
with:
target: 'https://cesivi.example.com'
Hardening Checklist¶
Authentication & Authorization¶
- [ ] Basic authentication disabled in production
- [ ] Strong password policy enforced (12+ chars, complexity)
- [ ] Multi-factor authentication enabled for admins
- [ ] Account lockout policy configured (5 failed attempts)
- [ ] API keys rotated every 90 days
- [ ] Session timeout configured (30 minutes idle)
Transport Security¶
- [ ] HTTPS enforced (no HTTP traffic)
- [ ] TLS 1.2+ only (TLS 1.0/1.1 disabled)
- [ ] SSL certificate from trusted CA
- [ ] SSL certificate auto-renewal configured
- [ ] Strong cipher suites configured
API Security¶
- [ ] Rate limiting enabled (100 req/min default)
- [ ] Input validation on all endpoints
- [ ] Output encoding to prevent XSS
- [ ] CORS restricted to trusted domains only
- [ ] API versioning implemented
Database Security¶
- [ ] Connection strings encrypted (Key Vault, etc.)
- [ ] Database user has minimal permissions (no sa/db_owner)
- [ ] Separate migration user (not used by app)
- [ ] Database encryption enabled (TDE)
- [ ] Connection encryption enabled (Encrypt=true)
Network Security¶
- [ ] Firewall rules configured (deny by default)
- [ ] IP whitelisting for admin endpoints
- [ ] Reverse proxy configured (nginx/IIS ARR)
- [ ] DDoS protection enabled (Cloudflare, Azure DDoS)
Security Headers¶
- [ ] HSTS enabled (max-age=31536000)
- [ ] Content-Security-Policy configured
- [ ] X-Frame-Options set to SAMEORIGIN
- [ ] X-Content-Type-Options set to nosniff
- [ ] X-XSS-Protection enabled
Secret Management¶
- [ ] No secrets committed to Git
- [ ] Secrets stored in Key Vault/Secrets Manager
- [ ] Secret rotation schedule defined
- [ ] Secrets not logged or exposed
Logging & Monitoring¶
- [ ] Security events logged (logins, permission changes)
- [ ] Audit logs retained (1+ year)
- [ ] Sensitive data not logged (passwords, PII)
- [ ] Centralized logging configured (ELK, Splunk)
- [ ] Alerting configured for security events
Operational Security¶
- [ ] Intrusion detection system deployed
- [ ] Vulnerability scanning monthly
- [ ] Penetration testing annually
- [ ] Security incident response plan documented
- [ ] Security training for development team
Last Updated: 2026-01-18 Version: 1.0 For Support: See README.md