漏洞分析 | 漏洞调试的捷径:精简代码加速分析与利用

0x01前言

近期,Microsoft威胁情报团队曝光了DEV-0950(Lace Tempest)组织利用SysAid的事件。随后,SysAid安全团队迅速启动了应急响应,以应对该组织的攻击手法。然而,在对漏洞的分析和复现过程中,并未提供详细说明。由于该产品在安装时需要许可证,增加了动态调试漏洞的难度。为了便于调试能够快速复现该漏洞,我们尝试通过只使用部分的单元代码来模拟漏洞的主要逻辑流程进行动态调试分析。最终,我们成功利用 Goby 工具完美地实现了该漏洞的利用。
在这里插入图片描述

0x02 补丁分析

在 SysAid 中发布的公告中说明在 23.3.36 修复了该漏洞,通过 Diff 补丁发现该修复方式主要为限制 com.ilient.server.UserEntry#doPost函数中的 ..来完成的。
在这里插入图片描述

0x03 单元调试

由于安装包在安装时对许可证进行了限制,因此无法有效地进行安装和调试。为了能够高效地进行动态调试,我们采取了以下优化策略:创建一个独立的空项目,将存在漏洞的 Servlet 进行重写,用于单元模拟。通过这种方法,我们可以在没有任何依赖的情况下最小化地运行漏洞点,并顺利完成研究和分析的工作。
通过修复的方式来推断,该漏洞通过目录穿越的方式来指定上传的路径(accountId 参数)以及上传内容来完成利用。
在这里插入图片描述

再收到 accountId 参数值后会通过 a 函数来完成对该路径的拼接,由于该拼接方式存在一定的问题就导致了目录穿越,然后将传入的数据流写入到 accountId 可控的路径。
在这里插入图片描述

在写入完毕之后通过调用 a(var31, var46, var7);完成对传入数据的解压到指定的目录中。
在这里插入图片描述

根据漏洞分析得出漏洞的核心利用点主要取决于 accountId 和 POST 请求传入的字节数据,所以我们可以将存在可能利用的代码进行抽象。

package com.example.sysaid;

import com.ilient.server.IlientConf;

import java.io.*;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.zip.InflaterInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

@WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet {
    private String message;

    public void init() {
    }

    public void doGet(HttpServletRequest var1, HttpServletResponse var2) throws IOException {
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse var2) throws ServletException, IOException {
        String accountId = request.getParameter("accountId");
        InflaterInputStream inputStream = new InflaterInputStream(request.getInputStream());
        byte[] bytes = InputStreamUtils.InputStreamToBytes(inputStream);
        String var46  = a(accountId);
        String var7 = request.getParameter("symbolName");
        File var31 = new File(var46 + File.separator + Long.toString(Calendar.getInstance().getTimeInMillis()) + ".zip");
        FileOutputStream var38;
        (var38 = new FileOutputStream(var31)).write(bytes);
        var38.flush();
        var38.close();
        // var46
        a(var31, var46, var7);
        if (!var31.delete()) {
            var31.setWritable(true);
            var31.delete();
        }
    }

    private static void a(File var0, String var1) {
        File var2;
        if ((var2 = new File(var1)).exists() && var2.isDirectory()) {
            File[] var6 = var2.listFiles();
            String var3 = Long.toString(Calendar.getInstance().getTimeInMillis()) + ".bad";
            File var5 = new File(var1, var3);
            if (var0.renameTo(var5)) {
                System.out.println("UserEntry.renameAndMoveFile: File renamed and moved successfully.");
            } else {
                System.out.println("UserEntry.renameAndMoveFile: Failed to rename and move the file.");
            }
            if (var6.length >= 10) {
                Arrays.sort(var6, Comparator.comparingLong(File::lastModified));
                for(int var4 = 0; var4 < var6.length - 9; ++var4) {
                    if (var6[var4].isFile() && !var6[var4].delete()) {
                        System.out.println("UserEntry.renameAndMoveFile: Failed to delete file: " + var6[var4].getName());
                    }
                }
            }
        } else {
            System.out.println("UserEntry.renameAndMoveFile: Invalid output folder specified.");
        }
    }

    private static void a(File var0, String var1, String var2) {
        if (!var2.startsWith("LDAP_REFRESH_")) {
            IlientConf.logger.error(String.format("Error on UserEntry: symboleName %s not validated.", var2));
            a(var0, var1);
        } else {
            byte[] var8 = new byte[1024];
            try {
                ZipInputStream var3;
                for(ZipEntry var4 = (var3 = new ZipInputStream(new FileInputStream(var0))).getNextEntry(); var4 != null; var4 = var3.getNextEntry()) {
                    String var9;
                    if ((var9 = var4.getName()) != null && var9.indexOf("..") >= 0) {
                        System.out.println("Error in UserEntry.unZipIt - Found path manipulation!");
                        a(var0, var1);
                        return;
                    }
                    File var10 = new File(var1 + File.separator + var9);
                    String var5 = (new File(var1)).getCanonicalPath();
                    System.out.println(var10.getCanonicalPath());
                    System.out.println(var5 + File.separator);
                    if (!var10.getCanonicalPath().startsWith(var5 + File.separator)) {
                        System.out.println("Error in UserEntry.unZipIt - File is outside of the output directory!");
                        a(var0, var1);
                        return;
                    }
                    System.out.println("File unzip : " + var10.getAbsoluteFile());
                    FileOutputStream var11 = new FileOutputStream(var10);
                    int var12;
                    while((var12 = var3.read(var8)) > 0) {
                        var11.write(var8, 0, var12);
                    }
                    var11.close();
                }
                var3.closeEntry();
                var3.close();
                System.out.println("Finish unziping: " + var0.getAbsolutePath());
            } catch (Exception var7) {
                var7.printStackTrace();
                System.err.println("UserEntry: Error in unZipIt method:"+ var7);
            }
        }
    }

    public static String a(String var0) {
//        String var1 = IlientConf.getInstance().getNonAccountSharedFilesDir("ldapfiles");
        String var1 = "/1111/SysAidServer/root/WEB-INF/ldapfiles";
        File var2;
        if (!(var2 = new File(var1 + File.separator + var0)).exists()) {
            var2.mkdirs();
        }
        return var1 + File.separator + var0;
    }

    public void destroy() {
    }
}

构建新的 war 工程部署该 Servlet 即可完成对漏洞点单元模拟,用于漏洞的动态调试。
在这里插入图片描述

0x04 总结

在特殊情况下漏洞调试以及武器化利用时无法能够满足最佳的调试环境,我们尝试通过将有漏洞的部分代码进行单元模拟完成漏洞的动态调试。

0x05 参考

https://www.sysaid.com/blog/service-desk/on-premise-software-security-vulnerability-notification
https://www.huntress.com/blog/critical-vulnerability-sysaid-cve-2023-47246

Goby 欢迎表哥/表姐们加入我们的社区大家庭,一起交流技术、生活趣事、奇闻八卦,结交无数白帽好友。

也欢迎投稿到 Goby(Goby 介绍/扫描/口令爆破/漏洞利用/插件开发/ PoC 编写/ IP 库使用场景/ Webshell /漏洞分析 等文章均可),审核通过后可奖励 Goby 红队版,快来加入微信群体验吧~~~

文章来自Goby社区成员:Gryffinbit@白帽汇安全研究院,转载请注明出处。
微信群:公众号发暗号“加群”,参与积分商城、抽奖等众多有趣的活动
获取版本:https://gobysec.net/sale

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/152482.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Microsoft Dynamics AX 2012 - 1. 什么是Microsoft Dynamics AX?

Dynamics AX是Microsoft的核心业务管理解决方案&#xff0c;旨在满足中型公司和跨国组织的要求。基于 DynamicsAX基于最先进的体系结构和深度集成&#xff0c;在确保高可用性的同时&#xff0c;展现了全面的功能。 在AX 2012版中&#xff0c;Dynamics AX显示了大量新功能和增强…

Postman内置动态参数以及自定义的动态参数

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 一&#xff09;内置动态参数 {{$timestamp}} 生成当前时间的时间戳{{$randomInt}} 生成0-1000之间的随机数{{$guid}} 生成随…

⑩【MySQL】存储引擎详解, InnoDB、MyISAM、Memory。

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 存储引擎 ⑩【MySQL存储引擎】1. MySQL体系结构…

隐私协议 Secret Network 宣布使用 Octopus Network 构建的 NEAR-IBC 连接 NEAR 生态

2023年11月 NearCon2023 活动期间&#xff0c;基于 Cosmos SDK 构建的隐私协议 Secret Network&#xff0c;宣布使用 Octopus Network 开发的 NEAR-IBC&#xff0c;于2024年第一季度实现 Secret Network 与 NEAR Protocol 之间的跨链交互。 这将会是Cosmos 生态与 NEAR 之间的首…

java VR全景商城免费搭建 saas商城 b2b2c商城 o2o商城 积分商城 秒杀商城 拼团商城 分销商城 短视频商城

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

一个开源的汽修rbac后台管理系统项目,基于若依框架,实现了activiti工作流,附源码

文章目录 前言&源码项目参考图&#xff1a; e店邦O2O平台项目总结一、springboot1.1、springboot自动配置原理1.2、springboot优缺点1.3、springboot注解 二、rbac2.1、概括2.2、三个元素的理解 三、数据字典3.1、概括与作用3.2、怎么设计3.3、若依中使用字典 四、工作流—…

STM32CubeIDE报“xxx is not implemented and will always fail”解决方法

本文介绍STM32CubeIDE报“xxx is not implemented and will always fail”解决方法。 最近用STM32CubeIDE开发STM32程序时&#xff0c;编译报警告&#xff1a; warning: _close is not implemented and will always fail warning: _lseek is not implemented and will always…

idea中把spring boot项目打成jar包

打jar包 打开项目&#xff0c;右击项目选中Open Module Settings进入project Structure 选中Artifacts&#xff0c;点击中间的加号&#xff08;Project Settings->Artifacts->JAR->From modules with dependencies &#xff09; 弹出Create JAR from Modules&#…

想转行互联网行业,是选择网络安全还是人工智能?

随着数字时代的到来&#xff0c;网络安全和人工智能成了科技创新产业的重要组成部分。也逐渐成了大多数人心中热门的行业选择。那么该如何抉择呢&#xff1f; 首先我们来了解下人工智能的发展前景&#xff1a; 如今&#xff0c;人工智能技术无论是在核心技术方面&#xff0c…

系列四、本地接口(Native Interface)

一、概述 本地接口的作用是融合不同的编程语言为Java所用&#xff0c;它的初衷是融合C/C程序&#xff0c;Java诞生的时候正是C/C横行的时候&#xff0c;要想立足&#xff0c;必须要调用C/C的程序&#xff0c;于是Java就在内存中开辟了一块区域专门用于处理标记为native的代码&a…

wpf devexpress数据统计

GridControl允许显示总结信息关于单个数据行分组。例如&#xff0c;你可以显示记录数量&#xff0c;最小和最大值。这个统计信息可以叫做数据统计。 创建统计 GridControl 支持总结和分组统计&#xff1a; 总结统计 - 一个总结函数值计算对于所有列和视图显示统计面板和固定统…

2023最受推荐的五款项目管理工具

1、进度猫 进度猫是国内一款轻量级项目管理工具&#xff0c;适用于实时协作的团队。 以甘特图为向导&#xff0c;基于任务清单todolist&#xff0c;支持多用户协作&#xff1b; 甘特图显示具体任务清单、时间和任务的进度&#xff1b; 对未完成任务、已完成任务进行分类管…

深度学习OCR中文识别 - opencv python 计算机竞赛

文章目录 0 前言1 课题背景2 实现效果3 文本区域检测网络-CTPN4 文本识别网络-CRNN5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习OCR中文识别系统 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;…

【Spring进阶系列丨第二篇】Spring中的两大核心技术IoC(控制反转)与DI(依赖注入)

前言 我们都知道Spring 框架主要的优势是在 简化开发 和 框架整合 上&#xff0c;至于如何实现就是我们要学习Spring 框架的主要内容&#xff0c;今天我们就来一起学习Spring中的两大核心技术IoC&#xff08;控制反转&#xff09;与DI&#xff08;依赖注入&#xff09;。 文章目…

【BIM入门实战】高程点无法放置的解决方法

文章目录 一、问题提出二、解决办法1. 检查模型图形样式2. 高程点可以放置的图元一、问题提出 在平面图中添加高程点时有时会遇到无法在楼板等平面构件上放置高程点,应如何设置才能使高程点正常放置? 如下图所示,楼板上无法放置高程点: 二、解决办法 1. 检查模型图形样式…

Linux C/C++全栈开发知识图谱(后端/音视频/游戏/嵌入式/高性能网络/存储/基础架构/安全)

众所周知&#xff0c;在所有的编程语言中&#xff0c;C语言是一门颇具学习难度&#xff0c;需要很长学习周期的编程语言。甚至很多人经常听到一句调侃的话语——“C&#xff0c;从入门到放弃”。 C界的知名书籍特别多&#xff0c;从简单到高端书籍&#xff0c;许多书籍都是C之…

1.mysql安装及基础

目录 概述安装上传jar包解压添加用户组和用户更改权限修改配置文件 my.cnf初始化登录mysql修改密码远程登录生效配置 sql语句分类数据定义语言 结束 概述 mysql安装及基础&#xff0c;后续涉及基础会继续补充。 安装 上传jar包 下载地址 解压 tar -zxvf mysql-5.7.44-li…

代码随想录 Day47 动态规划15 LeetCode T583 两个字符串的删除操作 T72 编辑距离

LeetCode T583 两个字符串的删除操作 题目链接:583. 两个字符串的删除操作 - 力扣&#xff08;LeetCode&#xff09; 题目思路: 本题有两个思路 1.使用两个字符串的长度之和-2*最长公共子串(换汤不换药) 代码随想录Day45 动态规划13 LeetCode T1143最长公共子序列 T1135 不相交…

kubectl 本地远程链接k8s多个集群,远程管控多集群,查看日志 部署服务(windows版)

文章目录 一、前言二、windows上安装kubectl和mobaxterm2.1 准备安装包2.2 安装kubectl2.3 链接k8s集群2.4 查看某一个pod的容器日志2.5 切换context 上下文配置&#xff0c;实现在多个k8s集群间动态切换 一、前言 现如今是一个万物皆上云 的时代&#xff0c;各种云层出不穷&am…

JEECG BOOT 前端记录

目录 查询 1、模糊搜索中文 2、下拉框选择 3、文本框 新增 1、添加文本框 2、图片上传 3、文件上传 4、富文本 5、下拉框数字回显文字 第一种&#xff1a; 第二种&#xff1a; 展示 1、字典翻译注解Dict 1.2、字典表翻译用法 2、点击事件调接口 查询 1、模糊搜索中…