This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Wilma456's profile picture

Need Help with Sandboxing

Started by Wilma456, 02 April 2018 - 04:48 PM
Wilma456 #1
Posted 02 April 2018 - 06:48 PM
ardera had reported 2 Bugs in the Sandboxing of my Program VirtualOS that I can't solve:

1. getfenv(0) return the normal Enviroment. I had try do solve it with this code:

function tEnv.getfenv(arg)
    if type(arg) == "number" then
        return getfenv(arg+1)
    else
        return getfenv(arg)
    end
end
This works for getfenv(0), but gefenv(1),3,5 aare returning the unsandboxed Enviroment.

2. You can acces the host fileystem with "/../" e.g. fs.open("/../bug","w"). I had no idea how to solve it.

You can find the Code of VirtualOS here
apemanzilla #2
Posted 03 April 2018 - 01:31 AM
ardera had reported 2 Bugs in the Sandboxing of my Program VirtualOS that I can't solve:

1. getfenv(0) return the normal Enviroment. I had try do solve it with this code:

function tEnv.getfenv(arg)
	if type(arg) == "number" then
		return getfenv(arg+1)
	else
		return getfenv(arg)
	end
end
This works for getfenv(0), but gefenv(1),3,5 aare returning the unsandboxed Enviroment.

2. You can acces the host fileystem with "/../" e.g. fs.open("/../bug","w"). I had no idea how to solve it.

You can find the Code of VirtualOS here

1. getfenv and setfenv are deprecated anyways, might as well disable them entirely.
2. Resolve the path to an absolute one, strip any remaining .. segments, and then resolve relative to the sandboxed directory.
Bomb Bloke #3
Posted 03 April 2018 - 06:04 AM
getfenv and setfenv are deprecated anyways, might as well disable them entirely.

I'd agree with this if ComputerCraft didn't use a build of Lua in which they are not, in fact, deprecated.
ardera #4
Posted 03 April 2018 - 02:59 PM
First one: simple (but incomplete) Fix

local NEW_G = {}
local rawgetfenv = getfenv
function getfenv(x)
  local r = rawgetfenv(x)
  if r == _G then
	return NEW_G
  end
  return r
end
Note that this fix is incomplete.

os.run for example sets the environment of programs this way:

local f = loadstring(filecontents)
local env = setmetatable({}, {__index = _G})
setfenv(f, env)

So calling getfenv(1) in a program will return a table different from _G, but you can still get _G by doing "my_G = getmetatable(getfenv(1)).__index"
To fix this, you'd have to overwrite getmetatable.
(One may think you could also fix this by checking if getmetatable(r ).__index == _G in the getfenv function and then optionally doing getmetatable(r ).__index = NEW_G.
This doesn't work since you'd modify the environment of the function, not only of the return table)

Come to think of it, I think one could also exploit setfenv, getfenv, setmetatable & getmetatable to make code run in the host routine.

As I said, writing an unbreakable sandbox is hard :D/>

Fix 2 would be a bit more complicated, you'd have to write your own path parser.
Edited on 03 April 2018 - 03:37 PM
Wilma456 #5
Posted 10 April 2018 - 07:48 PM
The getfenv() function of you only works, if VirtualOs is diretly run from CraftOS, but if there is another sefenv() between VirtualOS and CraftOS it will not work.
CLNinja #6
Posted 10 April 2018 - 08:07 PM
The getfenv() function of you only works, if VirtualOs is diretly run from CraftOS, but if there is another sefenv() between VirtualOS and CraftOS it will not work.
There are a million ways to go about circumventing a sandbox that you'll have virtually no control over. Anything running prior to you will be able to inject stuff into you, so you kinda have to live with it.