mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
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). I'll apply this to 2.2 and 2.1 too.
This commit is contained in:
parent
9788384d02
commit
59b2a74c75
2 changed files with 23 additions and 1 deletions
|
@ -211,6 +211,18 @@ environment. The value for \class{RExec} is \code{('ps1', 'ps2',
|
||||||
'copyright', 'version', 'platform', 'exit', 'maxint')}.
|
'copyright', 'version', 'platform', 'exit', 'maxint')}.
|
||||||
\end{memberdesc}
|
\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}
|
\subsection{An example}
|
||||||
|
|
||||||
|
|
12
Lib/rexec.py
12
Lib/rexec.py
|
@ -22,6 +22,7 @@ import sys
|
||||||
import __builtin__
|
import __builtin__
|
||||||
import os
|
import os
|
||||||
import ihooks
|
import ihooks
|
||||||
|
import imp
|
||||||
|
|
||||||
__all__ = ["RExec"]
|
__all__ = ["RExec"]
|
||||||
|
|
||||||
|
@ -83,6 +84,9 @@ class RHooks(ihooks.Hooks):
|
||||||
# Called by RExec instance to complete initialization
|
# Called by RExec instance to complete initialization
|
||||||
self.rexec = rexec
|
self.rexec = rexec
|
||||||
|
|
||||||
|
def get_suffixes(self):
|
||||||
|
return self.rexec.get_suffixes()
|
||||||
|
|
||||||
def is_builtin(self, name):
|
def is_builtin(self, name):
|
||||||
return self.rexec.is_builtin(name)
|
return self.rexec.is_builtin(name)
|
||||||
|
|
||||||
|
@ -144,6 +148,8 @@ class RExec(ihooks._Verbose):
|
||||||
|
|
||||||
nok_builtin_names = ('open', 'file', 'reload', '__import__')
|
nok_builtin_names = ('open', 'file', 'reload', '__import__')
|
||||||
|
|
||||||
|
ok_file_types = (imp.C_EXTENSION, imp.PY_SOURCE)
|
||||||
|
|
||||||
def __init__(self, hooks = None, verbose = 0):
|
def __init__(self, hooks = None, verbose = 0):
|
||||||
"""Returns an instance of the RExec class.
|
"""Returns an instance of the RExec class.
|
||||||
|
|
||||||
|
@ -203,7 +209,6 @@ class RExec(ihooks._Verbose):
|
||||||
if sys.modules.has_key(name):
|
if sys.modules.has_key(name):
|
||||||
src = sys.modules[name]
|
src = sys.modules[name]
|
||||||
else:
|
else:
|
||||||
import imp
|
|
||||||
src = imp.load_dynamic(name, filename, file)
|
src = imp.load_dynamic(name, filename, file)
|
||||||
dst = self.copy_except(src, [])
|
dst = self.copy_except(src, [])
|
||||||
return dst
|
return dst
|
||||||
|
@ -214,6 +219,11 @@ class RExec(ihooks._Verbose):
|
||||||
|
|
||||||
# Helpers for RHooks
|
# 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):
|
def is_builtin(self, mname):
|
||||||
return mname in self.ok_builtin_modules
|
return mname in self.ok_builtin_modules
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue