0
A
回答
0
一种非常原始的方法是这样的:
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();
假设当前目录是在classpath中,并进一步假设点播类加载器加载类,这或类似的东西应该工作,至少例如你的System.out
。
使用此代码时,请注意,上传的代码可能会执行任何操作,包括调用System.exit(1)
,读取文件系统中的所有文件,在计算机上启动僵尸网络等。
而不是代码的最后两行,你也可以这样做:
Runtime.getRuntime().exec("java " + className);
(或它的一些变化,然后让你捕捉System.out
和System.err
,所以你可以喂它们回HTTP客户端,这也可以防止来自System.exit
的任何危险,因此只剩下许多其他漏洞。)
对于初学者:对安全性变得极度偏执。 –
@LouisWasserman当然,但编译和运行用户代码是我的想法的基础。 – z17
是否需要编译程序中的代码?提供用户可以编程的接口,编译自己的实现,然后在程序中注册它们的实现(.jar文件)是一种更常见的技术。当您必须注册JDBC驱动程序时,这是启用JDBC的程序的工作方式。 – Samuel