Skip to content
This repository has been archived by the owner on Feb 10, 2023. It is now read-only.

Commit

Permalink
- Fix: Prevent header spoofing via underscore/dash conflation
Browse files Browse the repository at this point in the history
  • Loading branch information
dataflake committed Feb 7, 2020
1 parent 820450d commit 2fd0d28
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Changelog
4.1 (unreleased)
----------------

- Nothing changed yet.
- Fix: Prevent header spoofing via underscore/dash conflation
(`Zope#655 <https://github.com/zopefoundation/Zope/pull/655>`_)


4.0.2 (2019-08-22)
Expand Down
3 changes: 2 additions & 1 deletion src/ZServer/HTTPServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ def get_environment(self, request,
value = value.strip()
if h2ehas(key) and value:
env[h2eget(key)] = value
else:
elif "_" not in key: # Headers with underscores,
# might spoof real ones.
key = 'HTTP_%s' % ("_".join(key.split("-"))).upper()
if value and not env_has(key):
env[key] = value
Expand Down
90 changes: 90 additions & 0 deletions src/ZServer/tests/test_HTTPServer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
##############################################################################
#
# Copyright (c) 2003 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Test HTTPServer module"""

import unittest
import urlparse


class FakeMedusaServer:

def __init__(self):
self.port = 80
self.request_server_name = 'localhost'
self.SERVER_IDENT = 'whoami?'
self.logger = None


class FakeMedusaChannel:

def __init__(self):
self.server = FakeMedusaServer()
self.creation_time = 'now'
self.addr=('0.0.0.0', 7865)


class FakeMedusaRequest:

def __init__(self):
self.channel = FakeMedusaChannel()
self.command = 'get'
self.port = 80
self.version = '0.9'
self.header = []
self.url = 'http://localhost/foo/bar?key1=val1'

def split_uri(self):
return urlparse.urlparse(self.url)[2:]


class zhttp_handlerTests(unittest.TestCase):
""" Tests for ZServer.HTTPServer.zhttp_handler """

def _getTargetClass(self):
from ZServer.HTTPServer import zhttp_handler
return zhttp_handler

def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)

def _makeRequest(self, **kw):
req = FakeMedusaRequest()
for key, value in kw.items():
req.header.append('%s:%s' % (key, value))
return req

def test_header_spoofing(self):
# See https://www.djangoproject.com/weblog/2015/jan/13/security/
handler = self._makeOne('Zope2')

req = self._makeRequest(**{'X-AUTH-USER': 'CORRECT'})
env = handler.get_environment(req)
self.assertIn('HTTP_X_AUTH_USER', env)
self.assertEqual(env['HTTP_X_AUTH_USER'], 'CORRECT')

req = self._makeRequest(**{'X_AUTH-USER': 'SPOOF'})
env = handler.get_environment(req)
self.assertNotIn('HTTP_X_AUTH_USER', env)

req = self._makeRequest(**{'x_auth_user': 'SPOOF'})
env = handler.get_environment(req)
self.assertNotIn('HTTP_X_AUTH_USER', env)


def test_suite():
suite = unittest.TestSuite()
suite.addTests((
unittest.makeSuite(zhttp_handlerTests),
))
return suite

0 comments on commit 2fd0d28

Please sign in to comment.