Mercurial > p > roundup > code
comparison test/test_cgi.py @ 5210:7da56980754d
Remove csrf keys used with get
The original code didn't delete keys used with a get. Detect this and
invalidate the keys. Get keys are more likely to leak (in urls etc.)
so they have to be removed once used.
Also a little code cleanup and added testing.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Sun, 19 Mar 2017 15:32:14 -0400 |
| parents | 23b8eeaf9864 |
| children | 44f7e6b958fe |
comparison
equal
deleted
inserted
replaced
| 5209:729e703a6c5a | 5210:7da56980754d |
|---|---|
| 970 match_at=out[0].find('Invalid X-FORWARDED-HOST whoami.net') | 970 match_at=out[0].find('Invalid X-FORWARDED-HOST whoami.net') |
| 971 self.assertNotEqual(match_at, -1) | 971 self.assertNotEqual(match_at, -1) |
| 972 del(cl.env['HTTP_X-FORWARDED-HOST']) | 972 del(cl.env['HTTP_X-FORWARDED-HOST']) |
| 973 del(out[0]) | 973 del(out[0]) |
| 974 | 974 |
| 975 # header checks succeed | |
| 976 # check nonce handling. | |
| 977 cl.env['HTTP_REFERER'] = 'http://whoami.com/path/' | |
| 978 | |
| 975 import copy | 979 import copy |
| 976 | |
| 977 form2 = copy.copy(form) | 980 form2 = copy.copy(form) |
| 978 form2.update({'@csrf': 'booogus'}) | 981 form2.update({'@csrf': 'booogus'}) |
| 979 # add a bogus csrf field to the form and rerun the inner_main | 982 # add a bogus csrf field to the form and rerun the inner_main |
| 980 cl.form = makeForm(form2) | 983 cl.form = makeForm(form2) |
| 981 | 984 |
| 982 cl.env['HTTP_REFERER'] = 'http://whoami.com/path/' | |
| 983 cl.inner_main() | 985 cl.inner_main() |
| 984 match_at=out[0].find('Invalid csrf token found: booogus') | 986 match_at=out[0].find('Invalid csrf token found: booogus') |
| 985 self.assertEqual(match_at, 36) | 987 self.assertEqual(match_at, 36) |
| 986 del(out[0]) | 988 del(out[0]) |
| 987 | 989 |
| 988 form2 = copy.copy(form) | 990 form2 = copy.copy(form) |
| 989 nonce = anti_csrf_nonce(cl, cl) | 991 nonce = anti_csrf_nonce(cl, cl) |
| 992 # verify that we can see the nonce | |
| 993 otks = cl.db.getOTKManager() | |
| 994 isitthere = otks.exists(nonce) | |
| 995 self.assertEqual(isitthere, True) | |
| 996 | |
| 990 form2.update({'@csrf': nonce}) | 997 form2.update({'@csrf': nonce}) |
| 991 # add a real csrf field to the form and rerun the inner_main | 998 # add a real csrf field to the form and rerun the inner_main |
| 992 cl.form = makeForm(form2) | 999 cl.form = makeForm(form2) |
| 993 cl.inner_main() | 1000 cl.inner_main() |
| 994 # csrf passes and redirects to the new issue. | 1001 # csrf passes and redirects to the new issue. |
| 995 match_at=out[0].find('Redirecting to <a href="http://whoami.com/path/issue1?@ok_message') | 1002 match_at=out[0].find('Redirecting to <a href="http://whoami.com/path/issue1?@ok_message') |
| 996 self.assertEqual(match_at, 0) | 1003 self.assertEqual(match_at, 0) |
| 1004 del(out[0]) | |
| 1005 | |
| 1006 # try a replay attack | |
| 1007 cl.inner_main() | |
| 1008 # This should fail as token was wiped by last run. | |
| 1009 match_at=out[0].find('Invalid csrf token found: %s'%nonce) | |
| 1010 print "replay of csrf after post use", out[0] | |
| 1011 self.assertEqual(match_at, 36) | |
| 1012 del(out[0]) | |
| 1013 | |
| 1014 # make sure that a get deletes the csrf. | |
| 1015 cl.env['REQUEST_METHOD'] = 'GET' | |
| 1016 cl.env['HTTP_REFERER'] = 'http://whoami.com/path/' | |
| 1017 form2 = copy.copy(form) | |
| 1018 nonce = anti_csrf_nonce(cl, cl) | |
| 1019 form2.update({'@csrf': nonce}) | |
| 1020 # add a real csrf field to the form and rerun the inner_main | |
| 1021 cl.form = makeForm(form2) | |
| 1022 cl.inner_main() | |
| 1023 # csrf passes but fail creating new issue because not a post | |
| 1024 match_at=out[0].find('<p>Invalid request</p>') | |
| 1025 self.assertEqual(match_at, 33) | |
| 1026 del(out[0]) | |
| 1027 | |
| 1028 # the token should be gone | |
| 1029 isitthere = otks.exists(nonce) | |
| 1030 self.assertEqual(isitthere, False) | |
| 1031 | |
| 1032 # change to post and should fail w/ invalid csrf | |
| 1033 # since get deleted the token. | |
| 1034 cl.env.update({'REQUEST_METHOD': 'POST'}) | |
| 1035 print cl.env | |
| 1036 cl.inner_main() | |
| 1037 match_at=out[0].find('Invalid csrf token found: %s'%nonce) | |
| 1038 print "post failure after get", out[0] | |
| 1039 self.assertEqual(match_at, 36) | |
| 1040 del(out[0]) | |
| 1041 | |
| 997 del(cl.env['HTTP_REFERER']) | 1042 del(cl.env['HTTP_REFERER']) |
| 998 del(out[0]) | 1043 |
| 999 | |
| 1000 # clean up from email log | 1044 # clean up from email log |
| 1001 if os.path.exists(SENDMAILDEBUG): | 1045 if os.path.exists(SENDMAILDEBUG): |
| 1002 os.remove(SENDMAILDEBUG) | 1046 os.remove(SENDMAILDEBUG) |
| 1003 #raise ValueError | 1047 #raise ValueError |
| 1004 | 1048 |
