Live
Hardening a live economy
The security side of over two years as the only developer of a live roleplay economy: finding the ways players duplicated, teleported or forged things, and closing them without taking the server down.
- Role
- Finding, fixing and preventing exploits, working solo
- Stack
- Lua (GLua), NutScript, MySQL
- Context
- Diverge Networks, a live roleplay server with a player-driven economy
- Status
- Live, with the trunk fix in testing
The problem
On a roleplay server, items are the economy. A bug that loses an item costs a player hours of play. A bug that duplicates one devalues everyone else’s. And the server can’t go down while you fix it.
As the only developer, I was also the security team. This is the side of the work players never see: finding the ways people duplicated, teleported or forged things, and closing them on a live server.
How I approach it
- Read every network handler as if the client is hostile. Anything a player’s game sends can be changed, so the server rebuilds or re-checks it against its own data.
- Reserve before you wait. Anything asynchronous, like a database write or an inventory add, is a gap a fast player can squeeze into, so the server takes what it needs first and gives it back if the work fails.
- Check permissions before reading the payload, not after.
- Ship fixes the live server can take. When an exploit is in use, the fix can’t wait for the next big update.
Shipment duplication
Live
Taking an item from a crate started an asynchronous inventory add without reserving the item first. Fast repeated requests could all pass the “is there one left?” check before any of them finished, and each walked away with an item.
I rewrote the take and drop back end. The count is now decremented and the crate locked before the asynchronous work starts, distance and amounts are checked on the server, and the item is refunded if it doesn’t fit. While I was there I fixed an admin inventory reset that could leave slots occupied by items that no longer existed.
Code excerpt coming soon
Taking from a crate: reserve and lock first, then the asynchronous add, with a refund on failure.
assets/excerpts/shipment-take.lua
Cheating a live PvP event
Live
Networked variables used by the Target PvP event revealed enough to the client for players to cheat it. I built the fix so it could go onto the live server straight away.
Forged evidence and records
Live
- A fingerprint card’s hidden data could be edited from the client. Edits now only accept known fields, capped in length, and are stored on the server (see forensics).
- Appeals only accept record IDs the server has already shown that player, so changing an ID in the request does nothing (see the justice system).
- When characters move between factions, the server checks the faction ID against its own data instead of accepting the one the client sent.
- The lockpicking minigame has server-side anti-cheat, so a modified client can’t just skip it.
Trunk teleporting
Built, in testing
Donators can spawn more than one vehicle. With two trunks open at once, players could move items between them from anywhere on the map. Only one spawned vehicle’s trunk can be open at a time now. This ships with the shared trunk migration.
And many smaller ones
- A context-menu action that removed weapon recoil.
- A way past the bank limit.
- Switching characters to get around the car limit.
- Duplication and restriction bypasses through gun bags, now isolated inventories.
- Moving and jumping from the console while tied up.
- Staff shooting from noclip and abusing the physics gun, plus logging when staff delete items from storage.
- Inventory syncs large enough to overflow network buffers, now encoded and compressed.
Keeping production safe
The fixes only matter if testing them can’t break the live server. I pushed for a production-like test server that can never touch production data, and guarded the development-only admin tools so they can’t run on production.