rexec question

Jeremy Hylton jeremy at cnri.reston.va.us
Fri Aug 6 15:22:48 EDT 1999


[Just rememberer that the basic of using rexec are explained in Andrew
Kuchling's howto: http://www.python.org/doc/howto/rexec/rexec.html]

>>>>> "RD" == Ralf Doering <ralf.doering at Prakinf.TU-Ilmenau.DE> writes:

  [near miss in my previous attempt to answer the question]

  RD> Thanks for your response. Do yo see any way to get an *already*
  RD> defined object into the namespace of rexec?  The object we talk
  RD> about will be unpickled from a byte stream and has to be
  RD> executed in the restricted environment.  So, how can I get this
  RD> unpickled object into RExec and run it in this namespace?  Seems
  RD> that I`m a little confused about the namespaces and how to
  RD> define entrys in RExec`s namespace ...

I should have answered this question from the outset.  The restricted
execution environment is definitely more interesting when there are
objects defined in the controlling environment that are all accessible 
in the restricted environment.

There is no direct way to add a name binding to the restricted
execution environment.  You need to modify one of the modules that
exists in rexec, typically its __main__.

Here's a simple approach that would work:

class RExecEx(rexec.RExec):
    """Adds method for setting attribute in rexec environment"""
    def setattr(self, name, value, bastion=1):
        if bastion:
            value = Bastion.Bastion(value)
        setattr(self.modules['__main__'], name, value)

In most cases, you want to pass a Bastion to the untrusted code rather 
than passing the object directly.  The howto and the Bastion module
documentation explain this.

I've included a short script that illustrates the damage the untrusted 
code can do if you don't use a bastion.

Jeremy



import rexec
import Bastion 

class Foo:
    _priveleged = 12
    
    def bar(self):
        return self._priveleged

spam = Foo()

untrusted_code = """print "Initial value:", spam.bar()
print "Attempting to read privleged attribute:",
try:
    x = spam._priveleged
    print "succeeded"
except AttributeError:
    print "failed"
    pass
print "Attempting to modify object:",
spam._priveleged = 15
if spam.bar() == 15:
    print "internally modified",
else:
    print "internally unmodified",
if spam._priveleged == 15:
    print "externally modified"
else:
    print "externally unmodified"
print "Final value:", spam.bar()
"""

renv = rexec.RExec()

print "Running user code with direct access to object"
setattr(renv.modules['__main__'], 'spam', spam)
renv.r_exec(untrusted_code)
print "Value outside rexec:", spam.bar()
print

spam = Foo()
print "Running user code with access through Bastion"
setattr(renv.modules['__main__'], 'spam', Bastion.Bastion(spam))
renv.r_exec(untrusted_code)
print "Value outside rexec:", spam.bar()




More information about the Python-list mailing list