browser2: Fix cookie security in redirections
With tests (another reason why it's good to write them).
This commit is contained in:
parent
83e08c103d
commit
ef379f830e
2 changed files with 67 additions and 4 deletions
|
|
@ -333,6 +333,9 @@ class BaseBrowser(object):
|
||||||
if cookies is None:
|
if cookies is None:
|
||||||
cookies = self.cookies.for_request(url)
|
cookies = self.cookies.for_request(url)
|
||||||
kwargs['cookies'] = cookies
|
kwargs['cookies'] = cookies
|
||||||
|
# erase all cookies, python-requests does not handle them securely
|
||||||
|
# and tries to merge them with provided cookies!
|
||||||
|
self.session.cookies.clear()
|
||||||
|
|
||||||
# call python-requests
|
# call python-requests
|
||||||
response = self.session.request(method, url, **kwargs)
|
response = self.session.request(method, url, **kwargs)
|
||||||
|
|
@ -343,7 +346,8 @@ class BaseBrowser(object):
|
||||||
if allow_redirects:
|
if allow_redirects:
|
||||||
response = self.follow_redirects(response, orig_args)
|
response = self.follow_redirects(response, orig_args)
|
||||||
|
|
||||||
# erase all cookies, python-requests does not handle them securely
|
# erase all cookies again
|
||||||
|
# to prevent leakage when using session.request() directly
|
||||||
self.session.cookies.clear()
|
self.session.cookies.clear()
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from random import choice
|
||||||
|
|
||||||
from requests import HTTPError
|
from requests import HTTPError
|
||||||
from nose.plugins.skip import SkipTest
|
from nose.plugins.skip import SkipTest
|
||||||
|
|
@ -35,6 +36,12 @@ HTTPBIN = 'http://httpbin.org/' # https://github.com/kennethreitz/httpbin
|
||||||
POSTBIN = 'http://www.postbin.org/' # https://github.com/progrium/postbin
|
POSTBIN = 'http://www.postbin.org/' # https://github.com/progrium/postbin
|
||||||
REQUESTBIN = 'http://requestb.in/' # https://github.com/progrium/requestbin
|
REQUESTBIN = 'http://requestb.in/' # https://github.com/progrium/requestbin
|
||||||
|
|
||||||
|
# if you change HTTPBIN, you should also change these URLs for some tests:
|
||||||
|
# redirect to http://httpbin.org/get
|
||||||
|
REDIRECTS1 = ('http://tinyurl.com/ouiboube-b2', 'http://bit.ly/st4Hcv')
|
||||||
|
# redirect to http://httpbin.org/cookies
|
||||||
|
REDIRECTS2 = ('http://tinyurl.com/7zp3jnr', 'http://bit.ly/HZCCX7')
|
||||||
|
|
||||||
|
|
||||||
def test_base():
|
def test_base():
|
||||||
b = BaseBrowser()
|
b = BaseBrowser()
|
||||||
|
|
@ -99,9 +106,21 @@ def test_redirects():
|
||||||
assert r.status_code == 302
|
assert r.status_code == 302
|
||||||
|
|
||||||
|
|
||||||
|
def test_redirect2():
|
||||||
|
"""
|
||||||
|
More redirect tests
|
||||||
|
"""
|
||||||
|
rurl = choice(REDIRECTS1)
|
||||||
|
b = BaseBrowser()
|
||||||
|
r = b.location(rurl)
|
||||||
|
assert r.url == HTTPBIN + 'get'
|
||||||
|
assert json.loads(r.text)['headers'].get('Referer') == rurl
|
||||||
|
# TODO referrer privacy settings
|
||||||
|
|
||||||
|
|
||||||
def test_brokenpost():
|
def test_brokenpost():
|
||||||
"""
|
"""
|
||||||
Tests _fix_redirect()
|
Test empty POST and redirect after POST
|
||||||
"""
|
"""
|
||||||
raise SkipTest('PostBin is disabled')
|
raise SkipTest('PostBin is disabled')
|
||||||
try:
|
try:
|
||||||
|
|
@ -234,6 +253,9 @@ def test_referrer():
|
||||||
|
|
||||||
|
|
||||||
def test_cookieparse():
|
def test_cookieparse():
|
||||||
|
"""
|
||||||
|
Test cookie parsing and processing
|
||||||
|
"""
|
||||||
cj = CookieJar()
|
cj = CookieJar()
|
||||||
|
|
||||||
def bc(data):
|
def bc(data):
|
||||||
|
|
@ -284,6 +306,9 @@ def test_cookieparse():
|
||||||
|
|
||||||
|
|
||||||
def test_cookiejar():
|
def test_cookiejar():
|
||||||
|
"""
|
||||||
|
Test adding, removing, finding cookies to and from the jar
|
||||||
|
"""
|
||||||
def bc(data):
|
def bc(data):
|
||||||
"""
|
"""
|
||||||
build one cookie
|
build one cookie
|
||||||
|
|
@ -370,10 +395,10 @@ def test_cookiejar():
|
||||||
|
|
||||||
|
|
||||||
def test_buildcookie():
|
def test_buildcookie():
|
||||||
|
"""
|
||||||
|
Test easy cookie building
|
||||||
|
"""
|
||||||
cj = CookieJar()
|
cj = CookieJar()
|
||||||
"""
|
|
||||||
Test cookie building
|
|
||||||
"""
|
|
||||||
c = cj.build('kk', 'vv', 'http://example.com/')
|
c = cj.build('kk', 'vv', 'http://example.com/')
|
||||||
assert c.domain == 'example.com'
|
assert c.domain == 'example.com'
|
||||||
assert not c.secure
|
assert not c.secure
|
||||||
|
|
@ -435,3 +460,37 @@ def test_cookienav():
|
||||||
r = b.location(HTTPBIN + 'cookies')
|
r = b.location(HTTPBIN + 'cookies')
|
||||||
assert len(json.loads(r.text)['cookies']) == 2
|
assert len(json.loads(r.text)['cookies']) == 2
|
||||||
assert 'bla' not in json.loads(r.text)['cookies']
|
assert 'bla' not in json.loads(r.text)['cookies']
|
||||||
|
|
||||||
|
|
||||||
|
def test_cookieredirect():
|
||||||
|
"""
|
||||||
|
Test cookie redirection security
|
||||||
|
"""
|
||||||
|
rurl = choice(REDIRECTS2)
|
||||||
|
|
||||||
|
b = BaseBrowser()
|
||||||
|
r = b.location(HTTPBIN + 'cookies')
|
||||||
|
assert len(json.loads(r.text)['cookies']) == 0
|
||||||
|
|
||||||
|
# add a cookie to the redirection service domain (not the target!)
|
||||||
|
cookie = b.cookies.build('k', 'v1', rurl)
|
||||||
|
b.cookies.set(cookie)
|
||||||
|
r = b.location(rurl)
|
||||||
|
assert r.url == HTTPBIN + 'cookies'
|
||||||
|
# the cookie was not forwarded; it's for another domain
|
||||||
|
# this is important for security reasons,
|
||||||
|
# and because python-requests tries to do it by default!
|
||||||
|
print json.loads(r.text)['cookies']
|
||||||
|
assert len(json.loads(r.text)['cookies']) == 0
|
||||||
|
|
||||||
|
# add a cookie for the target
|
||||||
|
cookie = b.cookies.build('k', 'v2', HTTPBIN)
|
||||||
|
b.cookies.set(cookie)
|
||||||
|
r = b.location(rurl)
|
||||||
|
assert r.url == HTTPBIN + 'cookies'
|
||||||
|
assert len(json.loads(r.text)['cookies']) == 1
|
||||||
|
assert json.loads(r.text)['cookies']['k'] == 'v2'
|
||||||
|
|
||||||
|
# check all cookies sent in the request chain
|
||||||
|
assert r.cookies == {'k': 'v2'}
|
||||||
|
assert r.history[0].cookies['k'] == 'v1' # some services add other cookies
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue