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\" /> <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=\"\" /> ");
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;