Author: toad
Date: 2006-06-10 21:37:41 +0000 (Sat, 10 Jun 2006)
New Revision: 9140

Modified:
   trunk/freenet/src/freenet/clients/http/ConfigToadlet.java
   trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
   trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
   trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java
   trunk/freenet/src/freenet/clients/http/PluginToadlet.java
   trunk/freenet/src/freenet/clients/http/PproxyToadlet.java
   trunk/freenet/src/freenet/clients/http/QueueToadlet.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/PeerNode.java
   trunk/freenet/src/freenet/node/Version.java
Log:
801: Fix cross-site-scripting possibles by including a random string as a 
hidden field on every form.

Modified: trunk/freenet/src/freenet/clients/http/ConfigToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ConfigToadlet.java   2006-06-10 
20:36:46 UTC (rev 9139)
+++ trunk/freenet/src/freenet/clients/http/ConfigToadlet.java   2006-06-10 
21:37:41 UTC (rev 9140)
@@ -8,25 +8,30 @@
 import freenet.config.Config;
 import freenet.config.Option;
 import freenet.config.SubConfig;
+import freenet.node.Node;
 import freenet.support.Bucket;
 import freenet.support.BucketTools;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
+import freenet.support.MultiValueTable;


 // FIXME: add logging, comments
 public class ConfigToadlet extends Toadlet {
        private Config config;
+       private final Node node;

-       ConfigToadlet(HighLevelSimpleClient client, Config conf) {
+       ConfigToadlet(HighLevelSimpleClient client, Config conf, Node node) {
                super(client);
                config=conf;
+               this.node = node;
        }

        public void handlePost(URI uri, Bucket data, ToadletContext ctx) throws 
ToadletContextClosedException, IOException {
                StringBuffer errbuf = new StringBuffer();
                SubConfig[] sc = config.getConfigs();

+               // FIXME this is stupid, use a direct constructor

                if(data.size() > 1024*1024) {
                        this.writeReply(ctx, 400, "text/plain", "Too big", "Too 
much data, config servlet limited to 1MB");
@@ -41,6 +46,15 @@
                        Logger.error(this, "Impossible: "+e, e);
                        return;
                }
+               
+               String pass = request.getParam("formPassword");
+               if(pass == null || !pass.equals(node.formPassword)) {
+                       MultiValueTable headers = new MultiValueTable();
+                       headers.put("Location", "/queue/");
+                       ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+                       return;
+               }
+               
                for(int i=0; i<sc.length ; i++){
                        Option[] o = sc[i].getOptions();
                        String prefix = new String(sc[i].getPrefix());
@@ -112,6 +126,7 @@
                buf.append("</div>\n");
                buf.append("<div class=\"infobox-content\">\n");
                buf.append("<form method=\"post\" action=\".\">");
+               buf.append("<input type=\"hidden\" name=\"formPassword\" 
value=\""+node.formPassword+"\">");

                //String last = null;


Modified: trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2006-06-10 20:36:46 UTC (rev 9139)
+++ trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2006-06-10 21:37:41 UTC (rev 9140)
@@ -319,6 +319,7 @@
                        buf.append(buf2);
                        //
                        buf.append("<input type=\"submit\" name=\"remove\" 
value=\"Remove selected peers\" />&nbsp;&nbsp;&nbsp;<span 
class=\"darknet_connections\">* Requesting ARK</span>\n");
+                       buf.append("<input type=\"hidden\" 
name=\"formPassword\" value=\""+node.formPassword+"\">");
                        buf.append("</form>\n");
                }
                buf.append("</div>\n");
@@ -340,6 +341,7 @@
                buf.append("or file:\n");
                buf.append("<input id=\"reffile\" type=\"file\" 
name=\"reffile\" />\n");
                buf.append("<br />\n");
+               buf.append("<input type=\"hidden\" name=\"formPassword\" 
value=\""+node.formPassword+"\">");
                buf.append("<input type=\"submit\" name=\"add\" value=\"Add\" 
/>\n");
                buf.append("</form>\n");
                buf.append("</div>\n");
@@ -370,6 +372,14 @@

                HTTPRequest request = new HTTPRequest(uri, data, ctx);

+               String pass = request.getPartAsString("formPassword", 32);
+               if(pass == null || !pass.equals(node.formPassword)) {
+                       MultiValueTable headers = new MultiValueTable();
+                       headers.put("Location", "/darknet/");
+                       ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+                       return;
+               }
+               
                if (request.isPartSet("add")) {
                        // add a new node
                        String urltext = request.getPartAsString("url", 100);

Modified: trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2006-06-10 
20:36:46 UTC (rev 9139)
+++ trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2006-06-10 
21:37:41 UTC (rev 9140)
@@ -343,16 +343,16 @@
                        node.setFProxy(fproxy);
                        server.register(fproxy, "/", false);

-                       PproxyToadlet pproxy = new PproxyToadlet(client, 
node.pluginManager);
+                       PproxyToadlet pproxy = new PproxyToadlet(client, 
node.pluginManager, node);
                        server.register(pproxy, "/plugins/", true);

                        WelcomeToadlet welcometoadlet = new 
WelcomeToadlet(client, node, fproxyConfig);
                        server.register(welcometoadlet, "/welcome/", true);

-                       PluginToadlet pluginToadlet = new PluginToadlet(client, 
node.pluginManager2);
+                       PluginToadlet pluginToadlet = new PluginToadlet(client, 
node.pluginManager2, node);
                        server.register(pluginToadlet, "/plugin/", true);

-                       ConfigToadlet configtoadlet = new ConfigToadlet(client, 
config);
+                       ConfigToadlet configtoadlet = new ConfigToadlet(client, 
config, node);
                        server.register(configtoadlet, "/config/", true);

                        StaticToadlet statictoadlet = new StaticToadlet(client);

Modified: trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java    2006-06-10 
20:36:46 UTC (rev 9139)
+++ trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java    2006-06-10 
21:37:41 UTC (rev 9140)
@@ -75,6 +75,7 @@
       }

       buf.append("<form action=\".\" method=\"post\" 
enctype=\"multipart/form-data\">\n");
+      buf.append("<input type=\"hidden\" name=\"formPassword\" 
value=\""+node.formPassword+"\">");
       buf.append("<div class=\"infobox infobox-normal\">");
       buf.append("<div class=\"infobox-header\">");
       buf.append("Sending Node To Node Text Message to 
"+HTMLEncoder.encode(peernode_name)+"\n");
@@ -104,6 +105,14 @@
     HTTPRequest request = new HTTPRequest(uri, data, ctx);
     StringBuffer buf = new StringBuffer(1024);

+       String pass = request.getPartAsString("formPassword", 32);
+       if(pass == null || !pass.equals(node.formPassword)) {
+               MultiValueTable headers = new MultiValueTable();
+               headers.put("Location", "/send_n2ntm/");
+               ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+               return;
+       }
+       
     if (request.isPartSet("send")) {
       String message = request.getPartAsString("message", 2000);
       message = message.trim();

Modified: trunk/freenet/src/freenet/clients/http/PluginToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/PluginToadlet.java   2006-06-10 
20:36:46 UTC (rev 9139)
+++ trunk/freenet/src/freenet/clients/http/PluginToadlet.java   2006-06-10 
21:37:41 UTC (rev 9140)
@@ -7,11 +7,13 @@
 import java.net.URI;

 import freenet.client.HighLevelSimpleClient;
+import freenet.node.Node;
 import freenet.plugin.HttpPlugin;
 import freenet.plugin.Plugin;
 import freenet.plugin.PluginManager;
 import freenet.support.Bucket;
 import freenet.support.HTMLEncoder;
+import freenet.support.MultiValueTable;

 /**
  * Toadlet for the plugin manager.
@@ -23,6 +25,7 @@

        /** The plugin manager backing this toadlet. */
        private final PluginManager pluginManager;
+       private final Node node;

        /**
         * Creates a new toadlet.
@@ -32,9 +35,10 @@
         * @param pluginManager
         *            The plugin manager to use
         */
-       protected PluginToadlet(HighLevelSimpleClient client, PluginManager 
pluginManager) {
+       protected PluginToadlet(HighLevelSimpleClient client, PluginManager 
pluginManager, Node n) {
                super(client);
                this.pluginManager = pluginManager;
+               this.node = n;
        }

        /**
@@ -116,6 +120,14 @@
                        return;
                }

+               String pass = httpRequest.getParam("formPassword");
+               if(pass == null || !pass.equals(node.formPassword)) {
+                       MultiValueTable headers = new MultiValueTable();
+                       headers.put("Location", "/plugin/");
+                       ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+                       return;
+               }
+               
                String action = httpRequest.getParam("action");
                if (action.length() == 0) {
                        writePermanentRedirect(ctx, "Plugin list", 
"?action=list");
@@ -206,8 +218,12 @@
                        } else {
                                outputBuffer.append("<td/>");
                        }
-                       outputBuffer.append("<td><form action=\"./\" 
method=\"post\"><input type=\"hidden\" name=\"action\" value=\"reload\"/><input 
type=\"hidden\" name=\"pluginName\" value=\"").append(internalName).append("\" 
/><input type=\"submit\" value=\"Reload\" /></form></td>");
-                       outputBuffer.append("<td><form action=\"./\" 
method=\"post\"><input type=\"hidden\" name=\"action\" value=\"unload\"/><input 
type=\"hidden\" name=\"pluginName\" value=\"").append(internalName).append("\" 
/><input type=\"submit\" value=\"Unload\" /></form></td>");
+                       outputBuffer.append("<td><form action=\"./\" 
method=\"post\"><input type=\"hidden\" name=\"action\" value=\"reload\"/><input 
type=\"hidden\" name=\"pluginName\" value=\"").append(internalName).append("\" 
/><input type=\"submit\" value=\"Reload\" />" +
+                                       "<input type=\"hidden\" 
name=\"formPassword\" value=\""+node.formPassword+"\">"+
+                                       "</form></td>");
+                       outputBuffer.append("<td><form action=\"./\" 
method=\"post\"><input type=\"hidden\" name=\"action\" value=\"unload\"/><input 
type=\"hidden\" name=\"pluginName\" value=\"").append(internalName).append("\" 
/><input type=\"submit\" value=\"Unload\" />" +
+                                       "<input type=\"hidden\" 
name=\"formPassword\" value=\""+node.formPassword+"\">"+
+                                       "</form></td>");
                        outputBuffer.append("</tr>\n");
                }
                outputBuffer.append("</table>");
@@ -259,6 +275,7 @@
                outputBuffer.append("<div class=\"infobox-content\">");
                outputBuffer.append("<form action=\"./\" method=\"post\">");
                outputBuffer.append("<input type=\"hidden\" name=\"action\" 
value=\"add\" />");
+               outputBuffer.append("<input type=\"hidden\" 
name=\"formPassword\" value=\""+node.formPassword+"\">");
                outputBuffer.append("<input type=\"text\" size=\"40\" 
name=\"pluginName\" value=\"\" />&nbsp;");
                outputBuffer.append("<input type=\"submit\" value=\"Load 
plugin\" />");
                outputBuffer.append("</form>");

Modified: trunk/freenet/src/freenet/clients/http/PproxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/PproxyToadlet.java   2006-06-10 
20:36:46 UTC (rev 9139)
+++ trunk/freenet/src/freenet/clients/http/PproxyToadlet.java   2006-06-10 
21:37:41 UTC (rev 9140)
@@ -9,6 +9,7 @@
 import java.util.Iterator;

 import freenet.client.HighLevelSimpleClient;
+import freenet.node.Node;
 import freenet.pluginmanager.PluginHTTPException;
 import freenet.pluginmanager.PluginInfoWrapper;
 import freenet.pluginmanager.PluginManager;
@@ -19,11 +20,13 @@
 import freenet.support.MultiValueTable;

 public class PproxyToadlet extends Toadlet {
-       private PluginManager pm = null;
+       private final PluginManager pm;
+       private final Node node;

-       public PproxyToadlet(HighLevelSimpleClient client, PluginManager pm) {
+       public PproxyToadlet(HighLevelSimpleClient client, PluginManager pm, 
Node n) {
                super(client);
                this.pm = pm;
+               this.node = n;
        }

        public String supportedMethods() {
@@ -33,6 +36,8 @@
        public void handlePost(URI uri, Bucket data, ToadletContext ctx)
                throws ToadletContextClosedException, IOException {

+               // FIXME this is archaic! Make it use the direct bucket 
constructor!
+               
                if(data.size() > 1024*1024) {
                        this.writeReply(ctx, 400, "text/plain", "Too big", "Too 
much data, plugin servlet limited to 1MB");
                        return;
@@ -50,6 +55,14 @@
                StringBuffer buf = new StringBuffer();
                MultiValueTable headers = new MultiValueTable();

+               String pass = request.getParam("formPassword");
+               if(pass == null || !pass.equals(node.formPassword)) {
+                       MultiValueTable hdrs = new MultiValueTable();
+                       headers.put("Location", "/queue/");
+                       ctx.sendReplyHeaders(302, "Found", hdrs, null, 0);
+                       return;
+               }
+               
                if (request.isParameterSet("load")) {
                        pm.startPlugin(request.getParam("load"));
                        //writeReply(ctx, 200, "text/html", "OK", 
mkForwardPage("Loading plugin", "Loading plugin...", ".", 5));
@@ -85,6 +98,7 @@
                        buf.append("<div class=\"infobox-content\">\n");
                        buf.append("Are you sure you wish to unload " + 
HTMLEncoder.encode(request.getParam("unload")) + "?\n");
                        buf.append("<form action=\"/plugins/\" 
method=\"post\">\n");
+                       buf.append("<input type=\"hidden\" 
name=\"formPassword\" value=\""+node.formPassword+"\">");
                        buf.append("<input type=\"submit\" name=\"cancel\" 
value=\"Cancel\" />\n");
                        buf.append("<input type=\"hidden\" 
name=\"unloadconfirm\" value=\"" + 
HTMLEncoder.encode(request.getParam("unload")) + "\">\n");
                        buf.append("<input type=\"submit\" name=\"confirm\" 
value=\"Unload\" />\n");
@@ -205,13 +219,16 @@
                                        out.append("<td>");
                                        if (pi.isPproxyPlugin()) {
                                                out.append("<form 
method=\"get\" action=\"" + pi.getPluginClassName() + "\">" +
+                                                               "<input 
type=\"hidden\" name=\"formPassword\" value=\""+node.formPassword+"\">"+
                                                                "<input 
type=\"submit\" value=\"Visit\"></form>");
                                        }
                                        out.append("<form method=\"post\" 
action=\".\">" +
                                                        "<input type=\"hidden\" 
name=\"unload\" value=\"" + pi.getThreadName() + "\" />"+
+                                                       "<input type=\"hidden\" 
name=\"formPassword\" value=\""+node.formPassword+"\">"+
                                                        "<input type=\"submit\" 
value=\"Unload\"></form>");
                                        out.append("<form method=\"post\" 
action=\".\">" +
                                                        "<input type=\"hidden\" 
name=\"reload\" value=\"" + pi.getThreadName() + "\" />"+
+                                                       "<input type=\"hidden\" 
name=\"formPassword\" value=\""+node.formPassword+"\">"+
                                                        "<input type=\"submit\" 
value=\"Reload\"></form>");
                                        out.append("</td></tr>\n");
                                }
@@ -226,7 +243,9 @@

                        // Obsolete
                        //out.append("<form method=\"get\"><div>Remove plugin: 
(enter ID) <input type=\"text\" name=\"remove\" size=40/><input type=\"submit\" 
value=\"Remove\"/></div></form>\n");
-                       out.append("<form method=\"post\" 
action=\".\"><div>Load plugin: <input type=\"text\" name=\"load\" 
size=\"40\"/><input type=\"submit\" value=\"Load\" /></div></form>\n");
+                       out.append("<form method=\"post\" action=\".\">" +
+                                       "<input type=\"hidden\" 
name=\"formPassword\" value=\""+node.formPassword+"\">"+
+                                       "<div>Load plugin: <input type=\"text\" 
name=\"load\" size=\"40\"/><input type=\"submit\" value=\"Load\" 
/></div></form>\n");
                        //
                        out.append("</div>\n");
                        out.append("</div>\n");

Modified: trunk/freenet/src/freenet/clients/http/QueueToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/QueueToadlet.java    2006-06-10 
20:36:46 UTC (rev 9139)
+++ trunk/freenet/src/freenet/clients/http/QueueToadlet.java    2006-06-10 
21:37:41 UTC (rev 9140)
@@ -21,6 +21,7 @@
 import freenet.support.HTMLDecoder;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
+import freenet.support.MultiValueTable;
 import freenet.support.SizeUtil;
 import freenet.support.URLEncoder;

@@ -43,6 +44,14 @@
                }
                HTTPRequest request = new HTTPRequest(uri, data, ctx);

+               String pass = request.getParam("formPassword");
+               if(pass == null || !pass.equals(node.formPassword)) {
+                       MultiValueTable headers = new MultiValueTable();
+                       headers.put("Location", "/queue/");
+                       ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+                       return;
+               }
+               
                if(request.isParameterSet("remove_request") && 
request.getParam("remove_request").length() > 0) {
                        String identifier = request.getParam("identifier");
                        Logger.minor(this, "Removing "+identifier);
@@ -423,6 +432,7 @@
        private void writeDeleteCell(ClientRequest p, StringBuffer buf) {
                buf.append("<td>");
                buf.append("<form action=\"/queue/\" method=\"post\">");
+               buf.append("<input type=\"hidden\" name=\"formPassword\" 
value=\""+node.formPassword+"\">");
                buf.append("<input type=\"hidden\" name=\"identifier\" 
value=\"");
                buf.append(HTMLEncoder.encode(p.getIdentifier()));
                buf.append("\"><input type=\"submit\" name=\"remove_request\" 
value=\"Delete\">");

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-06-10 20:36:46 UTC (rev 
9139)
+++ trunk/freenet/src/freenet/node/Node.java    2006-06-10 21:37:41 UTC (rev 
9140)
@@ -561,6 +561,8 @@
     final RequestStarter sskInsertStarter;
        public final UserAlertManager alerts;
        final RunningAverage throttledPacketSendAverage;
+       /** Must be included as a hidden field in order for any dangerous HTTP 
operation to complete successfully. */
+       public final String formPassword;

     File downloadDir;
     public final ClientRequestScheduler chkFetchScheduler;
@@ -886,6 +888,9 @@
      */
      Node(Config config, RandomSource random, LoggingConfigHandler lc, 
NodeStarter ns) throws NodeInitException {
        // Easy stuff
+       byte[] pwdBuf = new byte[16];
+       random.nextBytes(pwdBuf);
+       this.formPassword = Base64.encode(pwdBuf);
        nodeStarter=ns;
        if(logConfigHandler != lc)
                logConfigHandler=lc;

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2006-06-10 20:36:46 UTC 
(rev 9139)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2006-06-10 21:37:41 UTC 
(rev 9140)
@@ -6,7 +6,6 @@
 import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
-import java.net.InetAddress;
 import java.net.MalformedURLException;
 import java.net.UnknownHostException;
 import java.security.MessageDigest;

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-06-10 20:36:46 UTC (rev 
9139)
+++ trunk/freenet/src/freenet/node/Version.java 2006-06-10 21:37:41 UTC (rev 
9140)
@@ -18,7 +18,7 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       private static final int buildNumber = 800;
+       private static final int buildNumber = 801;

        /** Oldest build of Fred we will talk to */
        private static final int lastGoodBuild = 765;


Reply via email to