Free tutorials & notes in Hindi & English · Clean code examples · Mobile friendly learning
MySQL + SQL · Lesson 109

Database Security Basics

Start with Assets, Threats and Trust Boundaries

Database security protects confidentiality, integrity and availability. Begin with an inventory instead of a generic command list:

AssetThreat exampleRequired evidence
Student/parent dataUnauthorized disclosureAccess matrix and audit trail
Fees/marksUnauthorized modificationAuthorization and change controls
Database serviceRansomware or overloadMonitoring and tested recovery
Credentials/keysTheft from code or backupVault, rotation and access logs

Map trust boundaries: browser → application → database, administrator workstation → management network → database, and database → backup storage. Record data classification, owner, lawful purpose, retention, RPO/RTO and incident contact.

Defense in depth: network isolation, strong identity, least privilege, safe application code, encryption, monitoring and recoverable backups must work together. No single setting makes a database secure.

Minimize Network Exposure and Verify TLS

  • Keep MySQL on a private network; do not expose port 3306 directly to the public Internet.
  • Allow only application/administration source addresses through firewall or security groups.
  • Use a bastion, VPN or managed private endpoint for administration.
  • Separate production, testing and development networks and credentials.
# Server policy (configuration change procedure required)
[mysqld]
bind_address=10.20.30.10
require_secure_transport=ON

# Client identity verification
mysql --login-path=school_app \
  --ssl-mode=VERIFY_IDENTITY \
  --ssl-ca=/approved/ca.pem

PREFERRED encryption can fall back depending on conditions. REQUIRED prevents unencrypted fallback, while VERIFY_CA verifies the CA and VERIFY_IDENTITY also checks the hostname. Deploy trusted certificates and test renewal before enforcing.

Account clauses such as REQUIRE SSL or managed REQUIRE X509 add per-account requirements. They complement, not replace, network controls.

Use Dedicated Identities and Protected Secrets

CREATE USER 'school_runtime'@'10.20.30.%'
  IDENTIFIED BY RANDOM PASSWORD
  REQUIRE SSL
  COMMENT 'Production school web runtime';

GRANT SELECT,INSERT,UPDATE
ON school_app.attendance
TO 'school_runtime'@'10.20.30.%';

SHOW GRANTS FOR 'school_runtime'@'10.20.30.%';

Applications must not use MySQL root, a developer's account or the migration identity. Keep secrets in a vault/environment injection mechanism with strict file/process permissions—not in Git, JavaScript, public folders, screenshots or tickets.

  • Narrow the user@host pattern.
  • Use roles and the smallest stable object scope.
  • Avoid FILE, GRANT OPTION and global administrative privileges.
  • Rotate secrets and test dual-secret/connection-pool rollout.
  • Lock leavers/stale services, then safely remove after dependency review.
  • Protect and monitor break-glass administration.

Review users and privileges for the full account lifecycle.

Prevent Injection and Enforce Application Authorization

Validate business input and bind every data value. Parameter binding does not authorize the current user and cannot replace identifiers; use allowlists for columns, directions and operations.

$pdo = new PDO($dsn,$dbUser,$dbPassword,[
 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
 PDO::ATTR_EMULATE_PREPARES => false,
]);

$stmt=$pdo->prepare(
 'SELECT student_id,student_name
  FROM students WHERE class_id=:class_id AND student_id=:id'
);
$stmt->execute([
 ':class_id'=>$authorizedClassId,
 ':id'=>$validatedStudentId,
]);

The query includes the authorized class boundary; checking only student_id could expose another class or tenant. Use server-side session identity, deny by default and enforce authorization for every object/action.

  • Do not display SQL errors, credentials or stack traces to users.
  • Use transactions for multi-step integrity rules.
  • Set query/time/row limits where appropriate.
  • Patch connectors and frameworks; disable unsafe debug modes.
  • Test injection, broken access control, mass assignment and race conditions.

See prepared statements and SQL injection prevention.

Protect Sensitive Data Through Its Lifecycle

Collect only necessary data, classify it and define retention. Encryption does not fix excessive collection or overbroad access.

  • Use verified TLS in transit and platform-supported encryption at rest.
  • Keep encryption keys outside the database and test authorized key recovery.
  • Encrypt backups/exports, control download links and expire them.
  • Mask or synthesize production data before development/testing.
  • Redact secrets and sensitive fields from logs and traces.
  • Securely delete expired data and every retained copy according to policy.

For web-user passwords, use the language/platform's adaptive password API. In PHP:

$hash=password_hash($password,PASSWORD_ARGON2ID);
if(password_verify($candidate,$hash)) {
  // Continue with session regeneration and authorization
}

If Argon2id is unavailable, use PASSWORD_DEFAULT and maintain an upgrade/rehash plan. General fast hashes such as plain SHA-256 are not appropriate password-storage functions, and encryption is reversible.

Harden, Patch and Control the MySQL Server

[mysqld]
require_secure_transport=ON
local_infile=OFF
secure_file_priv=/var/lib/mysql-files

Apply configuration through the hosting/platform change process; verify supported syntax, ownership and restart behavior first. A secure baseline includes:

  1. supported MySQL/OS versions and prompt security patches;
  2. non-root OS service identity and restrictive filesystem permissions;
  3. no anonymous/test accounts or empty administrative passwords;
  4. grant tables enabled—never leave skip-grant-tables active;
  5. LOCAL/file import disabled unless a controlled workflow needs it;
  6. plugins/components limited to approved inventory;
  7. separate production instance and nonproduction data;
  8. configuration-as-code, peer review and drift detection.

secure_file_priv set to a directory restricts server file operations; NULL disables them. Do not grant global FILE to the web application. Benchmark changes before production and keep a rollback.

Monitor Access, Changes and Failure Signals

Collect enough evidence to detect abuse without logging secrets. Centralize and protect:

  • authentication successes/failures and temporary locks;
  • account, role, GRANT/REVOKE and configuration changes;
  • unexpected privilege escalation or new definers;
  • backup failures, restore-test results and binary-log continuity;
  • abnormal queries, error rate, connections, latency and data export volume;
  • host, firewall, vault and cloud control-plane events.

Use available audit facilities appropriate to the deployed MySQL edition/service. The general query log can expose sensitive values and add overhead, so it is not a default continuous security audit strategy. Restrict log access, synchronize time, define retention and alert on actionable patterns.

SHOW GRANTS FOR 'school_runtime'@'10.20.30.%';
SELECT USER(),CURRENT_USER(),CURRENT_ROLE();
SHOW VARIABLES LIKE 'require_secure_transport';
SHOW VARIABLES LIKE 'local_infile';
SHOW VARIABLES LIKE 'secure_file_priv';

Review evidence regularly and compare it with the approved baseline.

Make Recovery and Incident Response Part of Security

  1. Prepare: owners, contacts, forensics, legal/privacy steps and clean recovery runbook.
  2. Detect: validate alert scope, affected identities, data and time window.
  3. Contain: preserve evidence; lock compromised account or isolate network safely.
  4. Eradicate: patch root cause, rotate secrets/keys and remove persistence.
  5. Recover: restore known-good data, apply reviewed logs and validate service.
  6. Learn: document timeline, impact, controls and test improvements.

Maintain encrypted, access-controlled, immutable/offsite backups and prove them through isolated restores within RPO/RTO. A replica is not a backup; destructive changes can replicate.

Final production gate: 0 public database exposure, 0 runtime admin accounts, verified TLS, least privilege tested both ways, secrets outside code, supported patches, actionable monitoring and a timed restore drill.

Use the complete backup and restore guide.

Official References

Network encryption, access control and server security guidance were verified against the official MySQL 8.4 manual. Features vary by edition and managed service; validate the deployed environment.

Frequently Asked Questions

What is the first step in securing a MySQL database?
Inventory data, users, applications, network paths and recovery dependencies, then define likely threats and impact. Security controls should follow the actual threat model rather than a copied checklist alone.
Is REQUIRE SSL enough to make a MySQL connection secure?
It requires encryption for that account, but the client should also verify the certificate authority and server hostname, such as with VERIFY_IDENTITY, to resist man-in-the-middle attacks.
Should application users have ALL PRIVILEGES?
No. Give each workload a dedicated host-scoped account or role with only the required schema operations. Keep migrations, backups and administration separate from runtime access.
How should web application passwords be stored in MySQL?
Store password hashes created by a dedicated adaptive password-hashing function such as Argon2id or the platform recommended password API, with unique salts handled by that API. Never store plaintext or reversible passwords.
Do backups need the same security as the live database?
Yes. Backups often contain the complete sensitive dataset. Encrypt them, restrict identities, keep an immutable copy, manage keys separately, define retention and prove recoverability with isolated restore tests.
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

💻 Live Code Editor

This page's programs are ready here — run them, edit them, and learn. No installation needed.
Powered by OneCompiler. The code loads into the editor automatically — press Run to see the output. If the editor does not open, open it in a new tab.