lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I don't se the rationale: the bytecode loader should not crash. Otherwise it offers a way for hackers to corrupt the store used by the compiler to keep the binary code that was running and installed, in order to crash a server with running applications, and force it to experiment pseudo-random behavior that can be eventually studied, predicted and then forge an attack that will be successful.

For CVE, it would be a candidate as a sever bug to be listed and should be corrected. This may eventually make the byteloader a bit longer, but Lua apps don"t pass lot of time loading binary code. This is critical for servers even if they try to limit accesses to the bytecode store on the filesystem (but let's remember that the byteloader itself does not use a specific system user account when it will be used internally by internal APIs of the applications where many sessions and remote users run "their" code or session within the same system account (creating a system account for each of them to isolate them is very costly, it is assumed to be not needed if Lua is its own virtualized machine providing this isolation.

Comparatively, the Java VMs all perform validation tasks to load its bytecode. As well there's a good usage for transporting the bytecode over the network in order to delegate tasks that will run or will deployed on other hosts, and which is compiled just once, on a more powerful machine. These remote hosts may be very small machines with limited resources, just trusting the server over which they are connected and instructing them what to do and within a virtualized security realm parameterizd by the server (these remote hosts won't really know what they are running for the benefit of this server.

A Bytecode verifier in the bytecode loader is then an essential component for a solid Lua implementation.

Anwya I don't understand the interest of the sentence "Loading malformed bytecode should not crash Lua. Running maliciously crafted bytecode can crash the interpreter." First the loader should not crash, but if it does n,to crash and let the code run, running it to cause a crash is even more harmful and can make serious security damages. If to avoid the crash of the interpreter caused by malicious crafted code depends on the assumption that the byte code loader should have returned an error (without crashing), then it is the byteloader (not crashing) that must reject this invalid code and properly return the error expected by the bytecode runner.

The good rule for security is still "detect error early as much as you can, don't let then pass the way". This does not mean that downstream processing units don't need to perform other security checks, but most of the time these checks depends on the fact that some of their input was already validated at some level.

So any invalid/malformed bytecode should not be loadable at all. There's no way to justify it (even if the loader does not crash itself along with the whole VM running it, as effectively it should not); if this is not implemented, what can be done is to first try loading the bytecode and test it in an isolated temporary VM that can crash, isolated with no filesystem access, no network access and some limited memory quotas and CPU usage, and ignore the errors that may be returned such as permission denied or simple normal termination; detect this crash, declare the bytecode as not loadable in the normal VM.

I think that it should be possible to do that  on any Jua VM that runs on top of a system where it is easy to instanciante a new VM instance and even isolate it on a strict environemtn with no file access (or access to an empty directory and limted storage, possibly with a virtual filesystem residing only in memory). At least this should work on servers, this won't run on remote small devices with limited OS running everything in the same process and the same thread with a single core, but at least the server has the control and can check the byte code that it will submit to remotes (which then just have to check if the code was not damaged, e.g. by using string digital signatures on the transmitted bytecode they will receive to authenticate that it was effectively checked by the appropriate trusted source and not damaged in the middle of the transmission)


Le lun. 31 août 2020 à 16:15, Andrew Gierth <andrew@tao11.riddles.org.uk> a écrit :
>>>>> "Luiz" == Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> writes:

 >> >  v55 = string.dump(v19)
 >> >  v56 = string.format(v55,v16,v6)
 >> >  v58 = load(v56)
 >>
 >> This dumps the byte code of v19,  then potentially mutilates the dump,
 >> then tries to load the potentially malformed byte code. Which, per the
 >> documentation, "can crash the interpreter".

 Luiz> Loading malformed bytecode should not crash Lua.
 Luiz> Running maliciously crafted bytecode can crash the interpreter.

The code in question does in fact run the malformed bytecode:

 v55 = string.dump(v19)
 v56 = string.format(v55,v16,v6)
 v58 = load(v56)

 -- at this point, v58 is a function value with invalid bytecode;

 v59 = load(v58)

 -- load(x) where x is a function assumes that x is a reader function,
 -- to be called in order to obtain chunks of input. So v58 is called
 -- from inside load(), via generic_reader -> lua_callk -> luaV_execute
 -- which then crashes due to the malformed code.

Regardless, the answer is "don't mutilate the bytecode". Sandboxes that
need to prevent the user crashing the interpreter obviously have to
disable the binary load option (along with preventing access to the
debug library, etc.)

--
Andrew.