[Zope-dev] restrictedTraverse() security problem

Terry Hancock hancock@anansispaceworks.com
Tue, 6 May 2003 21:03:24 -0700


Thanks for the responses, but so far I'm still not there... :-(

Oh, and BTW, I am *not* writing a replacement acl_user UserFolder,
the name is an unfortunate name collision -- I probably need to
change to "UserHomeFolder" or something, as it is more analogous
to a user's home directory than to an authentication record. Sorry
for any confusion that might've caused.

On Tuesday 06 May 2003 10:48 am, Clemens Robbenhaar wrote:
> Starting Zope with the envoronment variable:
> 
>  ZOPE_SECURITY_POLICY=PYTHON
> 
> should give a better traceback -- currently some code is hidden from the
> traceback, as it is implemented as a C extension.
> 
>  Maybe Shane's VerboseSecurity does tell you more? I found it quite
> useful (the above hint is actually from the readme of that product).
> http://hathaway.freezope.org/Software/VerboseSecurity

Oddly, it doesn't make any difference in the traceback. I still
get the same error message.  I'm pretty sure the environment
variable worked, because it didn't on the 1st try and I got a
log message from VerboseSecurity about it, then corrected it,
and now I don't get the log message. Presumeably this means
VerboseSecurity was happy with the monkey-patching
results.

But no more information appears -- when accessing this object
*using restrictedTraverse()* I get the same message:
"""
Error Type: Unauthorized
Error Value: You are not allowed to access terry in this context
"""
which occurs at:
File /usr/local/narya/z2.5.1/lib/python/OFS/Traversable.py, line 130, in unrestrictedTraverse
where I find:
"""
                    if restricted:
                        container = N
                        if has(o, 'im_self'):
                            container = o.im_self
                        elif (has(get(object, 'aq_base', object), name)
                              and get(object, name) == o):
                            container = object
                        if (not securityManager.validate(object,
                                                         container, name, o)):
                            raise Unauthorized, name
"""

I also found a nice example of how python *can* be obfuscated if
you try hard enough:
"""
        get=getattr
        has=hasattr
"""
(Whoever you are, shame on you! ;-D)

HOWEVER, after some fiddling, I got my object to publish when
called by URL:

http://my_site/Home/terry

To achieve this, I changed my "UserPB" class to inherit
from just "Acquisition.Explicit" and "Traversable", and I
had to define "getId" and "index_html" methods, which I
didn't have defined before.

Now, obviously, it's not too logical (at least from a security
perspective) for my object to be acquirable through URL, but
not by restrictedTraverse(). What could do that?  The only
difference I know about is the "fake REQUEST" that 
restrictedTraverse() passes to __bobo_traverse__, which I
discovered the last time I used it.

I did trace the validate method down to being a method of
"_policy" defined in the extension module "cAccessControl.c", 
although the code in that module is pretty much opaque to
me (yes I know C, but it's been awhile, and it's obviously fairly
complex in there).

My next step is to hack Traversable.py and raise an exception
that tells me what arguments validate() gets -- maybe that'll
help.

Thanks for any ideas.  Part of my fascination with this problem
is that I feel I will learn something about Zope's object
publishing here.

Terry

--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks  http://www.anansispaceworks.com