HTTP Server + Groovlet = A Back-Door Type of Trick When Using A Java App
Recently I saw an article about simple groovlet. Groovlet allows you to execute any code in your server. It looks very useful for creating a backdoor - for debugging, troubleshooting, etc.
My problem, however, is that we don't just have a server, but we also have a Swing-rich client who is unable to execute groovlets. So I tried to create something like this in a standalone application without adding to the application-embedded servlet engine (Jetty or Tomcat).
Luckily, I just read an article about a Simple HTTP server inside a standard Java library. I decided to use some of its ideas.
Let's start from Main:
Published at DZone with permission of its author, Pavel Bernshtam.My problem, however, is that we don't just have a server, but we also have a Swing-rich client who is unable to execute groovlets. So I tried to create something like this in a standalone application without adding to the application-embedded servlet engine (Jetty or Tomcat).
Luckily, I just read an article about a Simple HTTP server inside a standard Java library. I decided to use some of its ideas.
Let's start from Main:
public class Main {
public static void main(String[] args) {
// You can set port number from command line or leave it hardcoded
HttpBackdoorRunner runner = new HttpBackdoorRunner(18999, true);
runner.start();
}
}
Let's continue in groovy because it is simpler :)
import com.sun.net.httpserver.HttpServer
import java.util.concurrent.Executors
/**
* This class starts the server with our handler (Embedded server is not Servlet container!)
*/
class HttpBackdoorRunner {
final int port
final boolean silent
HttpBackdoorRunner(int port, boolean silent) {
this.port = port
this.silent = silent
}
def start() {
try {
InetSocketAddress addr = new InetSocketAddress(port);
HttpServer server = HttpServer.create(addr, 0);
server.createContext("/", new BackdoorHandler());
server.setExecutor(Executors.newCachedThreadPool(
));
server.start();
}
catch(Exception e) {
if (silent) {
// Ignore
}
else throw new RuntimeException(e)
}
}
}
Now - the HTTP requests handler:
/**
* I need this abstraction level to reuse script running code in groovlet and standalone backdoor
* The way, you receive script text is different in those two situations
*/
class BackdoorScriptRunner {
void runScript(script, responseBody, uri) {
def scriptOutput = new ByteArrayOutputStream()
if (script) {
// Redirect output
def saveOut = System.out
def stream = new PrintStream(scriptOutput)
System.out = stream
try{
def result = new GroovyShell().run(script, "dynamic.groovy");
}
catch (Throwable e) {
e.printStackTrace(stream);
}
System.out = saveOut
}
responseBody.println createHTML(uri, script, scriptOutput)
responseBody.close();
}
String createHTML(uri, script, scriptOutput) {
"""
< form action="${uri}" method="post">
< h2>BackDoor
Code comes here:
< textarea cols="120" rows="5" name="groovyscript">
${script ? script : ""}< /textarea>
< br>
< input type="submit" value="Go!" />
< /form>
< br>
${scriptOutput.toString() ? "< h2>Output< /h2>< pre>${scriptOutput}< /pre>" : ""}
"""
}
}
And now - start it up!
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)




