Re: LuaJIT bytecode disassembly and decompilation

  • From: Peter Cawley <corsix@xxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Sun, 8 Nov 2015 20:32:41 +0000

On Sun, Nov 8, 2015 at 7:49 PM, Alexander Gladysh <agladysh@xxxxxxxxx> wrote:

I'm actually interested in a "proof" that it is unsafe. Official
statement would do :)

As with PUC-Rio Lua, calling load(...) isn't overly dangerous, but
executing untrusted de-serialised LuaJIT bytecode in a Lua-level
sandbox is a bad idea.

Putting together a concrete proof of concept sandbox-escape would be
an interesting exercise, but it certainly feels like an attacker has
lots of tools to play with:
* The standard low-call trick probably still works for changing the
values of special stack slots. Combined with LuaJIT continuation
frames, this likely provides a very easy way to call arbitrary
addresses.
* LuaJIT bytecode is strictly stronger than source code: there are
several "private" bytecode instructions to allow pieces of standard
library to be implemented in Lua (thus making all such functions
expressible in bytecode and usable from the strictest of sandboxes),
and various fast-functions are implemented as special bytecode
instructions (thus again being almost-expressible in bytecode; the
"almost" comes from the extra BC_FUNCF header instruction inserted by
the bytecode reader, and the lack of the fallback code path being
properly wired up).
* Having a JIT compiler in play seems useful for getting around DEP:
if you craft some Lua code which uses interesting 32-bit constants,
and get said code JIT compiled, then the resulting machine code will
contain the constants. If those constants decode as x86 instructions,
then all you have to do is call the address where the constant was
emitted.

Other related posts: