New submission from Guido Vranken:
Proof of concept:
# Script for Python 2
import urllib2
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0' + chr(0x0A) + "Location:
header injection")]
response = opener.open("http://localhost:9999")
# Data sent is:
"""
GET / HTTP/1.1
Accept-Encoding: identity
Host: localhost:9999
Connection: close
User-Agent: Mozilla/5.0
Location: header injection
"""
# End of script
# Python 3
from urllib.request import urlopen, build_opener
opener = build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0' + chr(0x0A) + "Location:
header injection")]
opener.open("http://localhost:9999")
# Data sent is:
"""
GET / HTTP/1.1
Accept-Encoding: identity
Host: localhost:9999
Connection: close
User-Agent: Mozilla/5.0
Location: header injection
"""
# End of script
It is the responsibility of the developer leveraging Python and its HTTP client
libraries to ensure that their (web) application acts in accordance to official
HTTP specifications and that no threats to security will arise from their code.
However, newlines inside headers are arguably a special case of breaking the
conformity with RFC's in regard to the allowed character set. No illegal
character used inside a HTTP header is likely to have a compromising side
effect on back-end clients and servers and the integrity of their
communication, as a result of the leniency of most web servers. However, a
newline character (0x0A) embedded in a HTTP header invariably has the semantic
consequence of denoting the start of an additional header line. To put it
differently, not sanitizing headers in complete accordance to RFC's could be
seen as as virtue in that it gives the programmer a maximum amount of freedom,
without having to trade it for any likely or severe security ramifications, so
that they may use illegal characters in testing environments and environments
that are outlined by an expliticly less strict interpretation of the HTTP
protocol. Newlines are special in that they enable anyone who is able to
influence the header
content, to, in effect, perform additional invocations to add_header().
In issue 17322 ( http://bugs.python.org/issue17322 ) there is some discussion
as to the general compliance to RFC's by the HTTP client libraries. I'd like to
opt to begin with prohibiting newline characters to be present in HTTP headers.
Although this issue is not a "hard vulnerability" such as a buffer overflow, it
does translate to a potentially equal level of severity when considered from
the perspective of a web-enabled application, for which purpose the HTTP
libraries are typically used for. Lack of input validation on the application
developer's end will faciliate header injections, for example if user-supplied
data will end up as cookie content verbatim.
Adding this proposed additional layer of validation inside Python minimizes the
likelihood of a successful header injection while functionality is not notably
affected.
I'm inclined to add this validation to putheader() in the 'http' module rather
than in urllib, as this will secure all invocations to 'http' regardless of
intermediate libraries such as urllib.
Included is a patch for the latest checkout of the default branch that will
cause CannotSendHeader() to be raised if a newline character is detected in
either a header name or its value. Aside from detecting "\n", it also breaks on
"\r" as their respective implications can be similar. Feel free to adjust,
rewrite and transpose this to other branches where you feel this is appropriate.
Guido Vranken
Intelworks
----------
components: Library (Lib)
files: disable_http_header_injection.patch
keywords: patch
messages: 231590
nosy: Guido
priority: normal
severity: normal
status: open
title: HTTP header injection in urrlib2/urllib/httplib/http.client
type: security
versions: Python 2.7, Python 3.2, Python 3.3, Python 3.4, Python 3.5, Python 3.6
Added file: http://bugs.python.org/file37264/disable_http_header_injection.patch
_______________________________________
Python tracker <[email protected]>
<http://bugs.python.org/issue22928>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com