fix an edge case, where mallory can delete comments by bo
This commit is contained in:
parent
3459b7b9ee
commit
ecd4c6b120
@ -36,10 +36,12 @@ def create(app, environ, request, path):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
return abort(400)
|
return abort(400)
|
||||||
|
|
||||||
|
md5 = rv.md5
|
||||||
rv.text = app.markup.convert(rv.text)
|
rv.text = app.markup.convert(rv.text)
|
||||||
|
|
||||||
response = Response(json.dumps(rv), 201, content_type='application/json')
|
response = Response(json.dumps(rv), 201, content_type='application/json')
|
||||||
response.set_cookie('session-%s-%s' % (urllib.quote(path, ''), rv.id),
|
response.set_cookie('session-%s-%s' % (urllib.quote(path, ''), rv.id),
|
||||||
app.signer.dumps([path, rv.id]), max_age=app.MAX_AGE)
|
app.signer.dumps([path, rv.id, md5]), max_age=app.MAX_AGE)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@ -65,14 +67,23 @@ def modify(app, environ, request, path, id):
|
|||||||
except (SignatureExpired, BadSignature):
|
except (SignatureExpired, BadSignature):
|
||||||
return abort(403)
|
return abort(403)
|
||||||
|
|
||||||
if not (rv[0] == '*' or rv == [path, id]):
|
# verify checksum, mallory might skip cookie deletion when he deletes a comment
|
||||||
|
if app.db.get(path, id).md5 != rv[2]:
|
||||||
|
abort(403)
|
||||||
|
|
||||||
|
if not (rv[0] == '*' or rv[0:2] == [path, id]):
|
||||||
abort(401)
|
abort(401)
|
||||||
|
|
||||||
if request.method == 'PUT':
|
if request.method == 'PUT':
|
||||||
try:
|
try:
|
||||||
rv = app.db.update(path, id, models.Comment.fromjson(request.data))
|
rv = app.db.update(path, id, models.Comment.fromjson(request.data))
|
||||||
|
return Response(json.dumps(rv), 200, content_type='application/json')
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return Response(unicode(e), 400)
|
return Response(unicode(e), 400)
|
||||||
else:
|
|
||||||
|
if request.method == 'DELETE':
|
||||||
rv = app.db.delete(path, id)
|
rv = app.db.delete(path, id)
|
||||||
return Response(json.dumps(rv), 200, content_type='application/json')
|
|
||||||
|
response = Response(json.dumps(rv), 200, content_type='application/json')
|
||||||
|
response.delete_cookie('session-%s-%s' % (urllib.quote(path, ''), id))
|
||||||
|
return response
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
import hashlib
|
||||||
|
|
||||||
class Comment(object):
|
class Comment(object):
|
||||||
"""This class represents a regular comment. It needs at least a text
|
"""This class represents a regular comment. It needs at least a text
|
||||||
@ -56,3 +57,10 @@ class Comment(object):
|
|||||||
@property
|
@property
|
||||||
def deleted(self):
|
def deleted(self):
|
||||||
return self.mode == 4
|
return self.mode == 4
|
||||||
|
|
||||||
|
@property
|
||||||
|
def md5(self):
|
||||||
|
hv = hashlib.md5()
|
||||||
|
for key in set(self.fields) - set(['parent', ]):
|
||||||
|
hv.update(getattr(self, key) or '')
|
||||||
|
return hv.hexdigest()
|
||||||
|
@ -115,3 +115,15 @@ class TestComments(unittest.TestCase):
|
|||||||
for path in paths:
|
for path in paths:
|
||||||
assert self.get('/comment/' + path)
|
assert self.get('/comment/' + path)
|
||||||
assert self.get('/comment/' + path + '/1')
|
assert self.get('/comment/' + path + '/1')
|
||||||
|
|
||||||
|
def testDeleteAndCreateByDifferentUsersButSamePostId(self):
|
||||||
|
|
||||||
|
mallory = Client(self.app, Response)
|
||||||
|
mallory.post('/comment/path/new', data=json.dumps(comment(text='Foo')))
|
||||||
|
mallory.delete('/comment/path/1')
|
||||||
|
|
||||||
|
bob = Client(self.app, Response)
|
||||||
|
bob.post('/comment/path/new', data=json.dumps(comment(text='Bar')))
|
||||||
|
|
||||||
|
assert mallory.delete('/comment/path/1').status_code == 403
|
||||||
|
assert bob.delete('/comment/path/1').status_code == 200
|
||||||
|
Loading…
Reference in New Issue
Block a user