Java命令執行的方式
在最開始的時候,還不懂java代碼就去復現了fastjson的反序列化漏洞,發現真的是晦澀難懂。好在后面學了java基礎、web開發和框架的相關內容,才能讀懂部分。所以建議初學者還是要一步步學習,從最開始的java基礎代碼,包括JDBC、多線程、IO、泛型、java反射機制等等。
然后就可以去讀一些開源cms的源碼,老一些的源碼,不建議直接去讀若依、銘飛這些cms。復現的話可以去復現,只需要到gitee或者github上面去查找版本更新的代碼,就可以看出漏洞是怎么產生和修復的。
最后再去讀一些經典漏洞的復現文章,一步步調試,查找代碼的功能,才能更好地理解漏洞的底層原理。當然了,調試之前如果有時間去好好讀一讀框架或者組件的源碼會更好。因為我記得P牛說過一句話,跟着別人的文章學習學到的東西永遠是很少的。P牛自己也說了,他復現漏洞的時候很少參考別人的文章,而是去讀源碼,靠自己的思路去分析漏洞。能做到這樣最好。
大概講了java審計的學習流程,相關視頻和文章在谷歌上搜就能搜到了。那么廢話不多說,先進行審計的第一節——java命令執行的方式。
Java命令執行一共有三種方式,分別是Runtime.getRuntime().exec、processBuilder和Processlmpl。其中Processlmpl是最底層的實現。processBuilder為中間層的實現。Runtime.getRuntime().exec為最上層的實現。意思就是前兩種方式最后都是通過調用Processlmpl進行命令執行的。
Runtime.getRuntime().exec的實現代碼:
public class ExecTest {
public static void main(String[] args) throws IOException {
String[] cale = new String[]{"cmd.exe","/c","calc.exe"};
Runtime.getRuntime().exec(cale);
System.out.println(cale);
}
}
processBuilder的實現代碼:
public class ProcessBuilderTest {
public static void main(String[] args) throws IOException{
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe","/c","calc.exe");
Process start = processBuilder.start();
System.out.println(start);
}
}
Processlmpl的實現代碼:
import java.io.IOException;
import java.lang.Process;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
public class ProcesslmplTest {
public static void main(String []args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException{
Class clazz = Class.forName("java.lang.ProcessImpl"); // 獲取ProcessImpl的Class對象
Method method = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class); // 獲取start方法對象
method.setAccessible(true); // 設置方法允許在當前代碼使用
Process p = (Process) method.invoke(null, new String[]{"cmd.exe","/c","calc.exe"}, null, ".", null, true); // 調用start方法
System.out.println(p);
}
}