From b42dd4badf803bb9fb71ac34cd9cb0c249262f2c Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Fri, 30 Jul 2021 09:25:07 +0200 Subject: [PATCH] Merge pull request from GHSA-qcx9-j53g-ccgf --- CHANGES.rst | 3 ++- src/AccessControl/ZopeGuards.py | 8 ++++++++ src/AccessControl/tests/testZopeSecurityPolicy.py | 13 +++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index b6b527e..3fd47fe 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,7 +6,8 @@ For changes before version 3.0, see ``HISTORY.rst``. 5.1 (unreleased) ---------------- -- Nothing changed yet. +- Fix a remote code execution issue by preventing access to + ``string.Formatter`` from restricted code. 5.0 (2020-10-07) diff --git a/src/AccessControl/ZopeGuards.py b/src/AccessControl/ZopeGuards.py index 1ea2ca2..57add77 100644 --- a/src/AccessControl/ZopeGuards.py +++ b/src/AccessControl/ZopeGuards.py @@ -30,6 +30,7 @@ from RestrictedPython.Utilities import utility_builtins from zExceptions import Unauthorized +from AccessControl.SecurityInfo import ModuleSecurityInfo from AccessControl.SecurityInfo import secureModule from AccessControl.SecurityManagement import getSecurityManager from AccessControl.SimpleObjectPolicies import ContainerAssertions @@ -57,6 +58,13 @@ math.__allow_access_to_unprotected_subobjects__ = 1 random.__allow_access_to_unprotected_subobjects__ = 1 +# Mark some unprotected module attributes as private, these should not be +# used in untrusted Python code such as Scripts (Python) +string_modsec = ModuleSecurityInfo('string') +for name in ('Formatter', 'Template'): + string_modsec.declarePrivate(name) # NOQA: D001 +secureModule('string') + # AccessControl.Implementation inserts these names into this module as # module globals: aq_validate, guarded_getattr diff --git a/src/AccessControl/tests/testZopeSecurityPolicy.py b/src/AccessControl/tests/testZopeSecurityPolicy.py index c2a0063..c81face 100644 --- a/src/AccessControl/tests/testZopeSecurityPolicy.py +++ b/src/AccessControl/tests/testZopeSecurityPolicy.py @@ -278,6 +278,19 @@ def testAccessToSimpleContainer(self): c.attr = PublicMethod() self.assertPolicyAllows(c, 'attr') + def testAccessToStringModule(self): + # The string module is available to restricted code and its members are + # explicitly allowed via a + # ``__allow_access_to_unprotected_subobjects__`` declaration. However, + # a few classes are exempted and declared private, they can indirectly + # provide uncontrolled access to system libraries from within + # restricted code. + import string + + self.assertPolicyAllows(string, 'printable') + self.assertPolicyDenies(string, 'Formatter') + self.assertPolicyDenies(string, 'Template') + def testUnicodeAttributeLookups(self): item = self.item r_item = self.a.r_item