However, the devil is in the details, and while modules that have names like os with functions like execute are easily recognizable are dangerous, others like load or loadstring that are part of the base module might be seem as benign, while they are arguably the most powerful functions of Lua.
Lua’s sandboxing is extraordinarily powerful and for the most part easy to use, but the fact that you have one function that handles both loading code from strings (very safe, used 99% of the time) and loading bytecode (extremely dangerous but almost never used) is almost certainly the biggest security-related design flaw in the language. This isn’t the first time it’s been used in an exploit and it certainly won’t be the last.
The problem isn’t that you can’t make it safe; the problem is a lot of people will forget to, because loading bytecode is relatively obscure. When you’re listing out all the globals to decide which ones to include in the sandbox, you have to either omit load entirely, or replace it with a version that locks the mode parameter to "t".
You have one function that does two very different things with different safety considerations. A safer design would be to make it two functions.
Are there pwnie awards for best write ups? If so, I’d press that nominate button really hard. What an excellent level of detail and THEN an interactive challenge. Nice!
Some months ago I exploited a vulnerability in the Lua implementation of Factorio that allowed a malicious server to obtain arbitrary execution on clients. As the vulnerability has been patched for months already (Factorio versions below 1.1.101 are affected), is time to share the details with the community.
Some months ago I exploited a vulnerability in the Lua implementation of Factorio that allowed a malicious server to obtain arbitrary execution on clients. As the vulnerability has been patched for months already (Factorio versions below 1.1.101 are affected), is time to share the details with the community. (emphasis mine)
Lua’s sandboxing is extraordinarily powerful and for the most part easy to use, but the fact that you have one function that handles both loading code from strings (very safe, used 99% of the time) and loading bytecode (extremely dangerous but almost never used) is almost certainly the biggest security-related design flaw in the language. This isn’t the first time it’s been used in an exploit and it certainly won’t be the last.
But Lua 5.2 also included a parameter to
load()
to reject bytecode; all that’s needed there is to override the function to always reject bytecode.The problem isn’t that you can’t make it safe; the problem is a lot of people will forget to, because loading bytecode is relatively obscure. When you’re listing out all the globals to decide which ones to include in the sandbox, you have to either omit
load
entirely, or replace it with a version that locks themode
parameter to"t"
.You have one function that does two very different things with different safety considerations. A safer design would be to make it two functions.
Are there pwnie awards for best write ups? If so, I’d press that nominate button really hard. What an excellent level of detail and THEN an interactive challenge. Nice!
I just submitted it under “Pwnie for Remote Code Execution”, we’ll see what the organizers say!
Fascinating read.
I am kind of concerned this article doesn’t mention anything about responsible disclosure. Have this bug been fixed in Factorio?
The first paragraph of the article:
The first paragraph:
Thanks! For some reason I missed that