Permalink
Browse files

Get correctly the current frame

This change fixes a security issue: __builtins__ was not readonly when
execute() was used!

Bug found by 雪狼 <kurskk141 AT gmail.com>.
  • Loading branch information...
1 parent 49cf81c commit c6def352c131302a97ec82df72ecabd82133fc85 @vstinner committed Dec 26, 2012
Showing with 22 additions and 6 deletions.
  1. +2 −0 ChangeLog
  2. +2 −2 run_tests.sh
  3. +2 −2 sandbox/builtins.py
  4. +2 −1 sandbox/config.py
  5. +7 −0 sandbox/sandbox_class.py
  6. +7 −1 sandbox/test/test_builtins.py
View
@@ -3,6 +3,8 @@ Version 1.6
FIXME: repair ClearImport() protection, or remove it
+ * SECURITY FIX: __builtins__ is now readonly when execute() is used.
+ It was only readonly when call() was used.
* Execute code in a subprocess using the Python subprocess module
or os.fork()
* Add --disable-subprocess command line option
View
@@ -6,7 +6,7 @@ rm -rf build
TESTED=""
for PYVER in 2.5 2.6 2.7; do
PYTHON=python$PYVER
- $PYTHON -c pass || continue
+ $PYTHON -c pass 1>/dev/null 2>&1 || continue
$PYTHON setup.py build
PYTHONPATH=$(cd build/lib.*-$PYVER/; pwd) $PYTHON tests.py --raise
if [ ! -z "$TESTED" ]; then
@@ -16,4 +16,4 @@ for PYVER in 2.5 2.6 2.7; do
fi
done
-echo "pysandbox tesed on Python $TESTED"
+echo "pysandbox tested on Python $TESTED"
View
@@ -1,7 +1,7 @@
from __future__ import absolute_import
import __builtin__ as BUILTINS_MODULE
from types import FrameType
-from sys import _getframe, version_info
+from sys import version_info
import sys
from sandbox import SandboxError, HAVE_CSANDBOX
@@ -31,7 +31,7 @@ def enable(self, sandbox):
del self.builtin_dict[key]
# Get frame builtins
- self.frame = _getframe(2)
+ self.frame = sandbox.frame
self.builtins_dict = self.get_frame_builtins(self.frame)
# Get module list
View
@@ -484,6 +484,7 @@ def fromOptparseOptions(options):
if options.allow_path:
for path in options.allow_path:
config.allowPath(path)
- config.timeout = options.timeout
+ if config.use_subprocess:
+ config.timeout = options.timeout
return config
View
@@ -1,6 +1,7 @@
from __future__ import with_statement, absolute_import
from .config import SandboxConfig
from .proxy import proxy
+from sys import _getframe
def keywordsProxy(keywords):
# Dont proxy keys because function keywords must be strings
@@ -28,15 +29,19 @@ def __init__(self, config=None):
self.protections = [protection() for protection in self.PROTECTIONS]
self.execute_subprocess = None
self.call_fork = None
+ # set during enable()
+ self.frame = None
def _call(self, func, args, kw):
"""
Call a function in the sandbox.
"""
args = proxy(args)
kw = keywordsProxy(kw)
+ self.frame = _getframe()
for protection in self.protections:
protection.enable(self)
+ self.frame = None
try:
return func(*args, **kw)
finally:
@@ -63,8 +68,10 @@ def _execute(self, code, globals, locals):
"""
if globals is None:
globals = {}
+ self.frame = _getframe()
for protection in self.protections:
protection.enable(self)
+ self.frame = None
try:
_call_exec(code, globals, locals)
finally:
@@ -2,7 +2,7 @@
from sandbox.test import SkipTest, createSandbox, createSandboxConfig
from sys import version_info
-def test_exec_builtins():
+def test_call_exec_builtins():
def check_builtins_type():
result = []
exec "result.append(type(__builtins__))" in {'result': result}
@@ -14,6 +14,12 @@ def check_builtins_type():
config._builtins_whitelist.add('compile')
Sandbox(config).call(check_builtins_type)
+def test_exec_builtins():
+ config = createSandboxConfig()
+ Sandbox(config).execute("""
+assert type(__builtins__) != dict
+ """.strip())
+
def test_builtins_setitem():
def builtins_superglobal():
if isinstance(__builtins__, dict):

0 comments on commit c6def35

Please sign in to comment.