Commit a08905e35197e2fa9b5e9c0b2187c6d3754cce63

Authored by Miguel Barão
1 parent a305bb5d
Exists in master and in 1 other branch dev

- improved security against cross-site request forgery (XRSF).

serve.py
... ... @@ -39,7 +39,7 @@ class WebApplication(tornado.web.Application):
39 39 'template_path': path.join(path.dirname(__file__), 'templates'),
40 40 'static_path': path.join(path.dirname(__file__), 'static'),
41 41 'static_url_prefix': '/static/',
42   - 'xsrf_cookies': False, # FIXME not needed on private network
  42 + 'xsrf_cookies': True,
43 43 'cookie_secret': base64.b64encode(uuid.uuid4().bytes),
44 44 'login_url': '/login',
45 45 'debug': debug,
... ... @@ -105,7 +105,7 @@ class LogoutHandler(BaseHandler):
105 105 # Based on https://bhch.github.io/posts/2017/12/serving-large-files-with-tornado-safely-without-blocking/
106 106 # ----------------------------------------------------------------------------
107 107 class FileHandler(BaseHandler):
108   - chunk_size = 1024 * 1024 # serve up to 1 MiB multiple times
  108 + chunk_size = 512 * 1024 # serve up to 512 KiB multiple times
109 109  
110 110 @tornado.web.authenticated
111 111 async def get(self):
... ...
static/js/admin.js
  1 +// from: https://www.tornadoweb.org/en/stable/guide/security.html
  2 +// with changes: removed datatype and callback from original postJSON
  3 +function getCookie(name) {
  4 + var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
  5 + return r ? r[1] : undefined;
  6 +}
  7 +
  8 +jQuery.postJSON = function(url, args) {
  9 + args._xsrf = getCookie("_xsrf");
  10 + $.ajax({url: url, data: $.param(args), type: "POST"});
  11 +};
  12 +
  13 +// ---------------------------------------------------------------------------
1 14 $(document).ready(function() {
2 15 function button_handlers() {
3 16 // button handlers (runs once)
... ... @@ -13,28 +26,20 @@ $(document).ready(function() {
13 26 );
14 27 $("#reset_password").click(
15 28 function () {
16   - $.ajax({
17   - type: "POST",
18   - url: "/admin",
19   - data: {
20   - "cmd": "reset_password",
21   - "value": $("#reset_number").val()
22   - }
  29 + $.postJSON("/admin", {
  30 + "cmd": "reset_password",
  31 + "value": $("#reset_number").val()
23 32 });
24 33 }
25 34 );
26 35 $("#inserir_novo_aluno").click(
27 36 function () {
28   - $.ajax({
29   - type: "POST",
30   - url: "/admin",
31   - data: {
32   - "cmd": "insert_student",
33   - "value": JSON.stringify({
34   - "number": $("#novo_numero").val(),
35   - "name": $("#novo_nome").val()
36   - })
37   - }
  37 + $.postJSON("/admin", {
  38 + "cmd": "insert_student",
  39 + "value": JSON.stringify({
  40 + "number": $("#novo_numero").val(),
  41 + "name": $("#novo_nome").val()
  42 + })
38 43 });
39 44 }
40 45 );
... ... @@ -46,20 +51,12 @@ $(document).ready(function() {
46 51 // checkbox handler to allow/deny students individually
47 52 function autorizeStudent(e) {
48 53 if (this.checked) {
49   - $(this).parent().parent().addClass("table-primary"); // row class
50   - $.ajax({
51   - type: "POST",
52   - url: "/admin",
53   - data: {"cmd": "allow", "value": this.name}
54   - });
  54 + // $(this).parent().parent().addClass("table-primary"); // row class
  55 + $.postJSON("/admin", {"cmd": "allow", "value": this.name});
55 56 }
56 57 else {
57 58 // $(this).parent().parent().removeClass("active");
58   - $.ajax({
59   - type: "POST",
60   - url: "/admin",
61   - data: {"cmd": "deny", "value": this.name}
62   - });
  59 + $.postJSON("/admin", {"cmd": "deny", "value": this.name});
63 60 }
64 61 }
65 62  
... ...
templates/admin.html
... ... @@ -24,7 +24,7 @@
24 24 <script defer src="/static/fontawesome.min.js"></script>
25 25 <script defer src="/static/popper.min.js"></script>
26 26 <script defer src="/static/bootstrap/js/bootstrap.min.js"></script>
27   - <script type="text/javascript" src="/static/DataTables/datatables.min.js"></script>
  27 + <script defer src="/static/DataTables/datatables.min.js"></script>
28 28  
29 29 <script defer src="/static/js/admin.js"></script>
30 30 <script defer src="/static/js/clock.js"></script>
... ... @@ -140,7 +140,6 @@
140 140 <label for="reset_number" class="col-sm-2 col-form-label">Número</label>
141 141 <div class="col-sm-10">
142 142 <input id="reset_number" type="text" class="form-control">
143   - <!-- <input type="text" class="form-control" id="novo_numero" value=""> -->
144 143 </div>
145 144 </div>
146 145 </div>
... ...
templates/test.html
... ... @@ -92,6 +92,8 @@
92 92 </div>
93 93  
94 94 <form action="/test" method="post" id="test" autocomplete="off">
  95 + {% module xsrf_form_html() %}
  96 +
95 97 {% for i, q in enumerate(t['questions']) %}
96 98 {% module Template(templ[q['type']], i=i, q=q, md=md(q['ref']), show_ref=t['show_ref']) %}
97 99 {% end %}
... ...