✏️ Explanatory Question

GRANT/REVOKE and the principle of least privilege

👁 6 Views
📘 Detailed Answer
🟢 Easy
💡

Answer with Explanation

Section 23: Security, Roles & Privileges

132

GRANT/REVOKE and the principle of least privilege

Level: Hard — A core security responsibility; over-privileged accounts are one of the biggest real-world breach vectors.

Scenario: A security audit finds that your web application connects to MySQL using the root account. If the app is compromised via SQL injection, the attacker gets full control of every database. How do you design proper, minimal database access, and what does "least privilege" mean in practice?

The Principle of Least Privilege

Least privilege means every account gets only the permissions it actually needs to do its job — nothing more. A web app that only reads and writes application data should never have DROP, GRANT, or access to other databases.

Why using root for apps is dangerous: If the app account has full privileges, a single SQL injection or leaked credential lets an attacker read all data, drop tables, or create new admin users. Scoping the account limits the "blast radius" of any compromise.

Privilege Levels (from broad to narrow)

LevelScopeExample
GlobalAll databasesON *.*
DatabaseOne databaseON shop.*
TableOne tableON shop.orders
ColumnSpecific columnsSELECT (name, email)

The Fix — A Properly Scoped App User

-- Create a dedicated app user (not root!)
CREATE USER 'app_user'@'10.0.%' IDENTIFIED BY 'Str0ng!Passw0rd';
-- '10.0.%' restricts logins to your app subnet, not from anywhere

-- Grant ONLY the data operations the app needs, on ONLY its database
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.* TO 'app_user'@'10.0.%';

-- NOT granted: DROP, ALTER, CREATE, GRANT, or access to other schemas
-- Apply the changes
FLUSH PRIVILEGES;

Different Users for Different Jobs

-- Read-only user for analytics/reporting (cannot modify anything)
CREATE USER 'report_user'@'%' IDENTIFIED BY 'pass2';
GRANT SELECT ON shop.* TO 'report_user'@'%';

-- Migration/deploy user that CAN change schema (used only in deploys)
CREATE USER 'deploy_user'@'10.0.0.5' IDENTIFIED BY 'pass3';
GRANT ALL PRIVILEGES ON shop.* TO 'deploy_user'@'10.0.0.5';

-- Column-level: support staff can see names but NOT card numbers
CREATE USER 'support'@'%' IDENTIFIED BY 'pass4';
GRANT SELECT (id, name, email) ON shop.customers TO 'support'@'%';

Inspecting and Revoking Privileges

-- See what a user can do
SHOW GRANTS FOR 'app_user'@'10.0.%';

-- Revoke a privilege that was too broad
REVOKE DELETE ON shop.* FROM 'app_user'@'10.0.%';

-- Remove a user entirely
DROP USER 'old_user'@'%';

The user@host matters as much as the password: MySQL identifies accounts by both username and host. 'app'@'localhost' and 'app'@'%' are different accounts. Restricting the host (e.g., to your app server's IP/subnet) means a stolen password is useless from anywhere else.

Security Best Practices

  • Never use root for applications; create scoped users.
  • Grant the minimum privileges, on the narrowest scope.
  • Restrict accounts by host/IP, not '%', where possible.
  • Require SSL/TLS for sensitive accounts (REQUIRE SSL).
  • Rotate credentials and audit SHOW GRANTS regularly.

Interviewer follow-up: "You have 50 microservices each needing similar-but-slightly-different permissions — managing individual grants is a nightmare. What now?" → Use roles (MySQL 8.0). Define a role once (e.g., app_readwrite), grant privileges to the role, then assign the role to many users. Managing one role beats editing 50 users individually — which is exactly the next question.