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 <rep...@bugs.python.org>
<http://bugs.python.org/issue22928>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to