Bytecode Breakdown: Unraveling Factorio's Lua Security Flaws
A security researcher found memory corruption flaws in Factorio's Lua, enabling servers to run code on clients. Hardening Lua by disabling risky modules can prevent unauthorized code execution, crucial for securing dynamic languages.
Read original articleA security researcher uncovered memory corruption vulnerabilities in Factorio's Lua implementation, allowing malicious servers to execute code on clients. Lua is used in Factorio for game logic and mods, with a large modding community. The multiplayer mode's deterministic lockstep feature requires all players to execute Lua code to maintain synchronization, potentially exposing the game to network-based attacks. Exploiting Lua's powerful functions like loadstring can lead to memory manipulation and code execution. Lua bytecode, not machine code, is executed by the interpreter, making it susceptible to manipulation. To exploit Factorio, a malicious map with crafted Lua code can be hosted on a server to target connecting clients. Hardening Lua by disabling dangerous modules like os and loadstring is recommended to prevent unauthorized code execution. Understanding Lua bytecode and its execution process is crucial for comprehending and potentially exploiting vulnerabilities in dynamic languages like Lua.
Related
Factorio Fluids 2.0
The Factorio Friday Facts detail the game's fluid system overhaul. The new algorithm simplifies fluid flow with segments, improving efficiency, throughput, and distribution while addressing previous issues. Sacrificing realism for gameplay, the update aims to enhance player experience.
A portable lightweight C FFI for Lua, based on libffi
A GitHub repository offers a portable lightweight C FFI for Lua, based on libffi. It aims for LuaJIT FFI compatibility, developed in C. Includes features, examples, basic types, build instructions, testing, and acknowledgements.
Vulnerability in Popular PC and Server Firmware
Eclypsium found a critical vulnerability (CVE-2024-0762) in Intel Core processors' Phoenix SecureCore UEFI firmware, potentially enabling privilege escalation and persistent attacks. Lenovo issued BIOS updates, emphasizing the significance of supply chain security.
The Dirty Pipe Vulnerability
The Dirty Pipe Vulnerability (CVE-2022-0847) in Linux kernel versions since 5.8 allowed unauthorized data overwriting in read-only files, fixed in versions 5.16.11, 5.15.25, and 5.10.102. Discovered through CRC errors in log files, it revealed systematic corruption linked to ZIP file headers due to a kernel bug in Linux 5.10. The bug's origin was pinpointed by replicating data transfer issues between processes using C programs, exposing the faulty commit. Changes in the pipe buffer code impacted data transfer efficiency, emphasizing the intricate nature of kernel development and software component interactions.
OpenSSL CVE-2024-5535: `SSL_select_next_proto` buffer overread
A bug, CVE-2024-5535, in OpenSSL since 2011 allows heap data leakage. Impacts Python <= 3.9, Node.js <= 9. NPN support removal in newer versions reduces risk. Bug affects SSL_select_next_proto in OpenSSL, BoringSSL, LibreSSL. Memory safety risks demand caution and updates.
Since lua interprets bytecode, it can check the arguments to the bytecode are meaningful. Point to memory lua allocated, things like that.
Turns out it doesn't do that. Feed it bytecode with invalid arguments passed to the instructions and it executes it anyway. The rest of the compromise follows.
Further, instead of fixing their interpreter, the game plan is to statically analyse bytecode. Which turns out to only work in simple cases.
For a sandbox friendly interpreted language this is pretty disappointing. I wonder if they'd take patches to stop the interpreter trusting the input - presumably performance regression is the fear there, which seems dubious when luajit is the fast option anyway.
Some example scenarios:
- Code is static and is executed directly by a user, the default case languages care typically care about. Including Lua.
- Code is dynamically fetched and executed through some update process, hopefully only through official channels. Here you can get away by making the process secure, but who knows.
- Code can be added by the user through plugins, this can be made easier through stores with the click of a button. You can review plugins, but this is hardly done. Here you need to consider if the code should be sandboxed or the user should be careful.
- A multiplayer game where a server can be extended with custom code via plugins, but not the clients. Here you need to consider that the users/gamers who are hosting servers are eager to try many different plugins. The plugin community (gamers) can also be a lot more dangerous.
- A multiplayer game where the server can execute arbitrary code on clients, just like a browser. Here you need to be very careful about sandboxing, especially on clients as gamers will just join random servers without thinking about the security implications.
The last point being Factorio's case. I'm not necessarily disagreeing that it's the developers job to evaluate this, but sometimes it's not obvious that for example the load function in Lua can run arbitrary bytecode which is unsafe.
To be honest, I wasn't aware that Lua's bytecode is unsafe, but I am aware that LuaJIT's bytecode is unsafe. But as far as I know this fact is just stated randomly in the mailing list and github issues as an obvious fact.
There is another thing about servers being able to crash clients (just run some infinite loop on them), but this much harder and maybe pointless to avoid.
It's strange that after upstream has given up on the problem as it was too hard, factorio devs have chosen to try to fix the verifier/write their own (not sure which of the two they did).
Minetest's loadstring function forbids bytecode entirely: https://github.com/minetest/minetest/blob/9a1501ae89ffe79c38...
I wonder why factorio mods need the ability to execute raw lua bytecode. If they don't have it, there would be no need for a verifier.
It's quite dangerous in the first place to execute lua code downloaded over the network. JS execution environments have gone through decades of cycles of discoveries of exploits and fixes. Lua gets those as well but on a smaller scale, and with less staffing to improve security. The main protection is I guess that there is fewer people running malicious game servers.
Seems to me that this would benefit from the much more severe hardening work that's gone into isolating browser environments (a hard and VERY well tested and funded target), as well as the massive work that's gone into performance optimizing dynamic types.
Plus if the mod needs UI there's the canvas and potentially even React etc if a Dom-like model is available.
Content-wise: Wow... We are totally, completely, utterly screwed once people start putting together ensembles of AI SWEs equipped with 10,000 blog posts like this one on finding weird memory exploits. Ultimately I think we're gonna need a whole new paradigm for security, or at least some new element in the stack. It's my potentially naive opinion that all the modern talk about "trusted" clients and DB roles and all that is trying to patch holes in swiss cheese; hopefully, we can find a new stack of LLM-maintained swiss cheese to add on instead!
a. Bytecode
b. Debug, Io, Os libraries
...
Also, be very careful with sandboxing. It can be deceptively easy to break out of.
Everyone eventually learns this lesson, see: Roblox (removed bytecode almost a decade ago after, if I recall correctly, an exploit exfiltrated their server tokens), Company of Heroes (bytecode bug leading to RCE)
Luau should come with safe defaults, from what I've been told.
It doesn’t follow to me, that since all clients are running their own simulation, Lua scripts must run on every client too.
If a client runs a Lua script, why can’t we just run it on their machine and propagate any game state changes (if the script adds an inserted, for example,) as if the player made those changes themselves?
Browsers split their various components across multiple processes to provide isolation. VMs would provide even more isolation.
I don’t blame Factorio though - this (anonymous?) researcher is 100x developer material.
Related
Factorio Fluids 2.0
The Factorio Friday Facts detail the game's fluid system overhaul. The new algorithm simplifies fluid flow with segments, improving efficiency, throughput, and distribution while addressing previous issues. Sacrificing realism for gameplay, the update aims to enhance player experience.
A portable lightweight C FFI for Lua, based on libffi
A GitHub repository offers a portable lightweight C FFI for Lua, based on libffi. It aims for LuaJIT FFI compatibility, developed in C. Includes features, examples, basic types, build instructions, testing, and acknowledgements.
Vulnerability in Popular PC and Server Firmware
Eclypsium found a critical vulnerability (CVE-2024-0762) in Intel Core processors' Phoenix SecureCore UEFI firmware, potentially enabling privilege escalation and persistent attacks. Lenovo issued BIOS updates, emphasizing the significance of supply chain security.
The Dirty Pipe Vulnerability
The Dirty Pipe Vulnerability (CVE-2022-0847) in Linux kernel versions since 5.8 allowed unauthorized data overwriting in read-only files, fixed in versions 5.16.11, 5.15.25, and 5.10.102. Discovered through CRC errors in log files, it revealed systematic corruption linked to ZIP file headers due to a kernel bug in Linux 5.10. The bug's origin was pinpointed by replicating data transfer issues between processes using C programs, exposing the faulty commit. Changes in the pipe buffer code impacted data transfer efficiency, emphasizing the intricate nature of kernel development and software component interactions.
OpenSSL CVE-2024-5535: `SSL_select_next_proto` buffer overread
A bug, CVE-2024-5535, in OpenSSL since 2011 allows heap data leakage. Impacts Python <= 3.9, Node.js <= 9. NPN support removal in newer versions reduces risk. Bug affects SSL_select_next_proto in OpenSSL, BoringSSL, LibreSSL. Memory safety risks demand caution and updates.