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