veilletech.fr
28 sept. Feed du jour
#02 SÉCURITÉ Faille

LuaRocks : un rockspec en bytecode a pris le serveur

Un bac à sable qui cache les noms ne cache pas la mémoire.

Le registre LuaRocks.org a été compromis à plusieurs reprises entre le 9 juillet et le 20 août 2026 : un rockspec envoyé sous forme de bytecode LuaJIT sortait du bac à sable et exécutait du code sur le serveur. Les mainteneurs n'ont trouvé aucun paquet existant modifié, mais considèrent la base entière comme lue. Clés API, sessions et secrets 2FA ont été révoqués : chaque utilisateur a des gestes à faire.

4 min de lectureintermédiairevidéo 1:18
Partager
Sommaire6 sections
  1. Ce qui se passe
  2. Le mécanisme
  3. Chronologie
  4. Ce qui a été vérifié
  5. Comment s'y prendre
  6. À retenir

Ce qui se passe

LuaRocks.org, le registre de paquets de l'écosystème Lua, a reçu le 25 septembre, via la CISA, le signalement d'une faille d'exécution de code à distance, corrigée le lendemain. L'enquête a montré qu'elle avait déjà été exploitée plusieurs fois entre le 9 juillet et le 20 août. Tout ce que le serveur pouvait lire est considéré comme exposé : le site tourne désormais sur une machine neuve, et chaque identifiant de l'ancienne a été révoqué.

Le mécanisme

Un rockspec, le fichier qui décrit un paquet, est un script Lua que le site exécute à chaque envoi pour en lire les champs. LuaRocks.org tourne sur OpenResty, donc sous LuaJIT, avec trois précautions : chargement par loadstring, environnement vide posé par setfenv pour couper l'accès aux globales, plafond d'instructions.

Le défaut tient au chargement. En Lua 5.1 comme en LuaJIT, loadstring accepte par défaut du code source et du bytecode précompilé, reconnaissable à son premier octet, \27. Le site n'attendait que du texte, sans jamais l'exiger.

Or LuaJIT ne vérifie pas le bytecode qu'il charge. Un fichier forgé peut lire et écrire hors de ses propres données, donc n'importe où dans la mémoire du processus. L'environnement vide ne filtre que les noms de globales : le bytecode n'en a pas besoin, il retrouve l'état Lua réel en mémoire et appelle directement les fonctions que le bac à sable devait masquer. N'importe quel compte inscrit pouvait le faire, par le site ou par l'API.

textebytecodeRockspec envoyéloadstringEnvironnement videChamps lusAucune vérificationMémoire du serveurFonctions masquéesCommandes shell
Le même envoi, deux chemins : le texte reste dans le bac à sable, le bytecode en sort

Le correctif impose le mode texte seul et refuse en plus tout fichier qui commence par \27, car Lua 5.1 d'origine ignore l'argument de mode. La lecture des manifestes d'autres serveurs, qui avait le même défaut, est corrigée aussi. Le motif, pour qui évalue de la configuration écrite en Lua :

Lua
if content:byte(1) == 27 then
  return nil, "bytecode refusé"
end
local chunk, err = loadstring(content, "rockspec", "t") -- "t" : texte seul (LuaJIT)
if not chunk then return nil, err end
setfenv(chunk, {})

Chronologie

Le compte du serveur web pouvait obtenir les droits d'administration : la base entière est supposée lue. Soit les e-mails et hachages bcrypt des mots de passe, les clés API, les secrets 2FA, les jetons GitHub liés (profil et e-mail seulement), les sessions et journaux avec adresses IP, et les identifiants de services tiers.

Ce qui a été vérifié

Un dépôt public, rocks-moonscript-org/moonrocks-mirror, recopie chaque jour tout ce que le site sert. Comparé à l'état du 8 juillet, il n'a révélé aucun paquet existant altéré, et seuls les paquets des attaquants contenaient du bytecode. Deux angles morts, reconnus : une suppression par l'attaquant ressemble à une suppression légitime, et rien ne dit ce que le serveur compromis a réellement servi aux clients.

Comment s'y prendre

  1. Créer une nouvelle clé API si vous utilisez luarocks upload.
  2. Se reconnecter et changer le mot de passe, partout où il est réutilisé.
  3. Reconfigurer la 2FA, dont les secrets ont été supprimés.
  4. Passer le client en 3.12 ou plus : jusqu'à la 3.11.1, sous LuaJIT ou Lua 5.1, il exécuterait un bytecode servi à la place d'un rockspec.
  5. Chercher les trois paquets de l'attaquant ; une machine qui les a installés est compromise.
  6. Mainteneurs : relire vos versions récentes depuis la page Security Audit.
Terminal
luarocks --version
luarocks list | grep -E 'bcrcewon|7e0b94029db0|7e0b9402f9c8'

Source : LuaRocks Security Incident September 2026, LuaRocks.org, septembre 2026. Repéré sur Lobste.rs le 27 septembre.