extensions/sandbox_test/try_exploit.lua: Try calling found functions

master
Perttu Ahola 2014-09-28 14:00:17 +03:00
parent 0e7c9fc6e4
commit b23711f066
1 changed files with 52 additions and 7 deletions

View File

@ -48,21 +48,36 @@ local bad_values = {
io.popen,
}
-- Have a list of field names to check in case of metatables
-- Have a list of field names to check in case of disabled iteration
local interesting_field_names = {
"meta",
"class_meta",
"CreateChild",
"root",
"text",
"x",
}
for _, v in ipairs(bad_names) do -- All bad names are interesting
table.insert(interesting_field_names, v)
end
-- Functions that are known to shutdown the whole application if called without
-- parameters
local function_blacklist = {
"run_script_file",
"send_packet",
"disconnect",
"sub_tick",
}
local bad_names_set = {}
for _, v in ipairs(bad_names) do bad_names_set[v] = true end
local bad_values_set = {}
for _, v in ipairs(bad_values) do bad_values_set[v] = true end
local interesting_field_names_set = {}
for _, v in ipairs(interesting_field_names) do interesting_field_names_set[v] = true end
local function_blacklist_set = {}
for _, v in ipairs(function_blacklist) do function_blacklist_set[v] = true end
local function path_str(path)
local result = ""
@ -114,12 +129,15 @@ local function search(value, checked_values_set, result_list, current_path)
table.remove(current_path)
end
end
pcall(f)
pcall(f) -- Ignore errors
end
-- Iterate through the value
if type(value) == 'table' then
-- Iterate using __next
if getmetatable(value) and getmetatable(value).__next then
-- Use meta.__next
for field_name, v in pairs(value) do
local metapairs = function(t)
return getmetatable(value).__next, t, nil
end
for field_name, v in metapairs(value) do
if v ~= nil then
table.insert(current_path, field_name)
if bad_names_set[field_name] then
@ -130,6 +148,9 @@ local function search(value, checked_values_set, result_list, current_path)
table.remove(current_path)
end
end
end
-- Iterate through raw table value
if type(value) == 'table' then
-- Don't use meta.__next
local rawpairs = function(t)
return next, t, nil
@ -146,6 +167,26 @@ local function search(value, checked_values_set, result_list, current_path)
end
end
end
-- If it's a function or callable, call it and check the results
if type(value) == 'function' or
(getmetatable(value) and getmetatable(value).__call) then
-- Don't call if blacklisted
if not function_blacklist_set[current_path[#current_path]] then
-- Call with itself as parameter; that should give the most bang for
-- the buck
log:verbose("search: "..path_str(current_path).."(self)")
function f()
local ret = {value(value)}
for i = 1, table.getn(ret) do
local ret_v = ret[i]
table.insert(current_path, "()["..i.."]")
search(ret_v, checked_values_set, result_list, current_path)
table.remove(current_path)
end
end
pcall(f) -- Ignore errors
end
end
end
function M.run()
@ -204,8 +245,12 @@ function M.run()
for _, extname in ipairs(extnames) do
try_require_extension(extname)
end
-- Make this global so it stays in the environment for checking through
sandbox.make_global({loaded_extensions = loaded_extensions})
-- Make results global so they stay in the environment for checking
sandbox.make_global({
loaded_extensions = loaded_extensions,
})
-- Get the environment (which isn't available for iteration normally)
new_sandbox.env = local_getfenv(1)
end