Description
This may be considered intentional behaviour (in which case feel free to close this), but if a request is made to an https endpoint with authorization and it redirects to http on the same host, the Authorization header is not stripped and will be exposed on the wire.
Expected Result
rebuild_auth would strip the Authorization header if the scheme is changed from https to http.
Actual Result
The credentials that were intended to be sent over TLS were transmitted in plaintext with the redirected request.
Reproduction Steps
Run an HTTPS server on localhost:4443 that replies with a 302 redirect to http://localhost:8000, and a plain HTTP server (or netcat) on localhost:8000. Then run
import requests
requests.get('https://localhost:4443', auth=('hello', 'world'), verify=False)The basic auth credentials are sent in plaintext to http://localhost:8000 (the verify=False is just because I had a self-signed cert).
Here's the code I used for the SSL server:
import BaseHTTPServer
import ssl
class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(302)
self.send_header('Location', 'http://localhost:8000/')
self.end_headers()
self.wfile.write('')
httpd = BaseHTTPServer.HTTPServer(('localhost', 4443), Handler)
httpd.socket = ssl.wrap_socket (httpd.socket, server_side=True,
certfile='yourpemfile.pem')
httpd.serve_forever()System Information
{
"chardet": {
"version": "3.0.4"
},
"cryptography": {
"version": "2.2.2"
},
"idna": {
"version": "2.7"
},
"implementation": {
"name": "CPython",
"version": "2.7.12"
},
"platform": {
"release": "4.15.0-23-generic",
"system": "Linux"
},
"pyOpenSSL": {
"openssl_version": "1010008f",
"version": "18.0.0"
},
"requests": {
"version": "2.19.1"
},
"system_ssl": {
"version": "1000207f"
},
"urllib3": {
"version": "1.23"
},
"using_pyopenssl": true
}