luci-mod-admin-full: protect network post actions with csrf tokens
authorJo-Philipp Wich <jow@openwrt.org>
Tue, 20 Oct 2015 20:17:23 +0000 (22:17 +0200)
committerJo-Philipp Wich <jow@openwrt.org>
Tue, 20 Oct 2015 20:17:23 +0000 (22:17 +0200)
Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
modules/luci-mod-admin-full/luasrc/controller/admin/network.lua
modules/luci-mod-admin-full/luasrc/view/admin_network/diagnostics.htm
modules/luci-mod-admin-full/luasrc/view/admin_network/iface_overview.htm
modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_join.htm
modules/luci-mod-admin-full/luasrc/view/admin_network/wifi_overview.htm

index 6e578e0..879e54b 100644 (file)
@@ -1,5 +1,5 @@
 -- Copyright 2008 Steven Barth <steven@midlink.org>
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
+-- Copyright 2011-2015 Jo-Philipp Wich <jow@openwrt.org>
 -- Licensed to the public under the Apache License 2.0.
 
 module("luci.controller.admin.network", package.seeall)
@@ -43,22 +43,22 @@ function index()
                        end)
 
                if has_wifi then
-                       page = entry({"admin", "network", "wireless_join"}, call("wifi_join"), nil)
+                       page = entry({"admin", "network", "wireless_join"}, post("wifi_join"), nil)
                        page.leaf = true
 
-                       page = entry({"admin", "network", "wireless_add"}, call("wifi_add"), nil)
+                       page = entry({"admin", "network", "wireless_add"}, post("wifi_add"), nil)
                        page.leaf = true
 
-                       page = entry({"admin", "network", "wireless_delete"}, call("wifi_delete"), nil)
+                       page = entry({"admin", "network", "wireless_delete"}, post("wifi_delete"), nil)
                        page.leaf = true
 
                        page = entry({"admin", "network", "wireless_status"}, call("wifi_status"), nil)
                        page.leaf = true
 
-                       page = entry({"admin", "network", "wireless_reconnect"}, call("wifi_reconnect"), nil)
+                       page = entry({"admin", "network", "wireless_reconnect"}, post("wifi_reconnect"), nil)
                        page.leaf = true
 
-                       page = entry({"admin", "network", "wireless_shutdown"}, call("wifi_shutdown"), nil)
+                       page = entry({"admin", "network", "wireless_shutdown"}, post("wifi_shutdown"), nil)
                        page.leaf = true
 
                        page = entry({"admin", "network", "wireless"}, arcombine(template("admin_network/wifi_overview"), cbi("admin_network/wifi")), _("Wifi"), 15)
@@ -85,16 +85,16 @@ function index()
                page = entry({"admin", "network", "iface_add"}, cbi("admin_network/iface_add"), nil)
                page.leaf = true
 
-               page = entry({"admin", "network", "iface_delete"}, call("iface_delete"), nil)
+               page = entry({"admin", "network", "iface_delete"}, post("iface_delete"), nil)
                page.leaf = true
 
                page = entry({"admin", "network", "iface_status"}, call("iface_status"), nil)
                page.leaf = true
 
-               page = entry({"admin", "network", "iface_reconnect"}, call("iface_reconnect"), nil)
+               page = entry({"admin", "network", "iface_reconnect"}, post("iface_reconnect"), nil)
                page.leaf = true
 
-               page = entry({"admin", "network", "iface_shutdown"}, call("iface_shutdown"), nil)
+               page = entry({"admin", "network", "iface_shutdown"}, post("iface_shutdown"), nil)
                page.leaf = true
 
                page = entry({"admin", "network", "network"}, arcombine(cbi("admin_network/network"), cbi("admin_network/ifaces")), _("Interfaces"), 10)
@@ -138,44 +138,33 @@ function index()
                page.title  = _("Diagnostics")
                page.order  = 60
 
-               page = entry({"admin", "network", "diag_ping"}, call("diag_ping"), nil)
+               page = entry({"admin", "network", "diag_ping"}, post("diag_ping"), nil)
                page.leaf = true
 
-               page = entry({"admin", "network", "diag_nslookup"}, call("diag_nslookup"), nil)
+               page = entry({"admin", "network", "diag_nslookup"}, post("diag_nslookup"), nil)
                page.leaf = true
 
-               page = entry({"admin", "network", "diag_traceroute"}, call("diag_traceroute"), nil)
+               page = entry({"admin", "network", "diag_traceroute"}, post("diag_traceroute"), nil)
                page.leaf = true
 
-               page = entry({"admin", "network", "diag_ping6"}, call("diag_ping6"), nil)
+               page = entry({"admin", "network", "diag_ping6"}, post("diag_ping6"), nil)
                page.leaf = true
 
-               page = entry({"admin", "network", "diag_traceroute6"}, call("diag_traceroute6"), nil)
+               page = entry({"admin", "network", "diag_traceroute6"}, post("diag_traceroute6"), nil)
                page.leaf = true
 --     end
 end
 
 function wifi_join()
-       local function param(x)
-               return luci.http.formvalue(x)
-       end
-
-       local function ptable(x)
-               x = param(x)
-               return x and (type(x) ~= "table" and { x } or x) or {}
-       end
-
-       local dev  = param("device")
-       local ssid = param("join")
+       local tpl  = require "luci.template"
+       local http = require "luci.http"
+       local dev  = http.formvalue("device")
+       local ssid = http.formvalue("join")
 
        if dev and ssid then
-               local cancel  = (param("cancel") or param("cbi.cancel")) and true or false
-
-               if cancel then
-                       luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless_join?device=" .. dev))
-               else
+               local cancel = (http.formvalue("cancel") or http.formvalue("cbi.cancel"))
+               if not cancel then
                        local cbi = require "luci.cbi"
-                       local tpl = require "luci.template"
                        local map = luci.cbi.load("admin_network/wifi_add")[1]
 
                        if map:parse() ~= cbi.FORM_DONE then
@@ -183,10 +172,12 @@ function wifi_join()
                                map:render()
                                tpl.render("footer")
                        end
+
+                       return
                end
-       else
-               luci.template.render("admin_network/wifi_join")
        end
+
+       tpl.render("admin_network/wifi_join")
 end
 
 function wifi_add()
index e06a88d..685082a 100644 (file)
@@ -34,7 +34,7 @@ local has_traceroute6 = fs.access("/usr/bin/traceroute6")
                        legend.parentNode.style.display = 'block';
                        legend.style.display = 'inline';
 
-                       stxhr.get('<%=url('admin/network')%>/diag_' + tool + protocol + '/' + addr, null,
+                       stxhr.post('<%=url('admin/network')%>/diag_' + tool + protocol + '/' + addr, { token: '<%=token%>' },
                                function(x)
                                {
                                        if (x.responseText)
@@ -53,7 +53,7 @@ local has_traceroute6 = fs.access("/usr/bin/traceroute6")
        }
 //]]></script>
 
-<form method="post" action="<%=pcdata(luci.http.getenv("REQUEST_URI"))%>">
+<form method="post" action="<%=url('admin/network/diagnostics')%>">
        <div class="cbi-map">
                <h2 name="content"><%:Diagnostics%></h2>
 
index 4cdf2df..9a77f89 100644 (file)
@@ -49,7 +49,7 @@
                        s.innerHTML = '<%:Waiting for changes to be applied...%>';
                }
 
-               XHR.get('<%=url('admin/network')%>/iface_' + (reconnect ? 'reconnect' : 'shutdown') + '/' + id, null,
+               (new XHR()).post('<%=url('admin/network')%>/iface_' + (reconnect ? 'reconnect' : 'shutdown') + '/' + id, { token: '<%=token%>' },
                        function(x)
                        {
                                if (s)
                );
        }
 
+       function iface_delete(id) {
+               if (!confirm('<%:Really delete this interface? The deletion cannot be undone!\nYou might lose access to this device if you are connected via this interface.%>'))
+                       return;
+
+               (new XHR()).post('<%=url('admin/network/iface_delete')%>/' + id, { token: '<%=token%>' },
+                       function(x) {
+                               location.href = '<%=url('admin/network/network')%>';
+                       }
+               );
+       }
 
        var iwxhr = new XHR();
        var wifidevs = <%=luci.http.write_json(netdevs)%>;
                                                <input type="button" class="cbi-button cbi-button-reload" style="width:100px" onclick="iface_shutdown('<%=net[1]%>', true)" title="<%:Reconnect this interface%>" value="<%:Connect%>" />
                                                <input type="button" class="cbi-button cbi-button-reset" style="width:100px" onclick="iface_shutdown('<%=net[1]%>', false)" title="<%:Shutdown this interface%>" value="<%:Stop%>" />
                                                <input type="button" class="cbi-button cbi-button-edit" style="width:100px" onclick="location.href='<%=url("admin/network/network", net[1])%>'" title="<%:Edit this interface%>" value="<%:Edit%>" id="<%=net[1]%>-ifc-edit" />
-                                               <input type="button" class="cbi-button cbi-button-remove" style="width:100px" onclick="if (confirm('<%:Really delete this interface? The deletion cannot be undone!\nYou might lose access to this device if you are connected via this interface.%>')) location.href='<%=url("admin/network/iface_delete", net[1])%>'" title="<%:Delete this interface%>" value="<%:Delete%>" />
+                                               <input type="submit" class="cbi-button cbi-button-remove" style="width:100px" onclick="iface_delete('<%=net[1]%>')" value="<%:Delete%>" />
                                        </td>
                                </tr>
                        <% end %>
index 671d16e..3533c6f 100644 (file)
@@ -1,5 +1,5 @@
 <%#
- Copyright 2009 Jo-Philipp Wich <jow@openwrt.org>
+ Copyright 2009-2015 Jo-Philipp Wich <jow@openwrt.org>
  Licensed to the public under the Apache License 2.0.
 -%>
 
                                        <strong>Encryption:</strong> <%=format_wifi_encryption(net.encryption)%>
                                </td>
                                <td class="cbi-value-field" style="width:40px">
-                                       <form action="<%=REQUEST_URI%>" method="post">
+                                       <form action="<%=url('admin/network/wireless_join')%>" method="post">
+                                               <input type="hidden" name="token" value="<%=token%>" />
                                                <input type="hidden" name="device" value="<%=utl.pcdata(dev)%>" />
                                                <input type="hidden" name="join" value="<%=utl.pcdata(net.ssid)%>" />
                                                <input type="hidden" name="mode" value="<%=net.mode%>" />
        <form class="inline" action="<%=url("admin/network/wireless")%>" method="get">
                <input class="cbi-button cbi-button-reset" type="submit" value="<%:Back to overview%>" />
        </form>
-       <form class="inline" action="<%=REQUEST_URI%>" method="get">
+       <form class="inline" action="<%=url('admin/network/wireless_join')%>" method="post">
+               <input type="hidden" name="token" value="<%=token%>" />
                <input type="hidden" name="device" value="<%=utl.pcdata(dev)%>" />
                <input class="cbi-button cbi-input-find" type="submit" value="<%:Repeat scan%>" />
        </form>
index 17afe0d..f82d06d 100644 (file)
                                st.innerHTML = '<em><%:Wireless is restarting...%></em>';
                }
 
-               XHR.get('<%=url('admin/network')%>/wireless_' + (reconnect ? 'reconnect' : 'shutdown') + '/' + id, null,
+               (new XHR()).post('<%=url('admin/network')%>/wireless_' + (reconnect ? 'reconnect' : 'shutdown') + '/' + id, { token: '<%=token%>' },
                        function(x)
                        {
                                if (s)
                );
        }
 
+       function wifi_delete(id) {
+               if (!confirm('<%:Really delete this wireless network? The deletion cannot be undone!\nYou might lose access to this device if you are connected via this network.%>'))
+                       return;
+
+               (new XHR()).post('<%=url('admin/network/wireless_delete')%>/' + id, { token: '<%=token%>' },
+                       function(x) {
+                               location.href = '<%=url('admin/network/wireless')%>';
+                       }
+               );
+       }
+
        XHR.poll(5, '<%=url('admin/network/wireless_status', table.concat(netlist, ","))%>', null,
                function(x, st)
                {
                                        <span id="<%=dev:name()%>-iw-devinfo"></span>
                                </td>
                                <td style="width:310px;text-align:right">
-                                       <input type="button" class="cbi-button cbi-button-find" style="width:100px" onclick="location.href='<%=url("admin/network/wireless_join")%>?device=<%=dev:name()%>'" title="<%:Find and join network%>" value="<%:Scan%>" />
-                                       <input type="button" class="cbi-button cbi-button-add" style="width:100px" onclick="location.href='<%=url("admin/network/wireless_add")%>?device=<%=dev:name()%>'" title="<%:Provide new network%>" value="<%:Add%>" />
+                                       <form action="<%=url('admin/network/wireless_join')%>" method="post" class="inline">
+                                               <input type="hidden" name="device" value="<%=dev:name()%>" />
+                                               <input type="hidden" name="token" value="<%=token%>" />
+                                               <input type="submit" class="cbi-button cbi-button-find" style="width:100px" title="<%:Find and join network%>" value="<%:Scan%>" />
+                                       </form>
+                                       <form action="<%=url('admin/network/wireless_add')%>" method="post" class="inline">
+                                               <input type="hidden" name="device" value="<%=dev:name()%>" />
+                                               <input type="hidden" name="token" value="<%=token%>" />
+                                               <input type="submit" class="cbi-button cbi-button-add" style="width:100px" title="<%:Provide new network%>" value="<%:Add%>" />
+                                       </form>
                                </td>
                        </tr>
                        <!-- /physical device -->
                                        <td class="cbi-value-field" style="width:310px;text-align:right">
                                                <input id="<%=net:id()%>-iw-toggle" type="button" class="cbi-button cbi-button-reload" style="width:100px" onclick="wifi_shutdown('<%=net:id()%>', this)" title="<%:Delete this network%>" value="<%:Enable%>" />
                                                <input type="button" class="cbi-button cbi-button-edit" style="width:100px" onclick="location.href='<%=net:adminlink()%>'" title="<%:Edit this network%>" value="<%:Edit%>" />
-                                               <input type="button" class="cbi-button cbi-button-remove" style="width:100px" onclick="if (confirm('<%:Really delete this wireless network? The deletion cannot be undone!\nYou might lose access to this device if you are connected via this network.%>')) location.href='<%=url("admin/network/wireless_delete", net:ifname())%>'" title="<%:Delete this network%>" value="<%:Remove%>" />
+                                               <input type="button" class="cbi-button cbi-button-remove" style="width:100px" onclick="wifi_delete('<%=net:ifname()%>')" title="<%:Delete this network%>" value="<%:Remove%>" />
                                        </td>
                                </tr>
                                <% end %>
        <% end %>
 
 
-       <h2 name="content"><%:Associated Stations%></h2>
+       <h2><%:Associated Stations%></h2>
 
        <fieldset class="cbi-section">
                <table class="cbi-section-table" style="margin:10px" id="iw-assoclist">