diff options
author | Guido van Rossum <guido@python.org> | 2002-05-31 21:19:53 +0000 |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2002-05-31 21:19:53 +0000 |
commit | 4d4a642a43c219417656f72f2ff650b96bf47917 (patch) | |
tree | d25cc5f269a4bb859114ba4635cf610c21812e94 | |
parent | c1976cbebd6b129ab13640e296a9e8690f034f8c (diff) | |
download | cpython-4d4a642a43c219417656f72f2ff650b96bf47917.tar.gz |
Backport to 2.1.x:
SF bug 533625 (Armin Rigo). rexec: potential security hole
If a rexec instance allows writing in the current directory (a common
thing to do), there's a way to execute bogus bytecode. Fix this by
not allowing imports from .pyc files (in a way that allows a site to
configure things so that .pyc files *are* allowed, if writing is not
allowed).
-rw-r--r-- | Doc/lib/librexec.tex | 12 | ||||
-rw-r--r-- | Lib/rexec.py | 12 |
2 files changed, 23 insertions, 1 deletions
diff --git a/Doc/lib/librexec.tex b/Doc/lib/librexec.tex index 1f56a984b8..f00ddfcfc0 100644 --- a/Doc/lib/librexec.tex +++ b/Doc/lib/librexec.tex @@ -210,6 +210,18 @@ environment. The value for \class{RExec} is \code{('ps1', 'ps2', 'copyright', 'version', 'platform', 'exit', 'maxint')}. \end{memberdesc} +\begin{memberdesc}{ok_file_types} +Contains the file types from which modules are allowed to be loaded. +Each file type is an integer constant defined in the \refmodule{imp} module. +The meaningful values are \constant{PY_SOURCE}, \constant{PY_COMPILED}, and +\constant{C_EXTENSION}. The value for \class{RExec} is \code{(C_EXTENSION, +PY_SOURCE)}. Adding \constant{PY_COMPILED} in subclasses is not recommended; +an attacker could exit the restricted execution mode by putting a forged +byte-compiled file (\file{.pyc}) anywhere in your file system, for example +by writing it to \file{/tmp} or uploading it to the \file{/incoming} +directory of your public FTP server. +\end{memberdesc} + \subsection{An example} diff --git a/Lib/rexec.py b/Lib/rexec.py index cb397ce75c..ccc53df03a 100644 --- a/Lib/rexec.py +++ b/Lib/rexec.py @@ -22,6 +22,7 @@ import sys import __builtin__ import os import ihooks +import imp __all__ = ["RExec"] @@ -83,6 +84,9 @@ class RHooks(ihooks.Hooks): # Called by RExec instance to complete initialization self.rexec = rexec + def get_suffixes(self): + return self.rexec.get_suffixes() + def is_builtin(self, name): return self.rexec.is_builtin(name) @@ -134,6 +138,8 @@ class RExec(ihooks._Verbose): nok_builtin_names = ('open', 'reload', '__import__') + ok_file_types = (imp.C_EXTENSION, imp.PY_SOURCE) + def __init__(self, hooks = None, verbose = 0): ihooks._Verbose.__init__(self, verbose) # XXX There's a circular reference here: @@ -169,7 +175,6 @@ class RExec(ihooks._Verbose): if sys.modules.has_key(name): src = sys.modules[name] else: - import imp src = imp.load_dynamic(name, filename, file) dst = self.copy_except(src, []) return dst @@ -180,6 +185,11 @@ class RExec(ihooks._Verbose): # Helpers for RHooks + def get_suffixes(self): + return [item # (suff, mode, type) + for item in imp.get_suffixes() + if item[2] in self.ok_file_types] + def is_builtin(self, mname): return mname in self.ok_builtin_modules |