Store the request path in the nonce for the android cookie. Prevents replay attacks against more than a single URL

Test for android cross url replay attack prevention
This commit is contained in:
Kovid Goyal 2015-06-12 12:02:00 +05:30
parent 1ea0f8ddab
commit 4c1cd70233
2 changed files with 17 additions and 5 deletions

View File

@ -200,15 +200,16 @@ class AuthController(object):
return pw and self.user_credentials.get(un) == pw
def __call__(self, data, endpoint):
http_auth_needed = not (endpoint.android_workaround and self.validate_android_cookie(data.cookies.get(self.ANDROID_COOKIE)))
path = encode_path(*data.path)
http_auth_needed = not (endpoint.android_workaround and self.validate_android_cookie(path, data.cookies.get(self.ANDROID_COOKIE)))
if http_auth_needed:
self.do_http_auth(data, endpoint)
if endpoint.android_workaround:
data.outcookie[self.ANDROID_COOKIE] = synthesize_nonce(self.key_order, self.realm, self.secret)
data.outcookie[self.ANDROID_COOKIE]['path'] = encode_path(*data.path)
data.outcookie[self.ANDROID_COOKIE] = synthesize_nonce(self.key_order, path, self.secret)
data.outcookie[self.ANDROID_COOKIE]['path'] = path
def validate_android_cookie(self, cookie):
return cookie and validate_nonce(self.key_order, cookie, self.realm, self.secret) and not is_nonce_stale(cookie, self.max_age_seconds)
def validate_android_cookie(self, path, cookie):
return cookie and validate_nonce(self.key_order, cookie, path, self.secret) and not is_nonce_stale(cookie, self.max_age_seconds)
def do_http_auth(self, data, endpoint):
auth = data.inheaders.get('Authorization')

View File

@ -26,6 +26,10 @@ def auth(ctx, data):
def android(ctx, data):
return 'android'
@endpoint('/android2', auth_required=True, android_workaround=True)
def android2(ctx, data):
return 'android2'
def router(prefer_basic_auth=False):
from calibre.srv.auth import AuthController
return Router(globals().itervalues(), auth_controller=AuthController(
@ -199,4 +203,11 @@ class TestAuth(BaseTest):
r = urllib2.build_opener(cookie_handler).open(url)
self.ae(r.getcode(), httplib.OK)
self.ae(r.read(), b'android')
# Test that a replay attack against a different URL does not work
try:
urllib2.build_opener(cookie_handler).open(url+'2')
assert ('Replay attack succeeded')
except urllib2.HTTPError as e:
self.ae(e.code, httplib.UNAUTHORIZED)
# }}}