Eine sehr grobe Art und Weise wäre dies:
String code = request.getParameter("code");
String className = "Code" + DigestUtils.sha1hex(code);
String classCode = ""
+ "public class " + className + " implements Runnable {\n" +
+ " public void run() {\n" +
+ code + "\n"
+ " }\n"
+ "}\n";
Files.write(new File(className + ".java"), code, StandardCharsets.UTF_8);
Runtime.getRuntime().exec("javac " + className + ".java");
Class<?> clazz = Class.forName(className);
((Runnable)clazz.newInstance()).run();
Unter der Annahme, dass das aktuelle Verzeichnis im Classpath ist, und weiter unter der Annahme, dass die Klassenlader lädt Klassen on-Demand, dies oder etwas ähnliches funktionieren sollte, zumindest für Ihr System.out
Beispiel.
Wenn Sie mit diesem Code spielen, beachten Sie, dass der hochgeladene Code möglicherweise etwas unternimmt, einschließlich des Aufrufs von System.exit(1)
, Lesen aller Dateien im Dateisystem, Starten eines Botnets auf dem Computer und so weiter.
Anstelle der letzten beiden Zeilen Code, können Sie auch tun:
Runtime.getRuntime().exec("java " + className);
(oder eine Variante davon, die dann Sie System.out
und System.err
erfassen können, so können sie die rückzukoppeln HTTP-Client: Dies würde auch eine Gefahr von System.exit
verhindern, so dass nur die zahlreichen anderen Schwachstellen übrig bleiben.)
Für den Anfang: Werden Sie extrem paranoid in Sachen Sicherheit. –
@LouisWasserman natürlich, aber kompilieren und Benutzercode ausführen ist die Grundlage meiner Idee. – z17
Ist es eine Voraussetzung, dass Sie den Code in Ihrem Programm kompilieren? Es ist eine häufigere Technik, eine Schnittstelle bereitzustellen, auf der Benutzer programmieren können, ihre eigene Implementierung zu kompilieren und dann ihre Implementierung (.jar-Datei) bei Ihrem Programm zu registrieren. So funktionieren JDBC-aktivierte Programme, wenn Sie einen JDBC-Treiber registrieren müssen. – Samuel