Skip to content

Guide

How to find a backdoor in a FiveM script

A cheater takes an unfair advantage. A backdoor takes the server. If you install resources from anywhere other than their original author, this is the more important of the two problems.

Updated 8 min read

Why this outranks cheating

A cheater takes an unfair advantage inside your game. A backdoor takes your database, your administrative accounts, your players' data and, depending on how your host is set up, the machine. The two problems are usually filed under the same heading and they are not the same size.

The realistic route in is not a targeted attack. It is a leaked or re-uploaded script installed because it was free, with something extra inserted before it was passed on. This is common enough that dedicated scanner projects exist for named malware families in this ecosystem.

What to look for

A static scan is a text search with judgement attached. It cannot prove anything. It narrows a hundred thousand lines down to a list short enough for a person to read.

Patterns worth a look, and why each appears
PatternLegitimate useWhy an attacker wants it
os.execute, io.popenRare. Some tooling shells out for a genuine reason.Runs commands on the host. This is full server compromise, not a game exploit.
loadstring, dynamic loadLocale loaders and a few frameworks build code from data.Executes code delivered at runtime, so the payload never appears in the file you reviewed.
_G["os"] and bracket accessAlmost never, in resource code.Reaches the same functions while defeating a naive text search for the name.
Long base64 or hex blobsEmbedded assets, keys in config files, minified data.Hides a payload or a command-and-control address from a casual reader.
PerformHttpRequest to an unknown hostWebhooks, licence checks, map APIs.Exfiltrates data, or fetches instructions. The host is the tell.
Net events with vague names and no checksSloppy code, which is common.A remote command channel that looks like ordinary sloppiness.

Notice the middle column. Every pattern here has a legitimate use, which is exactly why this cannot be automated into a verdict. The output of a scan is a reading list, not a judgement.

Most hits are innocent

The first scan we ran against a real ESX server, 87 resources, produced 679 findings. Two were worth attention. Both were legitimate: a well-known library shelling out for a real reason, and a framework building code from locale data.

  1. 87 resources on the server
  2. 679 findings
  3. 57 findings
  4. 19 actual suspicions
  5. 2 worth attention A library shelling out for a real reason, and a framework building code from locale data. Both fine.
One real ESX server, scanned before and after the rules were tightened. Every number here is from our own run, and the two that survived were both legitimate.

A tool that produces 679 items nobody reads has achieved nothing. Tightening the rules brought that to 57 findings, of which 38 were inventory notes rather than suspicions. The mechanism that made the difference was not a cleverer pattern. It was requiring a written reason to suppress a finding:

A suppression with a reason is a review. A suppression without one is just a quieter problem.

If you audit your own server, keep the same discipline. Every finding you dismiss gets a line explaining why, stored next to the config. Six months later that file is the only reason anyone can tell a reviewed finding from an ignored one.

The files your scan misses

Most resources load their code with a wildcard, server/modules/*.lua or similar. A scanner that reads the manifest and follows the literal filenames it finds will silently skip every one of those files.

On our reference server that was 415 files. Not a rounding error: entire resources were invisible to both our backdoor scan and our event inventory until wildcards were expanded properly against the filesystem.

If you are running any scanner, community or commercial, this is the first thing to verify. Put a harmless marker string inside a glob-loaded file and check whether the tool reports it. Several do not.

Escrow-protected resources

Encrypted resources cannot be scanned at all, because the files are not readable. That is not a flaw in the scanner, but it does mean your coverage has a hole shaped exactly like every paid asset you installed. Worth knowing when you weigh how much a clean scan is telling you.

When you find a real one

  1. Do not restart the resource. Take the server offline first if you can afford to.
  2. Assume every secret the resource could read is compromised: database credentials, API keys, webhook URLs, admin tokens. Rotate them. A backdoor that ran once has already read them.
  3. Preserve a copy of the file before you delete anything. It is your only evidence.
  4. Check for persistence: other resources modified around the same time, unfamiliar admin accounts, unexpected entries in your identifier tables.
  5. Tell whoever else is running that resource. This one is a favour to the ecosystem.

Not installing them in the first place

  • Prefer the original author's distribution. Re-uploads and "free leaks" are the main delivery channel.
  • Read the manifest before the code. It tells you which files load and often reveals ones you did not expect.
  • Watch what a new resource talks to. An unexplained outbound host is worth an explanation before it goes live.
  • Scan on a schedule, not once. The risky moment is not installation day, it is the update three months later.

SwisserAC does this scan at boot and again on demand, with findings suppressible only with a reason. It is the least sophisticated part of the product and the one that has found the most on real servers, including, on one alpha server, the same shell call in two unrelated resources.