Work / Case study
A live honeypot breach, from first probe to forensic comparison
I built a Windows 11 server with a MySQL database, wired up logging and detections while it was still clean, then weakened it and opened it to the internet. Real attackers did the rest. This is what they did and how I traced it.
- Environment
- Windows 11 VM and MySQL 8.0 in Azure
- Detection
- Microsoft Sentinel, Defender for Endpoint
- Exposure window
- Sept. 25 to 27, 2026
- Outcome
- Database ransomed twice, admin password guessed
what happened, in numbers
- online to first probe
- 7 min
- online to data wiped
- 16 min
- successful root logins
- 60
- failed RDP logons
- 2,563
The short version
- The database fell first, and fast. Seven minutes after the server came online, the first scanner tried MySQL. Nine minutes after that, an attacker logged in as root, copied every table, deleted them, and left a ransom note.
- A second crew ransomed what was left. About 100 minutes later a different group dropped every database, left its own bitcoin demand, and locked the root account out. It never read the data it claimed to have backed up.
- RDP took longer but still fell. After about 28 hours and thousands of guesses, one address logged in as the local administrator twice.
- Nothing ran on the host afterward. I found no interactive session, no new process, file, or registry activity under that account, and no persistence.
How I built it
The order matters. Everything defensive was in place before anything was exposed, so the breach would be recorded from the first packet.
- Build it locked down. A Windows 11 VM named
CORP-FIN-PAYROLwith all inbound traffic denied, onboarded to Defender for Endpoint. - Add something worth stealing. MySQL 8.0 with a dummy company database,
lnp_corp, holding credentials, customers, orders, and payments tables. I took a full backup withmysqldumpbefore going further. - Log everything. MySQL's general query log went to a Log Analytics workspace through a data collection rule, into a custom table. Device telemetry came from Defender for Endpoint.
- Write detections while it was quiet. Two Sentinel analytics rules: one for a successful VM logon from a public address, and one for a successful MySQL login.
- Capture a baseline. A Defender investigation package, taken at 04:49 UTC on Sept. 25, so I could compare the machine before and after.
- Weaken and expose it. A local administrator with a weak password, the Guest account enabled for Remote Desktop, a MySQL root account reachable from any host, the Windows Firewall off, and the network security group opened to the internet.
The VM logon rule is short. The MySQL rule needed more work, because the query log arrives as one raw text field that has to be parsed into a user, an address, and a result.
KQL: successful VM logon from the internet
DeviceLogonEvents
| where DeviceName == "corp-fin-payrol"
| where AccountName in~ ("administrator", "guest")
| where ActionType == "LogonSuccess"
| where RemoteIPType == "Public"
| project TimeGenerated, RemoteIP, AccountName, LogonTypeAttack one: copy, delete, ransom in 84 seconds
The server powered on at 18:59 UTC. At 19:06 an address began trying root, admin, and sa with no password. At 19:14:38 a different address, 45.8.17.7, logged in as root over TLS.
What followed was fully automated. For each database it listed the tables, read every row with the same queries mysqldump uses, created a table called RECOVER_YOUR_DATA_info with a note, and dropped the originals.
MySQL query log: 45.8.17.7, 19:14:38 to 19:14:55 UTC
SHOW DATABASES
SHOW TABLES FROM `lnp_corp`
SELECT /*!40001 SQL_NO_CACHE */ * FROM `credentials`
SELECT /*!40001 SQL_NO_CACHE */ * FROM `customers`
SELECT /*!40001 SQL_NO_CACHE */ * FROM `orders`
SELECT /*!40001 SQL_NO_CACHE */ * FROM `payments`
CREATE TABLE `lnp_corp`.`RECOVER_YOUR_DATA_info` (`READ_ME` text)
INSERT INTO `lnp_corp`.`RECOVER_YOUR_DATA_info` (`READ_ME`) VALUES ('Saved file name: lnp_corp.sql ...
DROP TABLE IF EXISTS `lnp_corp`.`payments`
DROP TABLE IF EXISTS `lnp_corp`.`credentials`
DROP TABLE IF EXISTS `lnp_corp`.`customers`
DROP TABLE IF EXISTS `lnp_corp`.`orders`The company database was gone 17 seconds after login. All three databases were gone in 84 seconds.
Measured from the exposure time I recorded, the first breach came 14.5 hours later. The VM was powered off for 11 of those hours, so it survived about three and a half hours of time online.
Attack two: a second crew ransoms the ransom
At 20:53 UTC a second actor arrived from 64.89.163.165, this time over plain TCP. It read the first attacker's note, then replaced it.
MySQL query log: 64.89.163.165, 20:53:24 to 20:53:48 UTC
SELECT * FROM `recover_your_data_info`
DROP DATABASE `lnp_corp`
DROP DATABASE `sakila`
DROP DATABASE `world`
CREATE DATABASE IF NOT EXISTS RECOVER_YOUR_DATA
INSERT INTO RECOVER_YOUR_DATA (text) VALUES ('All your data was backed up by us.
You must pay 0.0101 bitcoin to bc1q3t3r...8m2n8d or in 48 hours, your data
will be publicly disclosed and deleted.')
RESET MASTER
PURGE BINARY LOGS TO '...'
REVOKE ALL PRIVILEGES, GRANT OPTION FROM `root`@'%'
GRANT SHUTDOWN ON *.* TO `root`@'%'
SHUTDOWNThree things stood out to me in this burst:
- The note was a bluff. It says the data was backed up, but this actor only checked the size of each database. It never selected a single row, and the tables had already been dropped by the first attacker.
- It went after recovery.
RESET MASTERandPURGE BINARY LOGSremove the binary logs an admin would use to replay lost transactions. - It locked the owner out. It revoked every privilege from the network root account, left only the right to shut the server down, and then issued
SHUTDOWN.
The same network came back five more times over the next 28 hours from four other addresses, each time re-creating its ransom database in case someone had removed it.
Attack three: the RDP password
Remote Desktop drew a different crowd. Defender recorded the first failed logon at 03:53 UTC on Sept. 26, and the Windows Security log shows 2,563 failures from eight public addresses over the following day. The account lockout policy triggered 44 times, which slowed the guessing but did not stop it.
At 07:50:08 and 07:54:35 UTC on Sept. 27, 80.66.83.80 logged in as administrator with full admin rights. The two successes sit exactly in that address's guessing rhythm, and it kept guessing afterward, so this was a tool working through a list and not a person at a keyboard.
I then checked what that account did. Across 4,422 process events, 7,069 file events, and 5,142 registry events from Defender, none were tied to it. There was no interactive logon and no user profile was ever created. The VM's nightly auto-shutdown cut the session off seven minutes after the second login.
Before and after: comparing the machine
On Sept. 28 I captured a second investigation package and isolated the VM in Defender for Endpoint, about 90 hours after exposure began. I then compared the package with the baseline, category by category.
| Area | Change | Verdict |
|---|---|---|
| Logons | 2,563 failed and 2 successful admin logons from public addresses | Malicious |
| Firewall | Off on all three profiles | Mine, done at 05:07 UTC to expose the host |
| Users and groups | None | Clean |
| Services, tasks, autoruns | No additions | Clean |
| Running processes | No additions | Clean |
| Prefetch | 32 new entries, all Microsoft updaters or collection tools | Clean |
| Defender | No detections, real-time protection on | Clean |
So the operating system came through intact, while the database was a total loss. The attackers who got in through MySQL never needed the host, and the one who got the host password never used it.
Timeline
| Time (UTC) | Event |
|---|---|
| Sept. 25 04:43 | Exposure start recorded, with the weak accounts in place |
| Sept. 25 04:49 | Baseline investigation package captured |
| Sept. 25 05:07 | Windows Firewall disabled |
| Sept. 25 18:59 | VM back online after its nightly shutdown |
| Sept. 25 19:06 | First MySQL login attempts from the internet |
| Sept. 25 19:14 | First attacker logs in as root, copies and drops all tables |
| Sept. 25 20:53 | Second attacker drops all databases, leaves a bitcoin demand, revokes root |
| Sept. 26 03:53 | First failed RDP logon recorded by Defender |
| Sept. 27 07:50 | RDP password guessed, first admin logon |
| Sept. 27 07:54 | Second admin logon from the same address |
| Sept. 27 08:01 | VM auto-shutdown ends the exposure |
| Sept. 28 22:55 | Second investigation package captured |
| Sept. 28 23:04 | VM isolated in Defender for Endpoint |
MITRE ATT&CK mapping
| Tactic | Technique | Where I saw it |
|---|---|---|
| Reconnaissance | T1595 | Scanners probing 3306 and 3389 within minutes |
| Credential Access | T1110.001 | Password guessing against MySQL and RDP |
| Initial Access | T1078.003 | Valid local accounts: MySQL root and Windows administrator |
| Initial Access | T1133 | Internet-facing RDP and MySQL |
| Discovery | T1082 | SHOW DATABASES, SHOW TABLES, version and size checks |
| Collection | T1213 | Full table reads of the company database |
| Impact | T1485 | DROP TABLE and DROP DATABASE |
| Impact | T1490 | Binary logs reset and purged |
| Impact | T1531 | Root privileges revoked |
| Impact | T1657 | Bitcoin ransom notes |
Indicators of compromise
| Indicator | Role |
|---|---|
| 45.8.17.7 | MySQL: first attacker, copied and dropped all tables |
| 64.89.163.138, .154, .165, .166, .178 | MySQL: second crew, dropped databases and left the bitcoin note |
| 77.90.185.21, 77.90.185.30 | MySQL: scanner returning about every 80 minutes, 14 root logins |
| 213.209.159.115, 80.82.77.202 | MySQL: other successful root logins |
| 80.66.83.80 | RDP: guessed the administrator password |
| 193.24.123.39 | RDP: 1,601 failed logons, the most of any address |
| bc1q3t3rnktgv9cnd59lzk9rdhhg6qcxs7d68m2n8d | Bitcoin address in the ransom note |
| RECOVER_YOUR_DATA, RECOVER_YOUR_DATA_info | Database and table names used for the notes |
What I took from it
- An exposed database is found in minutes, not days. Nobody targeted this server. Automated crews sweep the whole internet for port 3306, and the entire attack is a script.
- Backups decide whether a ransom note matters. Because I had taken a dump first, recovery was a restore. Paying would have bought nothing, since the second crew had no copy of the data.
- Lockout policies buy time, not safety. The lockout slowed RDP guessing to about a day. A weak password still lost.
- Size your logs for the incident. The Security log hit its 20 MB cap and rolled over, costing me about 26 hours of events. My own repeated evidence collection made it worse by generating audit noise. Defender and Sentinel filled the gap, which is the case for shipping logs off the host.
- Write detections first. Having the rules and the baseline in place before exposure meant I was reading answers afterward, not guessing.
How I would fix it for real
- Close the network security group to everything but a management address, and turn the firewall back on.
- Delete the extra administrator account and disable Guest.
- Remove the network root account in MySQL and bind the server to localhost.
- Rebuild the VM from a clean image, since an admin password was known to an attacker.
- Restore the database from the backup taken before exposure.
This was a controlled lab based on the Cyber Range capstone exercise. The server held only dummy data and sat in a tenant with restricted outbound traffic. I used an AI assistant to help parse the exported logs and investigation packages, and checked its findings against the raw records.