[Tutor] Security [Was: Re: Decoding]

Michael Sparks ms at cerenity.org
Tue Aug 14 13:04:41 CEST 2007


Tiger12506,


You are COMPLETELY missing the point. The __following__ code

> >> > foo = raw_input(...)
> >> > x = eval(foo)

ONLY works if the user has console access to the machine.

If they have console access to the machine 
AND you're worried about them damaging it
THEN an eval(raw_input( ...)) construct is the least of your worries.

I'm not referring to text taken from
   * a network connection
   * a file
   * a web form
   * a P2P network

I was JUST referring to the ONE context of immediately eval'ing user input. 
(an unlikely one at that)

Where you say this:
> But if you parse a text file that you haven't reviewed... that's possible.

You're talking about a completely different context. Taking data from a 
network socket and using eval there is again a different context from above. 
Using it as a generic data conversion tool is again a different context.

In those 3 contexts, yes, anyone would agree that using eval is extremely
unwise at best. In the context of evaluating something which someone types at 
a console though?

On Tuesday 14 August 2007 02:28, Tiger12506 wrote:
> > On Monday 13 August 2007 22:39, Tiger12506 wrote:
> >> > foo = raw_input(...)
> >> > x = eval(foo)
> >
> > ...
> >
> >> Let your program run on your machine and I'll walk by, type in this
> >> string,
> >> and hit enter. We'll see how much of an exception it is when you can't
> >> boot
> >> your XP machine anymore.
> >> ;-)
> >
> > Who cares? I don't run XP :-D
>
> I'm sure the equivalent can be done on different operating systems.

Actually, decent operating systems prevent that sort of problem. A way to 
trash a linux machine would be to wipe /lib/libc.* on Mac OS X , 
wipe /usr/lib/libc.dylib .

Let's see if it works on a linux machine:

>>> file("/lib/libc.so.6","w").close()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 13] Permission denied: '/lib/libc.so.6'

How about on a Mac OS X machine:

>>> file("/usr/lib/libc.dylib", "w").close()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
IOError: [Errno 13] Permission denied: '/usr/lib/libc.dylib'

Yes, of course if I was logged in as root on either it'd work. I could do far 
more damage far more easily though if I was.

> > Seriously though, if typing:
> >> "file('boot.ini','w').close()"
> >
> > Into an "eval prompt" worked then equally leaving a python interpreter
> > open
> > would be dumb, let alone a console.
>
> It does work. Try it with a simple file "temp.txt" for example. You can run
> any function call if the string is parsed with eval. Notice I did not say
> "type into an eval prompt type loop" I mean entirely if the string is
> parsed with eval.

I know just how powerful eval is. It's damn usefully powerful. 

You have changed the context here from the context I was talking about.

I was stating that *IF* the following can cause damage:
> >> > foo = raw_input(...)
> >> > x = eval(foo)

*AND* you are worried about that damage *BECAUSE* you believe the user is 
malicious, THEN the above code is the least of your worries.

> > Quite frankly anyone getting worried about this:
> >> > foo = raw_input(...)
> >> > x = eval(foo)
> >
> > Is pretty over anxious IMO. "Gosh, the person at the console might be
> > able to
> > get python do something which they can do anyway".
>
> Again. Anytime the function is parsed with eval, you can run *any* python
> function that is in the scope that the eval function is being executed
> from. Security risks are never simple. Of course they can do it with a  
> python console window open. But if you are worried about security you don't
> allow them access to the python console. You ecapsulate it.

Yes, I know. I was talking solely about a context where they clearly DO have 
access to the console, and that worrying about this was the least of your 
worries.

It's like saying "you left the door unlocked, you're going to get robbed", 
when you're missing that the people you're not trusting are inside the house 
watching the TV & drinking your coffee and you're leaving them there alone.

Leaving the doors on a house unlocked is generally unwise when you go out (not 
least due to invalidating insurance). It's totally irrelevant if you leave it 
with people in the house you expect to rob you.

> But what if you 
> use eval in a library function you write, which is used to parse some
> input? Peer to peer networks, http servers, even text files that you try to
> parse could be corrupted to cause your computer damage.

These are ALL different contexts from the one I was talking about. None
of these example are this context:

> >> > foo = raw_input(...)
> >> > x = eval(foo)

I maintain that this: eval(raw_input(...)) in the vast majority of cases is as 
safe as letting the user have access to the machine in the first place.

Your examples here:
> use eval in a library function you write, which is used to parse some
> input? Peer to peer networks, http servers, even text files that you try to
> parse could be corrupted to cause your computer damage.

Are NOT the same as sitting the user down in front of the machine. Therefore 
eval is a risk.

> The point is that eval is a security risk "greater than other
> implementations" that is-using int() is much more secure than eval().

It is only a security risk if the data source is untrusted. I maintain that
if you put a user down in front of a machine where they can run arbitrary
programs, then eval(raw_input( ...)) isn't a big deal.

> > (This is rather distinct from taking random crap from someone not on the
> > local
> > console and just doing it (eg from a network connection/external
> > resource))
> >
> > If the user wishes to trash their own machine, using an eval prompt is a
> > rather bizarre way to go about it.
>
> Sometimes it's not what they want to do. Kiosks centers are a good example.

Yes, I raised that as rare example. However those don't tend to use raw_input. 
They tend to use a local web browser locked in kiosk mode or custom 
application. And despite raising that example myself, I've yet to see any 
kiosk using python's raw_input on a console as an input source so far. Maybe 
you have odder kiosks where you are.

> But if you parse a text file that you haven't reviewed... that's possible.

Gosh, another completely different context, wonder if its relevant ;)

In case you've missed it:
   * Rule: eval is for the majority of uses a potentially gaping security hole
   * Exception proving rule: eval based on user input of a user sitting at
     the keyboard able to run programs cf code with the form:
     eval(raw_input( ...)) where that user can run arbitrary programs on the
     machine. (which they normally would be able to if they can interact
     with "raw_input").

Code is never a security risk. Code in context almost always has a security 
risk. The level of risk has to be weighed against other risks. If the user 
can trash a machine because they're physically preset, what they type in an 
eval loop is the least of your worries.


Michael.


More information about the Tutor mailing list