Re: [Python-Dev] Security capabilities in Python

2005-04-09 Thread Jp Calderone
On Sat, 9 Apr 2005 00:13:40 -0500 (CDT), Ka-Ping Yee <[EMAIL PROTECTED]> wrote:
>On Fri, 8 Apr 2005, Eyal Lotem wrote:
> > I would like to experiment with security based on Python references as
> > security capabilities.
> 
> This is an interesting and worthwhile thought.  Several people
> (including myself) have talked about the possibility of doing
> this in the past.  I believe the two problems you mention can be
> addressed without modifying the Python core.
> 
> > * There is no way to create secure proxies because there are no
> > private attributes.
> 
> Attributes are not private, but local variables are.  If you use
> lexical scoping to restrict variable access (as one would in
> Scheme, E, etc.) you can create secure proxies.  See below.
> 
> > * Lots of Python objects are reachable unnecessarily breaking the
> > principle of least privelege (i.e: object.__subclasses__() etc.)
> 
> True.  However, Python's restricted execution mode prevents access
> to these attributes, allowing you to enforce encapsulation.  (At
> least, that is part of the intent of restricted execution mode,
> though currently we do not make official guarantees about it.)
> Replacing __builtins__ activates restricted execution mode.
> 
> Here is a simple facet function.
> 
> def facet(target, allowed_attrs):
> class Facet:
> def __repr__(self):
> return '' % (allowed_attrs, target)
> def __getattr__(self, name):
> if name in allowed_attrs:
> return getattr(target, name)
> raise NameError(name)
> return Facet()
> 
> def restrict():
> global __builtins__
> __builtins__ = __builtins__.__dict__.copy()
> 
> # Here's an example.
> 
> list = [1, 2, 3]
> immutable_facet = facet(list, ['__getitem__', '__len__', '__iter__'])
> 
> # Here's another example.
> 
> class Counter:
> def __init__(self):
> self.n = 0
> 
> def increment(self):
> self.n += 1
> 
> def value(self):
> return self.n
> 
> counter = Counter()
> readonly_facet = facet(counter, ['value'])
> 
> If i've done this correctly, it should be impossible to alter the
> contents of the list or the counter, given only the immutable_facet
> or the readonly_facet, after restrict() has been called.
> 
> (Try it out and let me know if you can poke holes in it...)
> 
> The upshot of all this is that i think you can do secure programming
> in Python if you just use a different style.  Unfortunately, this
> style is incompatible with the way classes are usually written in
> Python, which means you can't safely use much of the standard library,
> but i believe the language itself is not fatally flawed.
> 

  Does using the gc module to bypass this security count?  If so:

[EMAIL PROTECTED]:~$ python -i facet.py 
>>> import gc
>>> c = readonly_facet.__getattr__.func_closure[1]
>>> r = gc.get_referents(c)[0]
>>> r.n = 'hax0r3d'
>>> readonly_facet.value()
'hax0r3d'
>>> 

  This is the easiest way of which I know to bypass the use of cells as a 
security mechanism.  I believe there are other more involved (and fragile, 
probably) ways, though.

  Jp
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Re: marshal / unmarshal

2005-04-09 Thread Martin v. Löwis
Terry Reedy wrote:
> The particular issue here is not platform dependence as such but 
> within-platform usage dependence, as in the same code giving radically 
> different answers in a standard interactive console window and an idle 
> window, or when you run it the first time (from xx.py) versus subsequent 
> times (from xx.pyc) until you edit the file again. 

Yet, this *still* is a platform dependence. Python makes no guarantee
that 1e1000 is a supported float literal on any platform, and indeed,
on your platform, 1e1000 is not supported on your platform.

Furthermore, Python makes no guarantee that it will report when an
unsupported float-literal is found, so you just get different behaviour,
by accident.

This, in turn, is a violation of the principle "errors should never
pass silently". Alas, nobody found the time to detect the error, yet.

Just don't do that, then.

Regards,
Martin
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Re: marshal / unmarshal

2005-04-09 Thread Skip Montanaro

Martin> Yet, this *still* is a platform dependence. Python makes no
Martin> guarantee that 1e1000 is a supported float literal on any
Martin> platform, and indeed, on your platform, 1e1000 is not supported
Martin> on your platform.

Are float("inf") and float("nan") supported everywhere?  I don't have ready
access to a Windows machine, but on the couple Linux and MacOS machines
at-hand they are.  As a starting point can it be agreed on whether they
should be supported?  (There is a unique IEEE-754 representation for both
values, right?  Should we try and support any other floating point format?)
If so, the float("1e1") == float("inf") in all cases, right?  If not,
then Python's lexer should be trained to know what out-of-range floats are
and complain when it encounters them.  In either case, we should then know
how to fix marshal.loads (and probably pickle.loads).

That seems like it would be a start in the right direction.

Skip
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Re: Re: marshal / unmarshal

2005-04-09 Thread Fredrik Lundh
Skip Montanaro wrote:

> Are float("inf") and float("nan") supported everywhere?

nope.

>>> float("inf")
Traceback (most recent call last):
  File "", line 1, in ?
ValueError: invalid literal for float(): inf
>>> float("nan")
Traceback (most recent call last):
  File "", line 1, in ?
ValueError: invalid literal for float(): nan

>>> 1e1
1.#INF
>>> float("1.#INF")
Traceback (most recent call last):
  File "", line 1, in ?
ValueError: invalid literal for float(): 1.#INF

> As a starting point can it be agreed on whether they should be supported?

that would be nice.

> In either case, we should then know how to fix marshal.loads (and probably
> pickle.loads).

pickle doesn't have the INF=>1.0 bug:

>>> import pickle
>>> pickle.loads(pickle.dumps(1e1))
...
ValueError: invalid literal for float(): 1.#INF

>>> import cPickle
>>> cPickle.loads(cPickle.dumps(1e1))
...
ValueError: could not convert string to float

>>> import marshal
>>> marshal.loads(marshal.dumps(1e1))
1.0

 



___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Re: marshal / unmarshal

2005-04-09 Thread Martin v. Löwis
Skip Montanaro wrote:
> Martin> Yet, this *still* is a platform dependence. Python makes no
> Martin> guarantee that 1e1000 is a supported float literal on any
> Martin> platform, and indeed, on your platform, 1e1000 is not supported
> Martin> on your platform.
> 
> Are float("inf") and float("nan") supported everywhere? 

I would not expect that, but Tim will correct me if I'm wrong.

> As a starting point can it be agreed on whether they
> should be supported?  (There is a unique IEEE-754 representation for both
> values, right?

Perhaps yes for inf, but I think maybe no for nan. There are multiple
IEEE-754 representations for NaN. However, I understand all NaN are
meant to compare unequal - even if they use the same representation.


> If so, the float("1e1") == float("inf") in all cases, right?

Currently, not necessarily: if a large-enough exponent is supported
(which might be the case with a IEEE "long double", dunno), 1e1
would be a regular value.

> That seems like it would be a start in the right direction.

Pieces of it would be a start in the right direction.

Regards,
Martin
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Re: Re: marshal / unmarshal

2005-04-09 Thread Fredrik Lundh
> pickle doesn't have the INF=>1.0 bug:
>
 import pickle
 pickle.loads(pickle.dumps(1e1))
> ...
> ValueError: invalid literal for float(): 1.#INF
>
 import cPickle
 cPickle.loads(cPickle.dumps(1e1))
> ...
> ValueError: could not convert string to float
>
 import marshal
 marshal.loads(marshal.dumps(1e1))
> 1.0

should I check in a fix for this?

the code in PyFloat_FromString contains lots of trickery to deal with more or 
less
broken literals, and more or less broken C libraries.

unfortunately, and unlike most other functions with similar names, 
PyFloat_FromString
takes a Python object, not a char pointer.  would it be a good idea to add a 
variant
that takes a char*?  if so, should PyFloat_FromString use the new function, or 
are we
avoiding that kind of refactoring for speed reasons these days?

any opinions?

 



___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Re: Security capabilities in Python

2005-04-09 Thread Fredrik Lundh
Ka-Ping wrote:

> counter = Counter()
> readonly_facet = facet(counter, ['value'])
>
> If i've done this correctly, it should be impossible to alter the
> contents of the list or the counter, given only the immutable_facet
> or the readonly_facet, after restrict() has been called.

I'm probably missing something, but a straightforward reflection
approach seems to work on my machine:

>>> restrict()
>>> readonly_facet = facet(counter, ['value'])
>>> print readonly_facet.value()
0
>>> readonly_facet.value.im_self.n = "oops!"
>>> print readonly_facet.value()
oops!
>>> class mycounter:
... def value(self): return "muhaha!"
...
>>> readonly_facet.value.im_self.__class__ = mycounter
>>> print readonly_facet.value()
muhaha!
...
>>> readonly_facet.value.im_func.func_globals["readonly_facet"] = myinstance
...

and so on

does that restrict() function really do the right thing, or is my
python install broken?





___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Security capabilities in Python

2005-04-09 Thread Michael Hudson
Jp Calderone <[EMAIL PROTECTED]> writes:

>   Does using the gc module to bypass this security count?  If so:
>
> [EMAIL PROTECTED]:~$ python -i facet.py 
> >>> import gc
> >>> c = readonly_facet.__getattr__.func_closure[1]
> >>> r = gc.get_referents(c)[0]
> >>> r.n = 'hax0r3d'
> >>> readonly_facet.value()
> 'hax0r3d'
> >>> 
>
>   This is the easiest way of which I know to bypass the use of cells
>   as a security mechanism.  I believe there are other more involved
>   (and fragile, probably) ways, though.

The funniest I know is part of PyPy:

def extract_cell_content(c):
"""Get the value contained in a CPython 'cell', as read through
the func_closure of a function object."""
# yuk! this is all I could come up with that works in Python 2.2 too
class X(object):
def __eq__(self, other):
self.other = other
x = X()
x_cell, = (lambda: x).func_closure
x_cell == c
return x.other

It would be unfortunate for PyPy (and IMHO, very un-pythonic) if this
process became impossible.

Cheers,
mwh

-- 
  Java sucks. [...] Java on TV set top boxes will suck so hard it
  might well inhale people from off  their sofa until their heads
  get wedged in the card slots.  --- Jon Rabone, ucam.chat
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] threading (GilState) question

2005-04-09 Thread Michael Hudson
"Gregory P. Smith" <[EMAIL PROTECTED]> writes:

>> > Under "Limitations and Exclusions" it specifically disowns
>> > responsibility for worrying about whether Py_Initialize() and
>> > PyEval_InitThreads() have been called:
>> >
>> [snip quote]
>> 
>> This suggests that I should call PyEval_InitThreads() in
>> initreadline(), which seems daft.
>
> fwiw, Modules/_bsddb.c does exactly that.

Interesting.  The problem with readline.c doing this is that it gets
implicitly imported by the interpreter -- although only for
interactive sessions.  Maybe that's not that big a deal.  I'd still
prefer to change the functions (would updating the PEP be in order
here?  Obviously, I'd update the api documentation).

Cheers,
mwh

-- 
  It's relatively seldom that desire for sex is involved in 
  technology procurement decisions.  -- ESR at EuroPython 2002
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] threading (GilState) question

2005-04-09 Thread Bob Ippolito
On Apr 9, 2005, at 11:15 AM, Michael Hudson wrote:
"Gregory P. Smith" <[EMAIL PROTECTED]> writes:
Under "Limitations and Exclusions" it specifically disowns
responsibility for worrying about whether Py_Initialize() and
PyEval_InitThreads() have been called:
[snip quote]
This suggests that I should call PyEval_InitThreads() in
initreadline(), which seems daft.
fwiw, Modules/_bsddb.c does exactly that.
Interesting.  The problem with readline.c doing this is that it gets
implicitly imported by the interpreter -- although only for
interactive sessions.  Maybe that's not that big a deal.  I'd still
prefer to change the functions (would updating the PEP be in order
here?  Obviously, I'd update the api documentation).
Is there a good reason to *not* call PyEval_InitThreads when using a 
threaded Python?  Sounds like it would just be easier to implicitly 
call it during Py_Initialize some day.

-bob
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Re: Security capabilities in Python

2005-04-09 Thread Ka-Ping Yee
On Sat, 9 Apr 2005, Fredrik Lundh wrote:
> Ka-Ping wrote:
> > counter = Counter()
> > readonly_facet = facet(counter, ['value'])
> >
> > If i've done this correctly, it should be impossible to alter the
> > contents of the list or the counter, given only the immutable_facet
> > or the readonly_facet, after restrict() has been called.
>
> I'm probably missing something, but a straightforward reflection
> approach seems to work on my machine:

That's funny.  After i called restrict() Python didn't let me get im_self.

>>> restrict()
>>> readonly_facet.value
>
>>> readonly_facet.value.im_self
Traceback (most recent call last):
  File "", line 1, in ?
RuntimeError: restricted attribute
>>>

It doesn't matter if i make the facet before or after restrict().

>>> restrict()
>>> rf2 = facet(counter, ['value'])
>>> rf2.value
>
>>> rf2.value.im_self
Traceback (most recent call last):
  File "", line 1, in ?
RuntimeError: restricted attribute
>>>

I'm using

Python 2.3 (#1, Sep 13 2003, 00:49:11)
[GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin


-- ?!ng
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Security capabilities in Python

2005-04-09 Thread James Y Knight
On Apr 9, 2005, at 2:13 PM, Michael Hudson wrote:
The funniest I know is part of PyPy:
def extract_cell_content(c):
"""Get the value contained in a CPython 'cell', as read through
the func_closure of a function object."""
# yuk! this is all I could come up with that works in Python 2.2 
too
class X(object):
def __eq__(self, other):
self.other = other
x = X()
x_cell, = (lambda: x).func_closure
x_cell == c
return x.other

It would be unfortunate for PyPy (and IMHO, very un-pythonic) if this
process became impossible.
It would be quite fortunate if you didn't have to do all that, and cell 
just had a "value" attribute, though.

James
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Security capabilities in Python

2005-04-09 Thread Ka-Ping Yee
On Sat, 9 Apr 2005, Jp Calderone wrote:
>   Does using the gc module to bypass this security count?  If so:
>
> [EMAIL PROTECTED]:~$ python -i facet.py
> >>> import gc
> >>> c = readonly_facet.__getattr__.func_closure[1]
> >>> r = gc.get_referents(c)[0]
> >>> r.n = 'hax0r3d'
> >>> readonly_facet.value()
> 'hax0r3d'
> >>>

You can't get func_closure in restricted mode.  (Or at least, i can't,
using the Python included with Mac OS 10.3.8.)

>>> restrict()
>>> readonly_facet.__getattr__.func_closure
Traceback (most recent call last):
  File "", line 1, in ?
RuntimeError: restricted attribute
>>>

Even though this particular example doesn't work in restricted mode,
it's true that the gc module violates capability discipline, and you
would have to forbid its import.  In any real use case, you would have
to restrict imports anyway to prevent access to sys.modules or loading
of arbitrary binaries.

For a version that restricts imports, see:

http://zesty.ca/python/facet.py

Let me know if you figure out how to defeat that.

(This is a fun exercise, but with a potential purpose -- it would be
nice to have a coherent story on this for Python 3000, or maybe even
Python 2.x.)


-- ?!ng
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Security capabilities in Python

2005-04-09 Thread Ka-Ping Yee
On Sat, 9 Apr 2005, Michael Hudson wrote:
> The funniest I know is part of PyPy:
>
> def extract_cell_content(c):
> """Get the value contained in a CPython 'cell', as read through
> the func_closure of a function object."""
> # yuk! this is all I could come up with that works in Python 2.2 too
> class X(object):
> def __eq__(self, other):
> self.other = other
> x = X()
> x_cell, = (lambda: x).func_closure
> x_cell == c
> return x.other

That's pretty amazing.

> It would be unfortunate for PyPy (and IMHO, very un-pythonic) if this
> process became impossible.

Not a problem.  func_closure is already a restricted attribute.

IMHO, the clean way to do this is to provide a built-in function to
get the cell content in a more direct and reliable way, and then
put that in a separate module with other interpreter hacks.

That both makes it easier to do stuff like this, and easier to prevent
it simply by forbidding import of that module.


-- ?!ng
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Security capabilities in Python

2005-04-09 Thread Samuele Pedroni
Ka-Ping Yee wrote:
On Sat, 9 Apr 2005, Jp Calderone wrote:
 Does using the gc module to bypass this security count?  If so:
   [EMAIL PROTECTED]:~$ python -i facet.py
   >>> import gc
   >>> c = readonly_facet.__getattr__.func_closure[1]
   >>> r = gc.get_referents(c)[0]
   >>> r.n = 'hax0r3d'
   >>> readonly_facet.value()
   'hax0r3d'
   >>>

You can't get func_closure in restricted mode.  (Or at least, i can't,
using the Python included with Mac OS 10.3.8.)
>>> restrict()
>>> readonly_facet.__getattr__.func_closure
Traceback (most recent call last):
  File "", line 1, in ?
RuntimeError: restricted attribute
>>>
Even though this particular example doesn't work in restricted mode,
it's true that the gc module violates capability discipline, and you
would have to forbid its import.  In any real use case, you would have
to restrict imports anyway to prevent access to sys.modules or loading
of arbitrary binaries.
For a version that restricts imports, see:
http://zesty.ca/python/facet.py
Let me know if you figure out how to defeat that.
you should probably search the list and look at my old attacks against
restricted execution, there's reason why is not much supported anymore.
One can still try to use it but needs to be extremely careful or use C 
defined proxies... etc.

(This is a fun exercise, but with a potential purpose -- it would be
nice to have a coherent story on this for Python 3000, or maybe even
Python 2.x.)
-- ?!ng
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/pedronis%40strakt.com
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Security capabilities in Python

2005-04-09 Thread James Y Knight
On Apr 9, 2005, at 5:37 PM, Ka-Ping Yee wrote:
Let me know if you figure out how to defeat that.
You can protect against this, too, but it does show that it's *really* 
hard to get restricting code right...I'm of the opinion that it's not 
really worth it -- you should just use OS protections.

untrusted_module.py:
class foostr(str):
 def __eq__(self, other):
  return True
def have_at_it(immutable_facet, readonly_facet):
  getattr(immutable_facet, foostr('append'))(5)
  print immutable_facet
James
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Security capabilities in Python

2005-04-09 Thread Ka-Ping Yee
On Sat, 9 Apr 2005, James Y Knight wrote:
> You can protect against this, too, but it does show that it's *really*
> hard to get restricting code right...

Good point.  If you can't trust ==, then you're hosed.

> I'm of the opinion that it's not
> really worth it -- you should just use OS protections.

This i disagree with, however.  OS protections are a few orders of
magnitude more heavyweight and vastly more error-prone than using a
language with simple, clear semantics.

Predictable code behaviour is good.


-- ?!ng
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com