Labs · Cyber Security
Lab: Create a Practice Database and a Least-Privilege MySQL User That Can Only Read (SELECT)
Course: Cyber Security · Chapter 10: MySQL Part 1: Install, Create, Insert and SELECT
Chapter 10 installs MySQL and runs CREATE, INSERT and SELECT; this lab adds a least-privilege user.
Chala mitrano! A reports page only needs to read data. If its database user can also delete tables, one small bug or stolen password can wipe everything. Least privilege means: give only what is needed. Today we make a user that can only SELECT, and we prove it. Saral aahe!
चला मित्रांनो! Reports page ला फक्त data वाचायचा असतो. त्याचा database user tables delete पण करू शकत असेल, तर एक छोटा bug किंवा चोरलेला password सगळं पुसू शकतो. Least privilege म्हणजे: फक्त गरजेपुरतं द्यायचं. आज आपण असा user बनवणार जो फक्त SELECT करू शकतो, आणि ते prove करणार. सोपं आहे!
चलो दोस्तों! Reports page को सिर्फ data पढ़ना होता है। अगर उसका database user tables delete भी कर सकता है, तो एक छोटा bug या चोरी हुआ password सब मिटा सकता है। Least privilege का मतलब: सिर्फ ज़रूरत जितना दो। आज हम ऐसा user बनाएँगे जो सिर्फ SELECT कर सके, और उसे prove करेंगे। आसान है!
Suppose we are…
Suppose we are a backend trainee at Meesho. The analytics team wants to connect a dashboard to our product database. Our lead says: "Give them a user that can read the shop tables and nothing else. No INSERT, no DELETE, no DROP, and no access to other databases." This is the principle of least privilege (every user gets the minimum rights it needs).
Goal of this lab
By the end you will have:
- MariaDB (a free database that works like MySQL) installed and secured.
- A practice database
shopwith aproductstable and 5 rows. - A user
reportthat can onlySELECTfromshop, with proof that other actions are denied.
What you need (all free)
- Your free-tier EC2 Amazon Linux 2023 server (no new port needed: we connect locally).
- 35–40 minutes.
Safety and ethics
Never open the database port (3306) in the security group for practice. Use example passwords only in the lab and real strong passwords in real systems.
Part 1: install and secure
-
SSH to the server and install MariaDB:
sudo dnf install -y mariadb105-server sudo systemctl enable --now mariadb -
Run the security script:
sudo mariadb-secure-installationPress Enter for the current root password (empty). Answer n to "Switch to unix_socket authentication" (it is already on), Y to remove anonymous users, Y to disallow root login remotely, Y to remove the test database and Y to reload privileges.
Part 2: practice database
-
Open the database shell as root and create the practice data:
sudo mariadbCREATE DATABASE shop; USE shop; CREATE TABLE products (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), price INT); INSERT INTO products (name, price) VALUES ('Kurti', 499), ('Saree', 1299), ('Bedsheet', 699), ('Earrings', 199), ('Backpack', 899); SELECT * FROM products;What you should see: a table with 5 rows,
5 rows in set.
Part 3: the least-privilege user
-
Still in the root shell, create the user and give only SELECT on
shop:CREATE USER 'report'@'localhost' IDENTIFIED BY 'Lab-Only-Pass-2026'; GRANT SELECT ON shop.* TO 'report'@'localhost'; SHOW GRANTS FOR 'report'@'localhost'; EXIT;What you should see:
GRANT USAGE ON *.* ...(only means "can log in") andGRANT SELECT ON shop.* TO report@localhost. -
Log in as the new user:
mariadb -u report -p shopType
Lab-Only-Pass-2026when asked. -
Try reading, then try the forbidden actions:
SELECT name, price FROM products WHERE price > 500; INSERT INTO products (name, price) VALUES ('Hack', 1); DROP TABLE products; SHOW DATABASES;What you should see: SELECT returns Saree, Bedsheet and Backpack. INSERT fails with
ERROR 1142 (42000): INSERT command denied to user 'report'@'localhost'. DROP fails withDROP command denied. SHOW DATABASES lists onlyinformation_schemaandshop. -
Type
EXIT;.
Ravindra Bagale's Tip
Many projects connect the website to MySQL as root because "it works". Then one SQL injection bug becomes a full database disaster. One user per app, only the rights it needs, only from localhost or the app server. He interview madhe pan vicharatat!
Ravindra Bagale's Tip – मराठी
बरेच projects website ला MySQL शी root म्हणून connect करतात कारण "चालतंय". मग एक SQL injection bug पूर्ण database disaster बनतो. प्रत्येक app साठी एक user, फक्त गरजेचे rights, फक्त localhost किंवा app server वरून. हे interview मध्ये पण विचारतात!
Ravindra Bagale's Tip – हिंदी
बहुत से projects website को MySQL से root बनकर connect करते हैं क्योंकि "चल रहा है"। फिर एक SQL injection bug पूरी database की तबाही बन जाता है। हर app के लिए एक user, सिर्फ ज़रूरी rights, सिर्फ localhost या app server से। ये interview में भी पूछते हैं!
Common mistakes
| Mistake | What happens | Fix |
|---|---|---|
GRANT ALL PRIVILEGES ON *.* "to save time" |
The user can change every database | Grant only what is needed, on one database |
Creating 'report'@'%' |
The user may log in from any host | Use 'localhost' or the app server's IP |
| Opening port 3306 to Anywhere | Bots try passwords on your database | Keep 3306 closed; connect locally or from the app's security group |
| Forgetting to remove the test database | Extra objects anyone can use | Answer Y in mariadb-secure-installation |
Typing mysql -u report with no -p |
Access denied (using password: NO) |
Add -p and enter the password |
Self-check checklist
0 of 5 done
Try-at-home challenge
The dashboard team now also needs to add rows to a new table feedback, but must still not change products. Write the SQL to create the table and give exactly that extra right.
Check your answer
CREATE TABLE shop.feedback (id INT PRIMARY KEY AUTO_INCREMENT, msg VARCHAR(200));
GRANT INSERT ON shop.feedback TO 'report'@'localhost';
SHOW GRANTS FOR 'report'@'localhost';
Run it as root. The grant is on one table only, so INSERT INTO products is still denied.
Clean up to avoid charges
Keep the server for Lab 11 (backup and restore) if you continue today. Otherwise: EC2 → Instances → Instance state → Terminate (delete) instance.
Samjla ka? One user per app, only the rights it needs. Aata pudhe jaauya: Chapter 11 backs up this database and removes users we do not need.