IDEA-216621 xslt debugger plugin misconfiguration allows arbitrary file read over network

introduced access token for eval() call

GitOrigin-RevId: ddcbbfed9b16a8c7e2d09b6c3896aaf321325dc3
This commit is contained in:
Dmitry Avdeev
2019-07-12 20:05:04 +03:00
committed by intellij-monorepo-bot
parent 8e95432bdf
commit a07ac702e0
8 changed files with 44 additions and 27 deletions
@@ -43,10 +43,12 @@ public class DebuggerServer extends PortableRemoteObject implements RemoteDebugg
private final RemoteBreakpointManagerImpl myBreakpointManager;
private final RemoteEventQueueImpl myEventQueue;
private final int myPort;
private final String myAccessToken;
private DebuggerServer(Transformer transformer, Source xml, Result out, int port)
throws TransformerConfigurationException, RemoteException {
myPort = port;
myAccessToken = System.getProperty("xslt.debugger.token");
myDebugger = new LocalDebugger(transformer, xml, out) {
@Override
public void stop(boolean b) {
@@ -115,15 +117,15 @@ public class DebuggerServer extends PortableRemoteObject implements RemoteDebugg
}
public Frame getCurrentFrame() throws RemoteException {
return RemoteFrameImpl.create(myDebugger.getCurrentFrame());
return RemoteFrameImpl.create(myDebugger.getCurrentFrame(), myAccessToken);
}
public Frame getSourceFrame() throws RemoteException {
return RemoteFrameImpl.create(myDebugger.getSourceFrame());
return RemoteFrameImpl.create(myDebugger.getSourceFrame(), myAccessToken);
}
public Value eval(String expr) throws RemoteException, Debugger.EvaluationException {
return getCurrentFrame().eval(expr);
public Value eval(String expr, String accessToken) throws RemoteException, Debugger.EvaluationException {
return getCurrentFrame().eval(expr, accessToken);
}
public List<Variable> getGlobalVariables() throws RemoteException {
Binary file not shown.
@@ -47,7 +47,7 @@ public interface RemoteDebugger extends Remote {
Frame getSourceFrame() throws RemoteException;
Value eval(String expr) throws RemoteException, Debugger.EvaluationException;
Value eval(String expr, String accessToken) throws RemoteException, Debugger.EvaluationException;
List<Variable> getGlobalVariables() throws RemoteException;
@@ -76,7 +76,7 @@ public interface RemoteDebugger extends Remote {
String getXPath() throws RemoteException;
Value eval(String expr) throws RemoteException, Debugger.EvaluationException;
Value eval(String expr, String accessToken) throws RemoteException, Debugger.EvaluationException;
List<Variable> getVariables() throws RemoteException;
@@ -30,11 +30,13 @@ import java.util.List;
public class RemoteDebuggerClient implements Debugger {
private final RemoteDebugger myRemote;
private final String myAccessToken;
private final BreakpointManager myBreakpointManager;
private final OutputEventQueue myEventQueue;
public RemoteDebuggerClient(int port) throws IOException, NotBoundException {
public RemoteDebuggerClient(int port, String accessToken) throws IOException, NotBoundException {
myRemote = (RemoteDebugger)Naming.lookup("rmi://127.0.0.1:" + port + "/XsltDebugger");
myAccessToken = accessToken;
final RemoteBreakpointManager manager = myRemote.getBreakpointManager();
myBreakpointManager = new MyBreakpointManager(manager);
@@ -144,7 +146,7 @@ public class RemoteDebuggerClient implements Debugger {
public StyleFrame getCurrentFrame() {
try {
return MyFrame.create(myRemote.getCurrentFrame());
return new MyFrame(myRemote.getCurrentFrame());
} catch (RemoteException e) {
throw handleRemoteException(e);
}
@@ -152,7 +154,7 @@ public class RemoteDebuggerClient implements Debugger {
public SourceFrame getSourceFrame() {
try {
return MySourceFrame.create(myRemote.getSourceFrame());
return new MySourceFrame(myRemote.getSourceFrame());
} catch (RemoteException e) {
throw handleRemoteException(e);
}
@@ -160,7 +162,7 @@ public class RemoteDebuggerClient implements Debugger {
public Value eval(String expr) throws EvaluationException {
try {
return myRemote.eval(expr);
return myRemote.eval(expr, myAccessToken);
} catch (RemoteException e) {
throw handleRemoteException(e);
}
@@ -348,7 +350,7 @@ public class RemoteDebuggerClient implements Debugger {
}
}
private static abstract class MyAbstractFrame<F extends Frame> implements Frame<F> {
private abstract class MyAbstractFrame<F extends Frame> implements Frame<F> {
protected final RemoteDebugger.Frame myFrame;
protected MyAbstractFrame(RemoteDebugger.Frame frame) {
@@ -399,7 +401,7 @@ public class RemoteDebuggerClient implements Debugger {
public Value eval(String expr) throws EvaluationException {
try {
return myFrame.eval(expr);
return myFrame.eval(expr, myAccessToken);
} catch (RemoteException e) {
throw handleRemoteException(e);
}
@@ -414,7 +416,7 @@ public class RemoteDebuggerClient implements Debugger {
}
}
private static class MyFrame extends MyAbstractFrame<StyleFrame> implements StyleFrame {
private class MyFrame extends MyAbstractFrame<StyleFrame> implements StyleFrame {
protected MyFrame(RemoteDebugger.Frame frame) {
super(frame);
}
@@ -432,12 +434,12 @@ public class RemoteDebuggerClient implements Debugger {
return create(frame);
}
public static StyleFrame create(RemoteDebugger.Frame currentFrame) {
public StyleFrame create(RemoteDebugger.Frame currentFrame) {
return currentFrame != null ? new MyFrame(currentFrame) : null;
}
}
private static class MySourceFrame extends MyAbstractFrame<SourceFrame> implements SourceFrame {
private class MySourceFrame extends MyAbstractFrame<SourceFrame> implements SourceFrame {
protected MySourceFrame(RemoteDebugger.Frame frame) {
super(frame);
}
@@ -447,7 +449,7 @@ public class RemoteDebuggerClient implements Debugger {
return create(frame);
}
public static SourceFrame create(RemoteDebugger.Frame currentFrame) {
public SourceFrame create(RemoteDebugger.Frame currentFrame) {
return currentFrame != null ? new MySourceFrame(currentFrame) : null;
}
}
@@ -26,9 +26,11 @@ import java.util.List;
class RemoteFrameImpl extends PortableRemoteObject implements RemoteDebugger.Frame {
private final Frame myFrame;
private final String myAccessToken;
private RemoteFrameImpl(Frame frame) throws RemoteException {
private RemoteFrameImpl(Frame frame, String accessToken) throws RemoteException {
myFrame = frame;
myAccessToken = accessToken;
}
public int getLineNumber() {
@@ -40,18 +42,19 @@ class RemoteFrameImpl extends PortableRemoteObject implements RemoteDebugger.Fra
}
public RemoteDebugger.Frame getNext() throws RemoteException {
return create(myFrame.getNext());
return create(myFrame.getNext(), myAccessToken);
}
public RemoteDebugger.Frame getPrevious() throws RemoteException {
return create(myFrame.getPrevious());
return create(myFrame.getPrevious(), myAccessToken);
}
public String getXPath() throws RemoteException {
return ((Debugger.SourceFrame)myFrame).getXPath();
}
public ValueImpl eval(String expr) throws Debugger.EvaluationException {
public ValueImpl eval(String expr, String accessToken) throws Debugger.EvaluationException, RemoteException {
if (!myAccessToken.equals(accessToken)) throw new RemoteException("Access denied");
final Value value = ((Debugger.StyleFrame)myFrame).eval(expr);
return new ValueImpl(value.getValue(), value.getType());
}
@@ -64,7 +67,7 @@ class RemoteFrameImpl extends PortableRemoteObject implements RemoteDebugger.Fra
return ((Debugger.StyleFrame)myFrame).getInstruction();
}
public static RemoteFrameImpl create(Frame frame) throws RemoteException {
return frame != null ? new RemoteFrameImpl(frame) : null;
public static RemoteFrameImpl create(Frame frame, String accessToken) throws RemoteException {
return frame != null ? new RemoteFrameImpl(frame, accessToken) : null;
}
}
@@ -29,15 +29,17 @@ import org.jetbrains.annotations.NotNull;
class DebugProcessListener extends ProcessAdapter {
private final Project myProject;
private final int myPort;
private final String myAccessToken;
DebugProcessListener(Project project, int port) {
DebugProcessListener(Project project, int port, String accessToken) {
myProject = project;
myPort = port;
myAccessToken = accessToken;
}
@Override
public void startNotified(@NotNull ProcessEvent event) {
final DebuggerConnector connector = new DebuggerConnector(myProject, event.getProcessHandler(), myPort);
final DebuggerConnector connector = new DebuggerConnector(myProject, event.getProcessHandler(), myPort, myAccessToken);
ApplicationManager.getApplication().executeOnPooledThread(connector);
}
@@ -40,11 +40,13 @@ class DebuggerConnector implements Runnable {
private final Project myProject;
private final ProcessHandler myProcess;
private final int myPort;
private final String myAccessToken;
DebuggerConnector(Project project, ProcessHandler process, int port) {
DebuggerConnector(Project project, ProcessHandler process, int port, String accessToken) {
myProject = project;
myProcess = process;
myPort = port;
myAccessToken = accessToken;
}
@Override
@@ -97,7 +99,7 @@ class DebuggerConnector implements Runnable {
if (myProcess.isProcessTerminated()) return null;
try {
final Debugger realClient = EDTGuard.create(new RemoteDebuggerClient(myPort), myProcess);
final Debugger realClient = EDTGuard.create(new RemoteDebuggerClient(myPort, myAccessToken), myProcess);
myProcess.notifyTextAvailable("Connected to XSLT debugger on port " + myPort + "\n", ProcessOutputTypes.SYSTEM);
return realClient;
} catch (ConnectException e) {
@@ -57,6 +57,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
@@ -70,6 +71,7 @@ public class XsltDebuggerExtension extends XsltRunnerExtension {
public static final Key<XsltChecker.LanguageLevel> VERSION = Key.create("VERSION");
private static final Key<Integer> PORT = Key.create("PORT");
private static final Key<Manifest> MANIFEST = Key.create("MANIFEST");
private static final Key<String> ACCESS_TOKEN = Key.create("access token");
@NonNls
private static final String SAXON_6_JAR = "saxon.jar";
@@ -87,7 +89,7 @@ public class XsltDebuggerExtension extends XsltRunnerExtension {
public ProcessListener createProcessListener(Project project, UserDataHolder extensionData) {
final Integer port = extensionData.getUserData(PORT);
assert port != null;
return new DebugProcessListener(project, port);
return new DebugProcessListener(project, port, extensionData.getUserData(ACCESS_TOKEN));
}
@Override
@@ -130,6 +132,10 @@ public class XsltDebuggerExtension extends XsltRunnerExtension {
throw new CantRunException("Unable to find a free network port");
}
String token = UUID.randomUUID().toString();
parameters.getVMParametersList().defineProperty("xslt.debugger.token", token);
extensionData.putUserData(ACCESS_TOKEN, token);
final char c = File.separatorChar;
final PluginId pluginId = PluginManagerCore.getPluginByClassName(getClass().getName());