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.

  1. Build it locked down. A Windows 11 VM named CORP-FIN-PAYROL with all inbound traffic denied, onboarded to Defender for Endpoint.
  2. 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 with mysqldump before going further.
  3. 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.
  4. 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.
  5. Capture a baseline. A Defender investigation package, taken at 04:49 UTC on Sept. 25, so I could compare the machine before and after.
  6. 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, LogonType

Attack 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`@'%'
SHUTDOWN

Three 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 MASTER and PURGE BINARY LOGS remove 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.

AreaChangeVerdict
Logons2,563 failed and 2 successful admin logons from public addressesMalicious
FirewallOff on all three profilesMine, done at 05:07 UTC to expose the host
Users and groupsNoneClean
Services, tasks, autorunsNo additionsClean
Running processesNo additionsClean
Prefetch32 new entries, all Microsoft updaters or collection toolsClean
DefenderNo detections, real-time protection onClean

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:43Exposure start recorded, with the weak accounts in place
Sept. 25 04:49Baseline investigation package captured
Sept. 25 05:07Windows Firewall disabled
Sept. 25 18:59VM back online after its nightly shutdown
Sept. 25 19:06First MySQL login attempts from the internet
Sept. 25 19:14First attacker logs in as root, copies and drops all tables
Sept. 25 20:53Second attacker drops all databases, leaves a bitcoin demand, revokes root
Sept. 26 03:53First failed RDP logon recorded by Defender
Sept. 27 07:50RDP password guessed, first admin logon
Sept. 27 07:54Second admin logon from the same address
Sept. 27 08:01VM auto-shutdown ends the exposure
Sept. 28 22:55Second investigation package captured
Sept. 28 23:04VM isolated in Defender for Endpoint

MITRE ATT&CK mapping

TacticTechniqueWhere I saw it
ReconnaissanceT1595Scanners probing 3306 and 3389 within minutes
Credential AccessT1110.001Password guessing against MySQL and RDP
Initial AccessT1078.003Valid local accounts: MySQL root and Windows administrator
Initial AccessT1133Internet-facing RDP and MySQL
DiscoveryT1082SHOW DATABASES, SHOW TABLES, version and size checks
CollectionT1213Full table reads of the company database
ImpactT1485DROP TABLE and DROP DATABASE
ImpactT1490Binary logs reset and purged
ImpactT1531Root privileges revoked
ImpactT1657Bitcoin ransom notes

Indicators of compromise

IndicatorRole
45.8.17.7MySQL: first attacker, copied and dropped all tables
64.89.163.138, .154, .165, .166, .178MySQL: second crew, dropped databases and left the bitcoin note
77.90.185.21, 77.90.185.30MySQL: scanner returning about every 80 minutes, 14 root logins
213.209.159.115, 80.82.77.202MySQL: other successful root logins
80.66.83.80RDP: guessed the administrator password
193.24.123.39RDP: 1,601 failed logons, the most of any address
bc1q3t3rnktgv9cnd59lzk9rdhhg6qcxs7d68m2n8dBitcoin address in the ransom note
RECOVER_YOUR_DATA, RECOVER_YOUR_DATA_infoDatabase 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

  1. Close the network security group to everything but a management address, and turn the firewall back on.
  2. Delete the extra administrator account and disable Guest.
  3. Remove the network root account in MySQL and bind the server to localhost.
  4. Rebuild the VM from a clean image, since an admin password was known to an attacker.
  5. 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.