VYPR
Medium severity5.9NVD Advisory· Published Sep 25, 2017· Updated May 13, 2026

CVE-2015-7315

CVE-2015-7315

Description

Plone 3.3.0 through 3.3.6, 4.0.0 through 4.0.10, 4.1.0 through 4.1.6, 4.2.0 through 4.2.7, 4.3.0 through 4.3.6, and 5.0rc1 allows remote attackers to add a new member to a Plone site with registration enabled, without acknowledgment of site administrator.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
Products.CMFPlonePyPI
>= 3.3.0, < 4.3.74.3.7
Products.CMFPlonePyPI
>= 5.0a1, < 5.0rc25.0rc2
PlonePyPI
>= 3.3, <= 3.3.6
PlonePyPI
>= 4.0a1, <= 4.0.10
PlonePyPI
>= 4.1a1, <= 4.1.6
PlonePyPI
>= 4.2a1, <= 4.2.7
PlonePyPI
>= 4.3a1, <= 4.3.6

Patches

3
9f0111f85cd1

Apply hotfixes from https://pypi.python.org/pypi/Products.PloneHotfix20150910

https://github.com/plone/Products.CMFPlonevangheemSep 10, 2015via ghsa
7 files changed · +65 3
  • docs/CHANGES.rst+3 0 modified
    @@ -8,6 +8,9 @@ Changelog
     4.3.7 (unreleased)
     ------------------
     
    +- Apply hotfixes from https://pypi.python.org/pypi/Products.PloneHotfix20150910
    +  [vangheem]
    +
     - Do not throw a 404 on site root RSS feeds
       [vangheem]
     
    
  • Products/CMFPlone/patches/addMember.py+8 0 added
    @@ -0,0 +1,8 @@
    +try:
    +    from Products.CMFPlone import patches  # noqa
    +except ImportError:
    +    pass
    +
    +from Products.CMFCore.RegistrationTool import RegistrationTool
    +if hasattr(RegistrationTool.addMember.im_func, '__doc__'):
    +    del RegistrationTool.addMember.im_func.__doc__
    
  • Products/CMFPlone/patches/__init__.py+8 0 modified
    @@ -24,3 +24,11 @@
     
     import sendmail
     sendmail.applyPatches()
    +
    +try:
    +    # kupu may not be installed
    +    import kupu
    +except ImportError:
    +    pass
    +
    +import addMember
    \ No newline at end of file
    
  • Products/CMFPlone/patches/kupu.py+22 0 added
    @@ -0,0 +1,22 @@
    +#####################
    +# Newly created sites
    +
    +from AccessControl.Permission import _registeredPermissions
    +from AccessControl.Permission import ApplicationDefaultPermissions
    +from AccessControl.Permission import pname
    +from Products.kupu.plone import permissions
    +
    +
    +mangled = pname(permissions.ManageLibraries)
    +if hasattr(ApplicationDefaultPermissions, mangled):
    +    delattr(ApplicationDefaultPermissions, mangled)
    +
    +
    +if permissions.ManageLibraries in _registeredPermissions:
    +    del _registeredPermissions[permissions.ManageLibraries]
    +
    +
    +permissions.setDefaultRoles(
    +    permissions.ManageLibraries,
    +    ('Manager', 'Site Administrator',)
    +    )
    
  • Products/CMFPlone/tests/testCSRFProtection.py+12 3 modified
    @@ -63,9 +63,18 @@ def test_PloneTool_renameObjectsByPaths(self):
             self.assertTrue(self.portal.get('foo', None))
     
         def test_RegistrationTool_addMember(self):
    -        self.checkAuthenticator(
    -            '/portal_registration/addMember',
    -            'id=john&password=y0d4Wg')
    +        # self.checkAuthenticator(
    +        #    '/portal_registration/addMember',
    +        #    'id=john&password=y0d4Wg')
    +        # instead of authenticator, with latest patch, addMember should not
    +        # be published
    +        path = '/portal_registration/addMember'
    +        path = '/' + self.portal.absolute_url(relative=True) + path
    +        query = 'id=john&password=y0d4Wg'
    +        data = StringIO(query)
    +        response = self.publish(path=path, env={},
    +                                request_method='POST', stdin=data)
    +        self.assertEqual(response.getStatus(), 404)
     
         def test_RegistrationTool_editMember(self):
             self.checkAuthenticator(
    
  • Products/CMFPlone/tests/testURLTool.py+9 0 modified
    @@ -96,3 +96,12 @@ def test_isURLInPortalExternal(self):
             self.assertFalse(iURLiP('http://external4/other'))
             self.assertFalse(iURLiP('http://external5'))
             self.assertFalse(iURLiP('http://external11'))
    +
    +    def test_script_tag_url_not_in_portal(self):
    +        self.assertFalse(self.portal.portal_url.isURLInPortal('<script>alert("hi");</script>'))
    +        self.assertFalse(
    +            self.portal.portal_url.isURLInPortal('%3Cscript%3Ealert(%22hi%22)%3B%3C%2Fscript%3E'))
    +
    +    def test_inline_url_not_in_portal(self):
    +        self.assertFalse(self.portal.portal_url.isURLInPortal('javascript%3Aalert(3)'))
    +        self.assertFalse(self.portal.portal_url.isURLInPortal('javascript:alert(3)'))
    
  • Products/CMFPlone/URLTool.py+3 0 modified
    @@ -30,6 +30,9 @@ def isURLInPortal(self, url, context=None):
             """
             # sanitize url
             url = re.sub('^[\x00-\x20]+', '', url).strip()
    +        if ('<script' in url or '%3Cscript' in url or 'javascript:' in url or
    +                'javascript%3A' in url):
    +            return False
     
             p_url = self()
     
    
1845b0a92312

Apply isURLInPortal fix from https://pypi.python.org/pypi/Products.PloneHotfix20150910

https://github.com/plone/Products.CMFPlonevangheemSep 10, 2015via ghsa
3 files changed · +15 0
  • CHANGES.rst+3 0 modified
    @@ -8,6 +8,9 @@ Changelog
     5.0rc2 (unreleased)
     -------------------
     
    +- Apply isURLInPortal fix from https://pypi.python.org/pypi/Products.PloneHotfix20150910
    +  [vangheem]
    +
     - Do not bother additional CRSF protection for addMember since all public
       users get same CSRF token and the method should be unpublished.
       See https://pypi.python.org/pypi/Products.PloneHotfix20150910
    
  • Products/CMFPlone/tests/testURLTool.py+9 0 modified
    @@ -96,3 +96,12 @@ def test_isURLInPortalExternal(self):
             self.assertFalse(iURLiP('http://external4/other'))
             self.assertFalse(iURLiP('http://external5'))
             self.assertFalse(iURLiP('http://external11'))
    +
    +    def test_script_tag_url_not_in_portal(self):
    +        self.assertFalse(self.portal.portal_url.isURLInPortal('<script>alert("hi");</script>'))
    +        self.assertFalse(
    +            self.portal.portal_url.isURLInPortal('%3Cscript%3Ealert(%22hi%22)%3B%3C%2Fscript%3E'))
    +
    +    def test_inline_url_not_in_portal(self):
    +        self.assertFalse(self.portal.portal_url.isURLInPortal('javascript%3Aalert(3)'))
    +        self.assertFalse(self.portal.portal_url.isURLInPortal('javascript:alert(3)'))
    
  • Products/CMFPlone/URLTool.py+3 0 modified
    @@ -30,6 +30,9 @@ def isURLInPortal(self, url, context=None):
             """
             # sanitize url
             url = re.sub('^[\x00-\x20]+', '', url).strip()
    +        if ('<script' in url or '%3Cscript' in url or 'javascript:' in url or
    +                'javascript%3A' in url):
    +            return False
     
             p_url = self()
     
    
e1d981bfa14b

Make sure RegistrationTool.addMember is not published

2 files changed · +13 9
  • Products/CMFCore/CHANGES.txt+2 1 modified
    @@ -4,7 +4,8 @@ Products.CMFCore Changelog
     2.3.1 (unreleased)
     ------------------
     
    -- Nothing changed yet.
    +- Make sure RegistrationTool.addMember is not published
    +  [vangheem]
     
     
     2.3.0 (2015-02-20)
    
  • Products/CMFCore/RegistrationTool.py+11 8 modified
    @@ -132,14 +132,17 @@ def generatePassword(self):
         @postonly
         def addMember(self, id, password, roles=('Member',), domains='',
                       properties=None, REQUEST=None):
    -        '''Creates a PortalMember and returns it. The properties argument
    -        can be a mapping with additional member properties. Raises an
    -        exception if the given id already exists, the password does not
    -        comply with the policy in effect, or the authenticated user is not
    -        allowed to grant one of the roles listed (where Member is a special
    -        role that can always be granted); these conditions should be
    -        detected before the fact so that a cleaner message can be printed.
    -        '''
    +        # XXX Do not make this a normal method comment. Doing so makes
    +        # this method publishable
    +
    +        # Creates a PortalMember and returns it. The properties argument
    +        # can be a mapping with additional member properties. Raises an
    +        # exception if the given id already exists, the password does not
    +        # comply with the policy in effect, or the authenticated user is not
    +        # allowed to grant one of the roles listed (where Member is a special
    +        # role that can always be granted); these conditions should be
    +        # detected before the fact so that a cleaner message can be printed.
    +
             if not self.isMemberIdAllowed(id):
                 raise ValueError(_(u'The login name you selected is already in '
                                    u'use or is not valid. Please choose another.'))
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

10

News mentions

0

No linked articles in our index yet.