Skip to content

Commit

Permalink
security fix in session.py (tx Sławomir Błaże)
Browse files Browse the repository at this point in the history
  • Loading branch information
anandology committed Nov 5, 2008
1 parent 57a293d commit 0badde0
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 6 deletions.
8 changes: 8 additions & 0 deletions test/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ def testParallelSessions(self):
self.assertEquals(b1.open('/count'), str(i+1))
self.assertEquals(b2.open('/count'), str(i))

def testBadSessionId(self):
b = Browser(self.app)
self.assertEquals(b.open('/count'), '1')
self.assertEquals(b.open('/count'), '2')

b.cookies['webpy_session_id'] = '/etc/password'
self.assertEquals(b.open('/count'), '1')

class DBSessionTest(SessionTest):
"""Session test with db store."""
def make_session(self, app):
Expand Down
25 changes: 19 additions & 6 deletions web/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ def _load(self):
cookie_name = self._config.cookie_name
cookie_domain = self._config.cookie_domain
self.session_id = web.cookies().get(cookie_name)


# protection against session_id tampering
if self.session_id and not self._valid_session_id(self.session_id):
self.session_id = None

self._check_expiry()
if self.session_id:
d = self.store[self.session_id]
Expand Down Expand Up @@ -118,6 +122,10 @@ def _generate_session_id(self):
if session_id not in self.store:
break
return session_id

def _valid_session_id(self, session_id):
rx = utils.re_compile('^[0-9a-fA-F]+$')
return rx.match(session_id)

def _cleanup(self):
"""Cleanup the stored sessions"""
Expand Down Expand Up @@ -183,22 +191,27 @@ def __init__(self, root):
if not os.path.exists(root):
os.mkdir(root)
self.root = root

def _get_path(self, key):
if os.path.sep in key:
raise ValueError, "Bad key: %s" % repr(key)
return os.path.join(self.root, key)

def __contains__(self, key):
path = os.path.join(self.root, key)
path = self._get_path(key)
return os.path.exists(path)

def __getitem__(self, key):
path = os.path.join(self.root, key)
path = self._get_path(key)
if os.path.exists(path):
pickled = open(path).read()
return self.decode(pickled)
else:
raise KeyError, key

def __setitem__(self, key, value):
path = self._get_path(key)
pickled = self.encode(value)
path = os.path.join(self.root, key)
try:
f = open(path, 'w')
try:
Expand All @@ -209,14 +222,14 @@ def __setitem__(self, key, value):
pass

def __delitem__(self, key):
path = os.path.join(self.root, key)
path = self._get_path(key)
if os.path.exists(path):
os.remove(path)

def cleanup(self, timeout):
now = time.time()
for f in os.listdir(self.root):
path = os.path.join(self.root, f)
path = self._get_path(f)
atime = os.stat(path).st_atime
if now - atime > timeout :
os.remove(path)
Expand Down

0 comments on commit 0badde0

Please sign in to comment.