Here I'm going to put these ones aside, as they are mainly dealing with
bugs in the Python guts, and therefore aren't something that can be designed
around.
> A second category of possible attacks can permanently damage the
> attacked system -- by deleting or modifying files or directories.
> - This is usually done by abusing functions that can create files or run
> arbitrary system commands.
My initial thoughts on this (these are somewhat influenced by safe-tcl,
and bits I've been kicking over during a wine-tasting lunch)
Ok, a switch (or something) that turns on 'unsafe mode'. Inside unsafe
mode, import is prohibited. Before entering unsafe mode, it is the
responsibility of the user to disable nasties. A lump of code might
read a code object from somewhere (net, email, whatever), fork(), then
kill off things that are unwanted (del posix, os, whatever*), then drop
into 'unsafe mode'. This makes it easy to set up things beforehand,
so, eg, if you want to make snmp commands available, you can. I'm not
sure entirely how the safe and unsafe interpreters should communicate
(assuming that you want to, which in my case, I do :)
Obviously it should not be possible to drop back out of unsafe mode.
Actually, re-reading your mail, its fairly similar - the guarded_exec()
would be similar - while inside that, the above checks would apply, once you
exit it, back to normal.
Don't know how on earth to kill __builtin__.open - maybe making it
subject to the same 'am I in unsafe mode' switch. Looking at bltinmodule.c,
the functions that would need this treatment are execfile, open, import.
I personally believe that allowing even open(file,'r') is too much - knowing
what files are 'dont touch' and what are safe is a problem. eg .rhosts,
/etc/shadow (for solaris), /tcb/anything (OSF/1). write and read should be
ok, so long as you can only do it to files already open before the switch to
unsafe mode - not sure how it would be possible to supply 'os.read' without
also supplying the rest of os. Maybe a new 'unsafemodule' which supplies
'write', 'read', and any of the other stuff, that is needed inside unsafe
mode.
The above has the advantage (imho) that it's not going to be a huge amount
of modifications to the base code. It's also easier for the programmer to
work out what he wants to provide.
Disadvantages: you need to think before using it - if you make stuff
available that's dangerous, you will open holes, but that's going to be
possible anyway - idiot-proof systems are almost impossible to design :-)
> - Do you have a need for this -- would you use it?
Yep.
> - Do you think it can be made safe enough?
For my purposes, yes. :)
> - Are there holes in my approach?
> - Do you like my approach?
See above.
> - Can you think of a better name for guarded_exec()? (I don't like
> rexec since it sounds too much like remote exec.)
unsafe_exec() taintexec()
> - Do you know of any potentially unsafe situations (i.e. bugs :-)in
> the current Python code, like the recursion I mentioned in repr() and
> print?
Not worried too much about these at the moment.
> - Would you like to help implementing this? (In that case you'll need
> to provide a PGP key :-)
Well, I'd have to get PGP working first. :) But I may fiddle around with
this anyway.
> - Anyone know enough about the approaches other languages are taking
> to summarize how they do it?
Not well enough - check out the papers on safe-tcl in the safe-tcl
distribution...
Anthony