Incident briefing
Open the SQL client Everything below is done there.
The situation
On Monday morning a file was posted to a public forum. It holds several hundred thousand records: names, addresses, IBANs and meter readings for Meridian Energy customers.
Our security team has compared it against our own customer table. It matches, row for row. This did not come from a partner, a supplier or a scraper. Somebody inside Meridian took it out of the database.
You have been brought in to establish who, and to make it stick.
What is established
- The file came from our own customer table. Security matched it record for record.
- It contains bank details, so it is not one of the routine marketing extracts.
- Customers have come and gone since. Some signed up after that night; some exercised their right to erasure and are no longer in the table at all.
- Twelve database accounts had read access to that table at the time.
- Every statement run against the database is recorded in the audit log, with the account that ran it and how many rows it returned.
What is not known
- When the data was taken.
- Which of the twelve accounts was used.
- How many records were in the file. The audit trail does not record a row count for a bulk copy, and the customer table has changed since that night.
- Who was sitting behind that account.
What you have
A read-only copy of Meridian's systems. The customer table itself, the database audit log, session records, badge readings at the doors, leave records, helpdesk tickets and personnel notes.
Start by looking around:
SELECT table_name, column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'meridian'
ORDER BY table_name, ordinal_position;
What we need from you
| # | Finding | Points |
|---|---|---|
| 01 | When did the bulk export run? a timestamp, like 2025-11-30 23:05 | 100 |
| 02 | Which database account was used? an account name as it appears in the audit log | 200 |
| 03 | How many customer records were exposed? a plain number | 400 |
| 04 | Which helpdesk ticket explains how that account was compromised? a ticket reference, HD-#### | 450 |
| 05 | Who actually took the data out? an employee number, EMP-#### | 700 |
This list also lives in the database:
SELECT * FROM game.findings_list;
How to report a finding
Submit each finding as you establish it, using the same team name every time:
SELECT game.submit('Your team name', 1, 'your answer');
The first team to establish a finding earns a quarter extra. Stuck?
SELECT game.hint('Your team name', 4);
Two hints per finding, each costing a quarter of that finding's value. All the tables are open from the start; there is no fixed order.
One warning
Some of what you will find looks damning and proves nothing. A grievance is not a confession. Being in the building is not the same as being at the keyboard. And an account is not a person: somebody has to have been sitting behind it.
Before you name anyone, check whether they could actually have done it.
This briefing is also readable from your SQL client:
SELECT * FROM game.briefing ORDER BY ord;