Tutorial 5.1: Database Security
Practice for 2026-05-11-database-security.
Section A — Discretionary Access Control
Universe of discourse: Rob’s Convenience Store has a database system to manage business activities. System admin Paris has created accounts for herself and four staff members, with these requirements:
- Paris (sysadmin) — full access to the whole database, and can grant permissions to others.
- Rachel (HR manager) — full access to
Employee; can view (but not modify)Restock. - Aaron (supply chain lead) — full access to
Item,Restock, andSale. - Chris (customer service) — full access to
Customer; read access toSale. - Emily (security manager, investigates missing stock) — read access to
SaleandRestock; can view only thefName/lNameattributes of bothEmployeeandCustomer.
Schema: Employee [id, fName, lName, role, email], Restock [employee, item, time, quantity] (FKs to Employee.id, Item.id), Item [id, name, description, price], Sale [customer, item, time, quantity] (FKs to Customer.id, Item.id), Customer [id, fName, lName, dob].
Question A.1 — Identify and fix incorrect access
The permission table below (as currently configured) contains several errors. Fix it, using the UoD above (- = not directly granted).
| Paris | Rachel | Aaron | Chris | Emily | |
|---|---|---|---|---|---|
| Employee | ALL | ALL | UPDATE | — | SELECT |
| Restock | ALL | ALL | ALL | — | SELECT |
| Item | ALL | — | ALL | — | — |
| Sale | — | — | ALL | UPDATE, GRANT | — |
| Customer | SELECT, UPDATE | — | SELECT | ALL | — |
| Customer.fName/lName | — | — | — | — | SELECT |
| Employee.fName/lName | — | — | — | — | — |
Corrected table:
| Paris | Rachel | Aaron | Chris | Emily | |
|---|---|---|---|---|---|
| Employee | ALL | ALL | — | — | — |
| Restock | ALL | SELECT | ALL | — | SELECT |
| Item | ALL | — | ALL | — | — |
| Sale | ALL | — | ALL | SELECT | SELECT |
| Customer | ALL | — | — | ALL | — |
| Customer.fName/lName | — | — | — | — | SELECT |
| Employee.fName/lName | — | — | — | — | SELECT |
Errors fixed (bold): Rachel had ALL on Restock (should only be SELECT — she’s not allowed to make changes there). Aaron had UPDATE on Employee and SELECT on Customer (should have none — he’s supply chain, not HR/customer-facing). Chris had UPDATE, GRANT on Sale (should be SELECT only, and definitely no grant option — he only needs read access, and never had a stated need to further delegate access). Emily had no access to Sale at all (should have SELECT, per her investigative role) and no access to Employee.fName/lName (should have SELECT, matching her Customer.fName/lName access) — and Paris, as sysadmin, needed ALL on Sale and Customer (both were missing/blank), consistent with her full-database access.
Question A.2 — SQL grant/revoke queries
Write the SQL queries to fix the incorrectly-configured accounts from A.1.
-- Rachel
REVOKE ALL PRIVILEGES ON `Rob's Convenience Store`.`Restock` FROM 'Rachel';
GRANT SELECT ON `Rob's Convenience Store`.`Restock` TO 'Rachel';
-- Aaron
REVOKE ALL PRIVILEGES ON `Rob's Convenience Store`.`Employee` FROM 'Aaron';
REVOKE ALL PRIVILEGES ON `Rob's Convenience Store`.`Customer` FROM 'Aaron';
-- Chris
REVOKE ALL PRIVILEGES ON `Rob's Convenience Store`.`Sale` FROM 'Chris';
REVOKE GRANT OPTION ON `Rob's Convenience Store`.`Sale` FROM 'Chris';
GRANT SELECT ON `Rob's Convenience Store`.`Sale` TO 'Chris';
-- Emily
REVOKE ALL PRIVILEGES ON `Rob's Convenience Store`.`Employee` FROM 'Emily';
GRANT SELECT ON `Rob's Convenience Store`.`Sale` TO 'Emily';
GRANT SELECT (`fName`, `lName`) ON `Rob's Convenience Store`.`Employee` TO 'Emily';Section B — Mandatory Access Control
Universe of discourse: ASIO tracks undercover agents’ identities in a MAC database, to keep classified information from riskier assignments protected.
Schema: Spy [ID, fName, lName, dob, email], CodeName [spyID, name, dateEffective, dateExpired, operation] (FK spyID → Spy.id, operation → Operation.name), Operation [name, description, budget].
DBMS accounts (low to high): Cody = U, Jane = C, Tanya = S, Jack = TS.
Sample data, with each attribute’s classification noted, and the overall Tuple Classification (TC = the highest classification of any attribute present):
Spy — id(U), fName(U), lName(TS), dob(C), email(S)
id fName lName dob email TC
1 Daniel Teal 18/06/1995 bmw@hotmail.com TS
2 May Lee 03/02/1998 may@stevefam.com TS
3 John Smith 12/05/1990 john@smith.com TS
4 April Fuller 25/06/1980 ilikefood@korea.com TS
CodeName — spyID always (C); name/operation classification varies per row;
dateEffective/dateExpired always (U)
spyID name dateEffective dateExpired operation TC
1 Handbrake (C) 01/02/2019 03/06/2020 Le-Ferrari (S) S
2 BunnyBunny (S) 12/03/2019 12/04/2019 Hotpot (C) S
4 BubbleTea (C) 19/04/2019 24/04/2019 Hotpot (C) C
2 BBQ (TS) 27/09/2019 04/10/2019 KimChi (TS) TS
Operation
name description budget TC
Hotpot (S) "Infiltrate McDonalds..." (S) 1000000 (S) S
Le-Ferrari (C) "Identify the Ferrari-stealing syndicate leader" (U) 10000000 (U) C
KimChi (S) "Someone stole ASIO's KimChi supply..." (S) 500000000 (S) S
Question B.1 — Identifying security denials
For each query, determine whether it succeeds (S) or fails (F), and why.
| User | Query | Result | Reason |
|---|---|---|---|
| Cody | SELECT id FROM Spy; |
S | Cody’s clearance (U) ≥ the classification of every id value (U). |
| Cody | SELECT name FROM Operation WHERE budget > 10000000 |
F | The one matching tuple (KimChi) has TC = S, above Cody’s U clearance — the query returns nothing even though the WHERE condition is logically true for it. |
| Cody | INSERT INTO CodeName (spyID, name, dateEffective, dateExpired, operation) VALUES (2, "BBQ", "16/05/2019", "26/05/2019", "Hotpot") |
S | Looks like it should violate the key constraint (another spyID=2, name="BBQ" combination already exists at TS) — but since the two “identical” tuples have different security classifications, the DBMS applies polyinstantiation to let them coexist. |
| Jack | INSERT INTO Operation (name, description, budget) VALUES ("Ace", "Find an unidentified hacker...", 350000) |
F | Operation’s highest classification is S. Jack’s clearance is TS — higher than S — so the star property (no write down) blocks this insert, to prevent Jack from writing lower-classified information into a table that could then leak higher-clearance context. |
| Jane | UPDATE CodeName SET name = "Iced Coffee" WHERE spyID = 4 |
S | Jane’s clearance (C) ≥ the classification of spyID (C, so she can read/select the row) and ≤ the classification of name for that row (C, so she can write it) — both read and write permission hold, so the update succeeds. |
Question B.2 — Returning data in a MAC database
What data is returned for each query?
Jane: SELECT spyID, name, operation FROM CodeName →
| spyID | name | operation |
|---|---|---|
| 1 | Handbrake | NULL |
| 2 | NULL | Hotpot |
| 4 | BubbleTea | Hotpot |
(Row spyID=2, name="BBQ" is entirely TS-classified — above Jane’s C clearance — so it doesn’t appear at all. Within the visible rows, any individual cell above Jane’s clearance is masked to NULL rather than hiding the whole row — e.g. row 1’s Handbrake is C, visible, but row 2’s BunnyBunny is S, masked.)
Jane: SELECT name, dob FROM CodeName, Spy WHERE id = spyID AND dateEffective < "01/06/2020" →
| name | dob |
|---|---|
| Handbrake | 18/06/1995 |
| NULL | 03/02/1998 |
| BubbleTea | 25/06/1980 |
Cody: SELECT name, budget FROM Operation WHERE description LIKE "%a%" →
| name | budget |
|---|---|
| NULL | 10,000,000 |
(Only Le-Ferrari — TC=C — is within reach of Cody’s U clearance enough to appear at all, and even then its name attribute specifically, being C-classified, is masked to NULL for a U user; budget for that row is U-classified so it’s shown.)
Jane: SELECT spyID, Operation.name, Operation.budget FROM Operation, CodeName WHERE Operation.name = CodeName.operation → empty set. Every possible join row pairs a CodeName.operation value with an Operation.name value where at least one side is classified S or TS — above Jane’s C clearance — so no valid (joinable, visible-to- Jane) pairing exists, and the join returns nothing.
Bonus — Completing a database audit
Universe of discourse: SummerStyles (a clothing retailer) audits its DBMS log monthly for unauthorised changes or potential privacy violations.
Using the log below, flag any potentially suspicious records (there’s no exact formula — use judgement).
event_time user_host thread_id argument
17-05-2020 8:27:18am SystemAdmin@localhost 2097 SHOW COLUMNS FROM SummerStyles.customer
17-05-2020 8:28:00am SystemAdmin@localhost 2097 SHOW INDEXES FROM SummerStyles.customer
17-05-2020 8:30:07am HRManager@localhost 2103 UPDATE SummerStyles.staff SET Wage = Wage * 1.1
17-05-2020 8:31:07am CustomerService@localhost 2129 SELECT * FROM SummerStyles.customer WHERE fName="Elaine" AND lName="Wang"
17-05-2020 8:33:30am SystemAdmin@localhost 2129 SELECT TABLE_NAME FROM information_schema.VIEWS WHERE TABLE_SCHEMA='SummerStyles' AND TABLE_NAME='Customer'
17-05-2020 8:35:05am CustomerService@localhost 2129 SELECT fName, lName, max(wage) FROM SummerStyles.staff
17-05-2020 8:35:43am StockManager@localhost 2129 DELETE FROM SummerStyles.deliveries WHERE id = 204472
17-05-2020 8:38:32am StockManager@localhost 2128 UPDATE SummerStyles.currentStock SET quantity = quantity + 8 WHERE stockID = 1263
17-05-2020 8:41:14am SystemAdmin@localhost 2129 ALTER TABLE SummerStyles.staff ADD email varchar(255);
17-05-2020 8:45:41am HRManager@localhost 2129 INSERT INTO SummerStyles.staff (id, fName, lName) VALUES (142, "Leya", "Rebecca")
17-05-2020 8:57:37am HRManager@localhost 2131 UPDATE SummerStyles.stock SET price = 11.00 WHERE name LIKE "%Calvin Klein%"
Two entries stand out as worth flagging:
8:35:05am — CustomerService:SELECT fName, lName, max(wage) FROM SummerStyles.staff. A customer service rep querying staff wage data is well outside their normal remit — salary information is HR’s domain (per the DAC exercise above, this kind of cross-role access is exactly what discretionary permissions should normally prevent) — a potential unauthorised-access/privacy concern worth following up.8:57:37am — HRManager:UPDATE SummerStyles.stock SET price = 11.00 WHERE name LIKE "%Calvin Klein%". An HR manager modifying product pricing is outside HR’s normal duties (that’sStockManager’s job, as seen elsewhere in the log) — an unauthorised-modification concern, and potentially indicative of privilege misuse.