• Java安全之命令执行(一)


    前言

    java安全里最关键的可以说就是命令执行了,无论是反序列化还是什么RCE漏洞,要说最终最能体现漏洞价值的话,那就是非命令执行莫属了。这次打算花点时间好好总结整理下java命令执行的几种方式,并做些浅面的分析。最近刚好看到了360BugCloud公众号的一篇java命令执行的调试分析文章,我也跟着调试了一遍,期间学到了不少,链接会在文末贴出来。

    首先总的的来说,java命令执行可以分为4种方法,分别是 java.lang.Runtime#exec()、java.lang.ProcessBuilder#start()、java.lang.ProcessImpl#start()以及通过JNI的方式调用动态链接库,最后一种方式这篇文章暂不做分析,先看完前面比较常用的三种方法。

    Runtime命令执行

    在java反序列化中用到最多的就是Runtime类的exec方法来命令执行了,用法:

    Runtime.getRuntime().exec("whoami")
    

    实际上Runtime类的exec的重载方法有6个,如下:

    例如本地运行命令ipconfig查看网络配置并返回信息:

    InputStream ins = Runtime.getRuntime().exec("ipconfig").getInputStream();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    byte[] bytes = new byte[1024];
    int size;
    while(
    	(size = ins.read(bytes)) > 0)bos.write(bytes,0,size);
        System.out.println(bos.toString()
         );
    

    但是这里有个问题,在渗透的过程中如果要遇到要写入文件的话,这里使用"echo xxx>test.txt"等类似的命令就会爆出如下的错误:

    跟入代码调试查看下具体原因

    首先是跳到另外一个exec的重载方法,envp参数为null,file类型的dir参数也为null

    接着将我们传入的command字符串带入到StringTokenizer类进行处理,跟入查看下

    初始化参数后又调用了setMaxDelimCodePoint方法

    跟入到setMaxDelimCodePoint方法后,查看代码

    来看最后的处理结果

    最后再重新调用了对应的exec重载方法

    跟入到java.lang.ProcessBuilder#start,首先会先取出cmdarray[0]赋值给prog,这里值为“echo”

    接着,后面又调用了ProcessImpl.start

    继续跟入查看ProcessImpl#start

    接着,后面调用了ProcessImpl的构造方法,再跟入构造方法查看下

    跟进ProcessImpl的构建方法后,首先是对系统的配置及环境变量进行检查,比如检测是否允许调用本地进程等配置,接着以cmd[0]为参数创建了一个File对象,然后调用其getPath方法得到路径并赋值给executablePath变量

    往下,接着调用needsEscaping()方法对executablePath进行判断,如果其中包含空格,则调用quoteString()方法进行处理;然后调用createCommandLine()把字符串数组拼成字符串,最终的cmdstr为“echo xxx>test.txt”

    最后,再调用了create()方法创建进程,整个过程调试到这里好像也没发现问题所在,原因是最后关键的问题还在create方法创建进程中。

    查看该create()方法的代码可看到,这是个native方法,后续是通过调用ProcessImpl_md.c的创建进程的方法来调用调用window系统的API接口,从而完成命令执行等操作。

    那么我们的问题该怎么解决呢?还是得回到ProcessImpl_md.c的创建进程的方法中,这方法会对最后的我们传入的cmdstr进行以空格分割,也就是"echo xxx>test.txt",会被分割会"echo"和"xxx>test.txt",然后第一部分的"echo"会被当成启动的执行模块,然而在window的系统环境变量中是找不到这个启动模块的(可以在cmd中输入命令“where echo”进行测试),所以运行后才会抛出文章一开始的“系统找不到指定文件”错误。

    知道了问题所在,解决办法的思路就比较清晰了,可以把cmd做为启动的指定模块,然后以运行批处理的方式来达到命令执行,要以这样的方式的话就必须启动命令解释器,就是在批处理的语句前面加上"/c",最终的命令应该为“cmd /c echo xxx>test.txt”。

    我们通过IDEA的调试器来测试一遍:

    OK,这回没有抛出其他错误了,在本地的项目位置在找到了新创建的test.txt文件

    Reference

    https://s.yam.com/ddxhQ

    乐观的悲观主义者。
  • 相关阅读:
    出差兰州
    出差乌鲁木齐(3)
    依赖倒置原则
    .NET 打印界面
    出差乌鲁木齐2
    出差乌鲁木齐(2)
    出差乌鲁木齐3
    IStyleGallery.AddItem、UpdateItem、RemoveItem用法
    Shapefile记录检索
    c#利用最小二乘法拟合任意次函数曲线(转)
  • 原文地址:https://www.cnblogs.com/v1ntlyn/p/13888547.html
Copyright © 2020-2023  润新知