REMOTE_USER Security Issue
My people want to adopt a single sign-on system for web applications that is based on the REMOTE_USER environment variable. I have tried out RemoteUserFolder and also adapted exUserFolder to work similarly. My problem is that I figured out how a user who has permission to create python scripts (might work with dtml and page templates too) could access otherwise forbidden content by making calls that pretend to come from another user. Has any one else come across this problem and devised a solution, either in software or organisation? Problem verified with Zope 2.9.2 and latest RemoteUserFolder. Cliff
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Cliff Ford wrote:
My people want to adopt a single sign-on system for web applications that is based on the REMOTE_USER environment variable. I have tried out RemoteUserFolder and also adapted exUserFolder to work similarly.
My problem is that I figured out how a user who has permission to create python scripts (might work with dtml and page templates too) could access otherwise forbidden content by making calls that pretend to come from another user. Has any one else come across this problem and devised a solution, either in software or organisation?
Problem verified with Zope 2.9.2 and latest RemoteUserFolder
User folders who care need to look at the request's 'environ' dict, e.g.:: remote_user = request.environ['REMOTE_USER'] # not hackable rather than the default one where untrusted code can scribble:: remote_user = request['REMOTE_USER'] # hackable Tres. - -- =================================================================== Tres Seaver +1 202-558-7113 tseaver@palladion.com Palladion Software "Excellence by Design" http://palladion.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFEaMVi+gerLs4ltQ4RAqUIAJsHpcPQTX7jv+db+DRG9TApaIImVQCgqCZn lPXu2KJoCLtTOSTyUJTIJ24= =3r0r -----END PGP SIGNATURE-----
Hmmm, it was request.environ['REMOTE_USER'] that I found a way to hack. However, your comment has caused me to realise that when not logged in, Apache is not setting the REMOTE_USER environment variable, so a script can set it (in environ). So if I get the Apache boss to set REMOTE_USER to None that should fix it? Subtle. Thanks for making me think. Cliff Tres Seaver wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Cliff Ford wrote:
My people want to adopt a single sign-on system for web applications that is based on the REMOTE_USER environment variable. I have tried out RemoteUserFolder and also adapted exUserFolder to work similarly.
My problem is that I figured out how a user who has permission to create python scripts (might work with dtml and page templates too) could access otherwise forbidden content by making calls that pretend to come from another user. Has any one else come across this problem and devised a solution, either in software or organisation?
Problem verified with Zope 2.9.2 and latest RemoteUserFolder
User folders who care need to look at the request's 'environ' dict, e.g.::
remote_user = request.environ['REMOTE_USER'] # not hackable
rather than the default one where untrusted code can scribble::
remote_user = request['REMOTE_USER'] # hackable
Tres. - -- =================================================================== Tres Seaver +1 202-558-7113 tseaver@palladion.com Palladion Software "Excellence by Design" http://palladion.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFEaMVi+gerLs4ltQ4RAqUIAJsHpcPQTX7jv+db+DRG9TApaIImVQCgqCZn lPXu2KJoCLtTOSTyUJTIJ24= =3r0r -----END PGP SIGNATURE-----
_______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev )
I have done some more testing, and despite being told that request.environ['REMOTE_USER'] is not hackable I have hacked it and can use the hack to get at otherwise forbidden content. For testing I have set REMOTE_USER in the zope.conf cgi-environment variable, so I can quickly change from being one user to another. I have read the RemoteUserFolder source code - that is what led me to the hack. The hack allows a user who can write a python script in his own folder to use it to hack the entire site. So I still wonder if anyone who is ising the REMOTE_USER environment variable is aware of a problem and has a solution. Cliff Tres Seaver wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Cliff Ford wrote:
My people want to adopt a single sign-on system for web applications that is based on the REMOTE_USER environment variable. I have tried out RemoteUserFolder and also adapted exUserFolder to work similarly.
My problem is that I figured out how a user who has permission to create python scripts (might work with dtml and page templates too) could access otherwise forbidden content by making calls that pretend to come from another user. Has any one else come across this problem and devised a solution, either in software or organisation?
Problem verified with Zope 2.9.2 and latest RemoteUserFolder
User folders who care need to look at the request's 'environ' dict, e.g.::
remote_user = request.environ['REMOTE_USER'] # not hackable
rather than the default one where untrusted code can scribble::
remote_user = request['REMOTE_USER'] # hackable
Tres. - -- =================================================================== Tres Seaver +1 202-558-7113 tseaver@palladion.com Palladion Software "Excellence by Design" http://palladion.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org
iD8DBQFEaMVi+gerLs4ltQ4RAqUIAJsHpcPQTX7jv+db+DRG9TApaIImVQCgqCZn lPXu2KJoCLtTOSTyUJTIJ24= =3r0r -----END PGP SIGNATURE-----
_______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev )
On 5/16/06, Cliff Ford <Cliff.Ford@ed.ac.uk> wrote:
So I still wonder if anyone who is ising the REMOTE_USER environment variable is aware of a problem and has a solution.
Environment-related variables should not be "hackable" from restricted code. Please file a report in de Zope Collector: http://www.zope.org/Collectors/Zope You'll need to log in (create a Zope.org account if you don't yet have one), and make sure you check the 'security related' tickbox. Thanks, -- Martijn Pieters
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Martijn Pieters wrote:
On 5/16/06, Cliff Ford <Cliff.Ford@ed.ac.uk> wrote:
So I still wonder if anyone who is ising the REMOTE_USER environment variable is aware of a problem and has a solution.
Environment-related variables should not be "hackable" from restricted code. Please file a report in de Zope Collector:
http://www.zope.org/Collectors/Zope
You'll need to log in (create a Zope.org account if you don't yet have one), and make sure you check the 'security related' tickbox.
MJ: Given the discussino here on the list already, *don't* tick that box, as it will only make it harder to address the issue. Cliff: The 'environ', 'form', 'taintedform', and 'cookies' attributes of ZPublisher's HTTPRequest are simple Python dicts, and hence can be modified by untrusted code (I thought they were instances of a derived, read-only class). If this is an issue for third-party code (such as your user folder), then you likely need to monkey-patch ZPublisher.HTTPRequest to lock them down. I'm attaching a patch which does that for 'environ'; similar tweaks might be required for the others. Given the possibility of a BBB foul (third-party code may *legitimately* expect to be able to mutate one or more of these dicts), we would probably have to land these changes as configurable options, defaulting (at least initially) to the current behavior. Before you chase this down, please verify that the user folder you use *can* be tricked this way: for instance, if the authentication always occurs *before* your script is executed, then the scribbling is only an annoyance, rather than a hole. Tres. - -- =================================================================== Tres Seaver +1 202-558-7113 tseaver@palladion.com Palladion Software "Excellence by Design" http://palladion.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFEadrg+gerLs4ltQ4RAlLiAKCzSAM7XJcG0+79EQxMYHz7HQQFIQCffDuS 4WIEwx4hoOZ/0c81ZECFIcY= =YQMp -----END PGP SIGNATURE-----
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Martijn Pieters wrote:
On 5/16/06, Cliff Ford <Cliff.Ford@ed.ac.uk> wrote:
So I still wonder if anyone who is ising the REMOTE_USER environment variable is aware of a problem and has a solution.
Environment-related variables should not be "hackable" from restricted code. Please file a report in de Zope Collector:
http://www.zope.org/Collectors/Zope
You'll need to log in (create a Zope.org account if you don't yet have one), and make sure you check the 'security related' tickbox.
Please *don't* mark the issue as "security related", as that only serves to hide it: the cat is already out of the bag here, anyway, assuming that the hole is real: - The 'form', 'taintedform', 'cookies', and 'environ' attributes of an HTTPRequest are simple Python dicts, and can therefore be mutated by untrusted code. - It would be possible, although painful, to replace them by a derived class. The pain will come from two axes: o Performance: might not be too bad, depending on the implementation; just using 'class MyDict(dict): pass' would be enough to prevent untrusted mutation. We might have to add assertions which allowed '__getitem__' and the other accessors, however. We could also use a "harder" implementation, which perhaps raised TypeError from all mutators. I'm attaching a sample patch for the 'environ' dict. o Backward compatibility: there may be third-party code which more-or-less legitimately expects to mutate one or more of those dicts. We would thus probably have to add a zope.conf switch for the "hardening", and default it to the *current* setting. Another solution would be to have the third-party code which suffers from this flaw monkey-patch the HTTPRequest module to supply the needed hardening. Cliff, before we chase all this down, can you verify that the script actually does allow access in your case? I can imagine a case where the authentication was already done by the time the script got to run, which would make this an annoyance, rather than a hole. Tres. - -- =================================================================== Tres Seaver +1 202-558-7113 tseaver@palladion.com Palladion Software "Excellence by Design" http://palladion.com -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFEad/Q+gerLs4ltQ4RAq6IAKDWRTIvxT9T1LUhVWkztHa0v4RUAgCbBc/b 2qRA0qkE0u46yaNVW4cH1aY= =5Cnv -----END PGP SIGNATURE-----
Can someone point me to Zope2 running Twisted server from Paris ecm sprint. I see at least three branches that look like Z2 Twisted refactoring in the svn. Can someone explain differences between these. Many thanks. Regards, David
The stuff has been merged on the Zope trunk and is documented in the CHANGE.txt file. -aj --On 17. Mai 2006 10:00:47 -0300 David Pratt <fairwinds@eastlink.ca> wrote:
Can someone point me to Zope2 running Twisted server from Paris ecm sprint. I see at least three branches that look like Z2 Twisted refactoring in the svn. Can someone explain differences between these. Many thanks.
Regards, David _______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev )
-- ZOPYX Ltd. & Co. KG - Charlottenstr. 37/1 - 72070 Tübingen - Germany Web: www.zopyx.com - Email: info@zopyx.com - Phone +49 - 7071 - 793376 E-Publishing, Python, Zope & Plone development, Consulting
Wow. That's great. I realize this is all still experimental but will https server be added to the mix? Regards, David Andreas Jung wrote:
The stuff has been merged on the Zope trunk and is documented in the CHANGE.txt file.
-aj
--On 17. Mai 2006 10:00:47 -0300 David Pratt <fairwinds@eastlink.ca> wrote:
Can someone point me to Zope2 running Twisted server from Paris ecm sprint. I see at least three branches that look like Z2 Twisted refactoring in the svn. Can someone explain differences between these. Many thanks.
Regards, David _______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev )
On 5/17/06, David Pratt <fairwinds@eastlink.ca> wrote:
Can someone point me to Zope2 running Twisted server from Paris ecm sprint. I see at least three branches that look like Z2 Twisted refactoring in the svn. Can someone explain differences between these. Many thanks.
Trunk includes the most recent effort for this. -- Lennart Regebro, Nuxeo http://www.nuxeo.com/ CPS Content Management http://www.cps-project.org/
This is just to report that this issue is resolved (for me). Tres Seaver kindly provided a patch for HTTPRequest.py that makes the environ dictionary immutable (appended below for those in a similar position). This may have adverse consequences for applications that rely on existing behaviour and Tres has recommended that it would be better to harden the User Folder code. In our case we might also be able to encrypt the remote Username. Once again, thanks to Tres and other list members, who are a wonderful resource. Cliff Cliff Ford wrote:
My people want to adopt a single sign-on system for web applications that is based on the REMOTE_USER environment variable. I have tried out RemoteUserFolder and also adapted exUserFolder to work similarly.
My problem is that I figured out how a user who has permission to create python scripts (might work with dtml and page templates too) could access otherwise forbidden content by making calls that pretend to come from another user. Has any one else come across this problem and devised a solution, either in software or organisation?
Problem verified with Zope 2.9.2 and latest RemoteUserFolder.
Cliff _______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev )
The Patch: Index: lib/python/ZPublisher/HTTPRequest.py =================================================================== --- lib/python/ZPublisher/HTTPRequest.py (revision 68139) +++ lib/python/ZPublisher/HTTPRequest.py (working copy) @@ -63,6 +63,16 @@ class NestedLoopExit( Exception ): pass +class ReadOnlyDict(dict): + def __setitem__(self, key, value): + raise TypeError, 'Immutable' + def __delitem__(self, key): + raise TypeError, 'Immutable' + def update(self, other): + raise TypeError, 'Immutable' + def clear(self): + raise TypeError, 'Immutable' + class HTTPRequest(BaseRequest): """\ Model HTTP request data. @@ -252,7 +262,7 @@ del environ['HTTP_AUTHORIZATION'] self.stdin=stdin - self.environ=environ + self.environ=ReadOnlyDict(environ) have_env=environ.has_key get_env=environ.get self.response=response Index: lib/python/ZPublisher/tests/testHTTPRequest.py =================================================================== --- lib/python/ZPublisher/tests/testHTTPRequest.py (revision 68139) +++ lib/python/ZPublisher/tests/testHTTPRequest.py (working copy) @@ -684,7 +684,23 @@ req.close() self.assertEqual(start_count, sys.getrefcount(s)) # The test + def test_environ_is_immutable(self): + from StringIO import StringIO + s = StringIO(TEST_FILE_DATA) + env = TEST_ENVIRON.copy() + env['to_replace'] = 'to_replace' + env['to_remove'] = 'to_remove' + from ZPublisher.HTTPRequest import HTTPRequest + req = HTTPRequest(s, env, None) + self.assertRaises(TypeError, req.environ.__setitem__, + 'hacked', 'hacked') + self.assertRaises(TypeError, req.environ.__setitem__, + 'to_replace', 'replaced') + self.assertRaises(TypeError, req.environ.__delitem__, 'to_remove') + self.assertRaises(TypeError, req.environ.update, {'hacked': 'hacked'}) + self.assertRaises(TypeError, req.environ.clear) + def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(AuthCredentialsTestsa, 'test')) Index: lib/python/OFS/tests/testRanges.py =================================================================== --- lib/python/OFS/tests/testRanges.py (revision 68139) +++ lib/python/OFS/tests/testRanges.py (working copy) @@ -59,6 +59,9 @@ r['Application'] = a self.root = a self.app = makerequest(self.root, stdout=self.responseOut) + # 'environ' is now immutable, so replace it to allow scribbling + # in tests + self.app.REQUEST.environ = dict(self.app.REQUEST.environ) try: self.app._delObject(TESTFOLDER_NAME) except AttributeError: pass manage_addFolder(self.app, TESTFOLDER_NAME)
Cliff Ford wrote:
This is just to report that this issue is resolved (for me). Tres Seaver kindly provided a patch for HTTPRequest.py that makes the environ dictionary immutable (appended below for those in a similar position). This may have adverse consequences for applications that rely on existing behaviour and Tres has recommended that it would be better to harden the User Folder code. In our case we might also be able to encrypt the remote Username. Once again, thanks to Tres and other list members, who are a wonderful resource. Completely immutable environ is not a good choice from WSGI point-of-view. environ can be useful for middleware information-passing.
-Jim Washington
On 5/18/06, Jim Washington <jwashin@vt.edu> wrote:
Completely immutable environ is not a good choice from WSGI point-of-view. environ can be useful for middleware information-passing.
WSGI middleware would by definition get the environ and be able to modify it before the request gets it, so that isn't a problem. -- Lennart Regebro, Nuxeo http://www.nuxeo.com/ CPS Content Management http://www.cps-project.org/
Lennart Regebro wrote:
On 5/18/06, Jim Washington <jwashin@vt.edu> wrote:
Completely immutable environ is not a good choice from WSGI point-of-view. environ can be useful for middleware information-passing.
WSGI middleware would by definition get the environ and be able to modify it before the request gets it, so that isn't a problem.
Yes, not a problem for for middleware -> app communication. But some app -> middleware communication would be impossible if environ is completely read-only. I am assuming that "immutable" here means "read-only". What if a middleware app puts a key in environ specifically for the app to write e.g., post-processing parameters? I have a use case for that. -Jim Washington
Cliff Ford wrote at 2006-5-14 23:39 +0100:
... My problem is that I figured out how a user who has permission to create python scripts (might work with dtml and page templates too) could access otherwise forbidden content by making calls that pretend to come from another user. Has any one else come across this problem and devised a solution, either in software or organisation?
Problem verified with Zope 2.9.2 and latest RemoteUserFolder.
That surprises my -- unless the user can create "AccessRule"s: Usually, authentication is performed before any PythonScript is executed. I know only one exception: "AccessRule"s -- Dieter
participants (8)
-
Andreas Jung -
Cliff Ford -
David Pratt -
Dieter Maurer -
Jim Washington -
Lennart Regebro -
Martijn Pieters -
Tres Seaver