This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: rexec: potential security hole
Type: Stage:
Components: Library (Lib) Versions:
process
Status: closed Resolution: accepted
Dependencies: Superseder:
Assigned To: gvanrossum Nosy List: arigo, gvanrossum, loewis
Priority: normal Keywords:

Created on 2002-03-22 15:29 by arigo, last changed 2022-04-10 16:05 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
crack1.py arigo, 2002-03-22 15:29 Potential security hole
rexec-diff.txt arigo, 2002-03-25 14:06 Security patch
rexec-diff-2.txt gvanrossum, 2002-03-25 17:02 Context diff, and using a list comprehension
rexec-doc-diff.txt arigo, 2002-04-07 10:08 Documentation patch
Messages (10)
msg9904 - (view) Author: Armin Rigo (arigo) * (Python committer) Date: 2002-03-22 15:29
The documentation of the restricted execution module, 
rexec, should make it clear that it is dangerous to 
allow the restricted code write into a directory that 
is included in sys.path. Indeed, I suspect that is it 
common to allow restricted code to write in the 
current directory (e.g. after a chdir() to a directory 
that contains only the files we want the restricted 
code to work on). But '' is in sys.path by default.

Attached is a script that uses this to perform the 
equivalent of an unmarshal of a code object (which is 
forbidden in restricted mode -- although it is clear 
to me why, it might not be obvious to someone not used 
to Python's internals and should be mentionned 
somewhere). The attached script writes and then import 
a .pyc file that defines a function whose bogus code 
(at least on 32-bit Unix machines with Python 2.2-2.3) 
returns the frame of the caller. This lets the 
restricted code access the original builtins.
msg9905 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2002-03-22 17:35
Logged In: YES 
user_id=21627

Isn't that a bug in LOAD_FAST?
msg9906 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2002-03-22 17:50
Logged In: YES 
user_id=6380

Martin: I don't think so. Adding range check to the VM would
slow it down considerably, especially since it affects all
the "fast" opcodes. In order to make the VM totally robust,
you would also have to fix the various push and pop opcodes
(or the macros) to check for stack overflow and underflow as
well. For better or for worse, the assumption of the VM is
that the compiler generates "perfect" bytecode, and we do
*not* have a bytecode verifier like Java. For trusted code,
I don't mind. For untrusted code, rexec should disallow any
manipulation of code objects. 

Armin has found a real security hole -- fortunately the
default is not to allow writing at all, but in fact, having
any writable directories at all opens up the hole, since
restricted code can changes its own sys.path!!!
msg9907 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2002-03-22 17:53
Logged In: YES 
user_id=6380

Note that rexec as shipped doesn't allow writing any files,
so it's only a security hole in apps that modify open() to
allow writing in some directory. I guess the rexec import
code could be made aware of which directories are writable
and skip those if they appear on sys.path.
msg9908 - (view) Author: Armin Rigo (arigo) * (Python committer) Date: 2002-03-24 15:00
Logged In: YES 
user_id=4771

This could be defeated by a double attack: one rexec'ed 
code leaves a .pyc file in a temporary directory, and later 
another rexec'ed code in a fully read-only environment 
imports it. Or the buggy .pyc file was put there with some 
other tool (e.g. ftp to /incoming).

To be on the safe side one could completely disable loading 
from .pyc files. This has the advantage of automatically 
fixing the problem in all of the existing applications. I 
don't know if this would be a serious performance problem --
 rexec'ed code might generally don't import too much 
standard modules itself anyway. One could later add 
a "safe_path" list that lists the directories from which 
loading .pyc files is considered to be safe.

Note that the default hooks are such that no .pyc files are 
ever *written* by imports from rexec'ed code. One can thus 
guess that no existing rexec'ed code relies on .pyc file 
performance for anything but the standard library.
msg9909 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2002-03-24 21:41
Logged In: YES 
user_id=6380

Good points, Armin. I guess it's unlikely to have a site
that allows limited read-write for some rexec clients and
read-only for others, but not impossible.

Could I twist your arm and ask for a patch?
msg9910 - (view) Author: Armin Rigo (arigo) * (Python committer) Date: 2002-03-25 14:06
Logged In: YES 
user_id=4771

Ok. This patch prevents the default module loader hooks 
used by RExec to locate any PY_COMPILED file. I added an 
ok_file_types tuple to RExec that lists the file types we 
should allow loading from -- currently only C_EXTENSION and 
PY_SOURCE.

I can add the above comment to the docs as well if the 
patch is acceptable.
msg9911 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2002-03-25 17:02
Logged In: YES 
user_id=6380

Thanks. I'll have to think about this some more. I guess
it's easy enough to document that one can get performance
back by adding imp.PY_COMPILED to ok_file_types.

I've added a context diff (1) to make your patch less
suscpetible to going stale (2) to use a list comprehension
instead of filter().
msg9912 - (view) Author: Armin Rigo (arigo) * (Python committer) Date: 2002-04-07 10:08
Logged In: YES 
user_id=4771

I uploaded a patch for the documentation.
msg9913 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2002-05-31 21:26
Logged In: YES 
user_id=6380

I've checked this in now, in 2.1, 2.2 and 2.3.  Thanks!
History
Date User Action Args
2022-04-10 16:05:08adminsetgithub: 36312
2002-03-22 15:29:06arigocreate