Revert "HTTP Origin is only sent on cross-origin requests in Firefox"
Revert "use Referer instead of Origin when using IE" Revert "fix unittests" Revert "check if Origin matches Host to mitigate CSRF, part of #40" This reverts commit 9376511485c70deaf908aa67bcdc8f0c9a0b003e. This reverts commit9a03cca793
. This reverts commit4c16ba76cc
. This reverts commit32e4b70510
.
This commit is contained in:
parent
b839b2be31
commit
1db06bbf39
@ -12,7 +12,6 @@ from werkzeug.http import dump_cookie
|
|||||||
from werkzeug.routing import Rule
|
from werkzeug.routing import Rule
|
||||||
from werkzeug.wrappers import Response
|
from werkzeug.wrappers import Response
|
||||||
from werkzeug.exceptions import BadRequest, Forbidden, NotFound
|
from werkzeug.exceptions import BadRequest, Forbidden, NotFound
|
||||||
from werkzeug.useragents import UserAgent
|
|
||||||
|
|
||||||
from isso.compat import text_type as str
|
from isso.compat import text_type as str
|
||||||
|
|
||||||
@ -32,33 +31,6 @@ class JSON(Response):
|
|||||||
return super(JSON, self).__init__(*args, content_type='application/json')
|
return super(JSON, self).__init__(*args, content_type='application/json')
|
||||||
|
|
||||||
|
|
||||||
def csrf(view):
|
|
||||||
"""A decorator to check if Origin matches Host (may be empty if in the same
|
|
||||||
origin, except for IE of course). When MSIE, use Referer. See
|
|
||||||
|
|
||||||
* https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Checking_The_Origin_Header
|
|
||||||
* http://tools.ietf.org/html/draft-abarth-origin-09
|
|
||||||
* https://wiki.mozilla.org/Security/Origin
|
|
||||||
|
|
||||||
for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def dec(self, environ, request, *args, **kwargs):
|
|
||||||
|
|
||||||
hosts = map(parse.host, self.conf.getiter("host"))
|
|
||||||
|
|
||||||
if UserAgent(environ).browser == "msie": # yup
|
|
||||||
if parse.host(request.headers.get("Referer", "")) not in hosts:
|
|
||||||
raise Forbidden("CSRF")
|
|
||||||
elif "Origin" in request.headers:
|
|
||||||
if parse.host(request.headers.get("Origin", "")) not in hosts:
|
|
||||||
raise Forbidden("CSRF")
|
|
||||||
|
|
||||||
return view(self, environ, request, *args, **kwargs)
|
|
||||||
|
|
||||||
return dec
|
|
||||||
|
|
||||||
|
|
||||||
class API(object):
|
class API(object):
|
||||||
|
|
||||||
FIELDS = set(['id', 'parent', 'text', 'author', 'website', 'email',
|
FIELDS = set(['id', 'parent', 'text', 'author', 'website', 'email',
|
||||||
@ -119,7 +91,6 @@ class API(object):
|
|||||||
|
|
||||||
return True, ""
|
return True, ""
|
||||||
|
|
||||||
@csrf
|
|
||||||
@requires(str, 'uri')
|
@requires(str, 'uri')
|
||||||
def new(self, environ, request, uri):
|
def new(self, environ, request, uri):
|
||||||
|
|
||||||
@ -203,7 +174,6 @@ class API(object):
|
|||||||
|
|
||||||
return Response(json.dumps(rv), 200, content_type='application/json')
|
return Response(json.dumps(rv), 200, content_type='application/json')
|
||||||
|
|
||||||
@csrf
|
|
||||||
def edit(self, environ, request, id):
|
def edit(self, environ, request, id):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -247,7 +217,6 @@ class API(object):
|
|||||||
resp.headers.add("X-Set-Cookie", cookie("isso-%i" % rv["id"]))
|
resp.headers.add("X-Set-Cookie", cookie("isso-%i" % rv["id"]))
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@csrf
|
|
||||||
def delete(self, environ, request, id, key=None):
|
def delete(self, environ, request, id, key=None):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -350,13 +319,11 @@ class API(object):
|
|||||||
|
|
||||||
return JSON(json.dumps(rv), 200)
|
return JSON(json.dumps(rv), 200)
|
||||||
|
|
||||||
@csrf
|
|
||||||
def like(self, environ, request, id):
|
def like(self, environ, request, id):
|
||||||
|
|
||||||
nv = self.comments.vote(True, id, utils.anonymize(str(request.remote_addr)))
|
nv = self.comments.vote(True, id, utils.anonymize(str(request.remote_addr)))
|
||||||
return Response(json.dumps(nv), 200)
|
return Response(json.dumps(nv), 200)
|
||||||
|
|
||||||
@csrf
|
|
||||||
def dislike(self, environ, request, id):
|
def dislike(self, environ, request, id):
|
||||||
|
|
||||||
nv = self.comments.vote(False, id, utils.anonymize(str(request.remote_addr)))
|
nv = self.comments.vote(False, id, utils.anonymize(str(request.remote_addr)))
|
||||||
|
@ -274,23 +274,6 @@ class TestComments(unittest.TestCase):
|
|||||||
self.client.delete('/id/1')
|
self.client.delete('/id/1')
|
||||||
assert '/' not in self.app.db.threads
|
assert '/' not in self.app.db.threads
|
||||||
|
|
||||||
def testCSRF(self):
|
|
||||||
|
|
||||||
payload = json.dumps({"text": "..."})
|
|
||||||
|
|
||||||
assert self.client.post('/new?uri=%2F', data=payload,
|
|
||||||
headers={"Origin": "http://localhost:8080"}
|
|
||||||
).status_code == 201
|
|
||||||
|
|
||||||
assert self.client.post('/new?uri=%2F', data=payload,
|
|
||||||
headers={"Referer": "http://other.example/asdf",
|
|
||||||
"User-Agent": "msie"}
|
|
||||||
).status_code == 403
|
|
||||||
|
|
||||||
assert self.client.post('/new?uri=%2F', data=payload,
|
|
||||||
headers={"Origin": "http://other.example"}
|
|
||||||
).status_code == 403
|
|
||||||
|
|
||||||
|
|
||||||
class TestModeratedComments(unittest.TestCase):
|
class TestModeratedComments(unittest.TestCase):
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user