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).

@@ -39,7 +39,7 @@ class WebApplication(tornado.web.Application): @@ -39,7 +39,7 @@ class WebApplication(tornado.web.Application):
39 'template_path': path.join(path.dirname(__file__), 'templates'), 39 'template_path': path.join(path.dirname(__file__), 'templates'),
40 'static_path': path.join(path.dirname(__file__), 'static'), 40 'static_path': path.join(path.dirname(__file__), 'static'),
41 'static_url_prefix': '/static/', 41 'static_url_prefix': '/static/',
42 - 'xsrf_cookies': False, # FIXME not needed on private network 42 + 'xsrf_cookies': True,
43 'cookie_secret': base64.b64encode(uuid.uuid4().bytes), 43 'cookie_secret': base64.b64encode(uuid.uuid4().bytes),
44 'login_url': '/login', 44 'login_url': '/login',
45 'debug': debug, 45 'debug': debug,
@@ -105,7 +105,7 @@ class LogoutHandler(BaseHandler): @@ -105,7 +105,7 @@ class LogoutHandler(BaseHandler):
105 # Based on https://bhch.github.io/posts/2017/12/serving-large-files-with-tornado-safely-without-blocking/ 105 # Based on https://bhch.github.io/posts/2017/12/serving-large-files-with-tornado-safely-without-blocking/
106 # ---------------------------------------------------------------------------- 106 # ----------------------------------------------------------------------------
107 class FileHandler(BaseHandler): 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 @tornado.web.authenticated 110 @tornado.web.authenticated
111 async def get(self): 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 $(document).ready(function() { 14 $(document).ready(function() {
2 function button_handlers() { 15 function button_handlers() {
3 // button handlers (runs once) 16 // button handlers (runs once)
@@ -13,28 +26,20 @@ $(document).ready(function() { @@ -13,28 +26,20 @@ $(document).ready(function() {
13 ); 26 );
14 $("#reset_password").click( 27 $("#reset_password").click(
15 function () { 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 $("#inserir_novo_aluno").click( 35 $("#inserir_novo_aluno").click(
27 function () { 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,20 +51,12 @@ $(document).ready(function() {
46 // checkbox handler to allow/deny students individually 51 // checkbox handler to allow/deny students individually
47 function autorizeStudent(e) { 52 function autorizeStudent(e) {
48 if (this.checked) { 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 else { 57 else {
57 // $(this).parent().parent().removeClass("active"); 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,7 +24,7 @@
24 <script defer src="/static/fontawesome.min.js"></script> 24 <script defer src="/static/fontawesome.min.js"></script>
25 <script defer src="/static/popper.min.js"></script> 25 <script defer src="/static/popper.min.js"></script>
26 <script defer src="/static/bootstrap/js/bootstrap.min.js"></script> 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 <script defer src="/static/js/admin.js"></script> 29 <script defer src="/static/js/admin.js"></script>
30 <script defer src="/static/js/clock.js"></script> 30 <script defer src="/static/js/clock.js"></script>
@@ -140,7 +140,6 @@ @@ -140,7 +140,6 @@
140 <label for="reset_number" class="col-sm-2 col-form-label">Número</label> 140 <label for="reset_number" class="col-sm-2 col-form-label">Número</label>
141 <div class="col-sm-10"> 141 <div class="col-sm-10">
142 <input id="reset_number" type="text" class="form-control"> 142 <input id="reset_number" type="text" class="form-control">
143 - <!-- <input type="text" class="form-control" id="novo_numero" value=""> -->  
144 </div> 143 </div>
145 </div> 144 </div>
146 </div> 145 </div>
templates/test.html
@@ -92,6 +92,8 @@ @@ -92,6 +92,8 @@
92 </div> 92 </div>
93 93
94 <form action="/test" method="post" id="test" autocomplete="off"> 94 <form action="/test" method="post" id="test" autocomplete="off">
  95 + {% module xsrf_form_html() %}
  96 +
95 {% for i, q in enumerate(t['questions']) %} 97 {% for i, q in enumerate(t['questions']) %}
96 {% module Template(templ[q['type']], i=i, q=q, md=md(q['ref']), show_ref=t['show_ref']) %} 98 {% module Template(templ[q['type']], i=i, q=q, md=md(q['ref']), show_ref=t['show_ref']) %}
97 {% end %} 99 {% end %}