[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Secure tables in Lua: Summary
- From: David Given <dg@...>
- Date: Thu, 03 Jul 2008 17:09:26 +0100
Dr. Markus Walther wrote:
[...]
I note that both David Given's solution and Doug Roger's improvement
allow violating the integrity of the secure table:
t.newkey = nil
Ah, I didn't realise you were trying to protect against malicious
attack; I thought you were just talking about data hiding.
In fact, in this situation, tables basically don't work --- they're
fundamentally mutable. If you share the same table to Alice and Bob,
then Alice can always mutate the table's state in such a way that Bob
will end up with a mutated table. In my approach, Alice can't get at
Bob's data directly, but it's still possible for Alice to replace Bob's
__index with her own version and eavesdrop.
Your example suffers from the same issue. Take the following code:
t = get_secure_table()
mt = getmetatable(t)
oldindex = mt.__index
mt.__index = function(t, k)
log_key(k)
end
setmetatable(t, mt)
This replaces the *shared* __index with an eavesdropping version that
logs all accessed keys.
A more secure approach avoids using shared mutable objects, which
basically means no tables.
function create_secure_store()
local data = {}
local keys = {}
local function newkey() local k = {} keys[k] = true end
local function get(k) if keys[k] then return data[k] end end
local function put(k, v) if keys[k] then data[k] = v end end
return newkey, get, put
end
...
local newkey, get, put = create_secure_store()
local k = newkey()
put(k, "Hello, world!")
(Finding a way of sharing newkey, get and put between Alice and Bob is
left as an exercise to the reader.) Now, all shared state is safely
hidden away in upvalues, and the only exposed data are the functions,
which aren't mutable, and so can't be suborned.
In fact, that's not strictly true: functions *are* mutable using
setfenv(). This means that you need to make sure that your secure
functions never try to access the environment, which means they must
import all external symbols via upvalues:
-- Dangerous! print can be suborned!
function p(n) print(n) end
-- Safe.
local print = print
function p(n) print(n) end
In general, Lua's not terribly good at this stuff because it lacks the
rigour necessary to make sure that you get everything right, all the
time --- it's far too easy to make a mistake and expose something, at
which point an attacker can fairly easily unravel your whole security
system. For example, in your sample code, your exposed object's
metatable's __index field points directly at the underlying data store,
which means that given a secured table t, this:
data = getmetatable(t).__index
...undoes all the security.
--
David Given
dg@cowlark.com