这篇文章主要以Tomcat为例子记录了一些关于Java内存Webshell利用与检测以及相关的思考。

内存Webshell的利用方式

现在的内存Websell的利用方式个人感觉可以分为以下三种:

1. 基于Servlet规范的利用,动态注册Servlet规范中的组件,包括Servlet,Filter,Listener,这部分的公开文章比较多,比如:

基于tomcat的内存 Webshell 无文件攻击技术 - 先知社区​xz.aliyun.com

2. 基于特定框架的利用,框架一般对于Servlet又进行了一层封装,动态注册框架的路由,文章:

基于内存 Webshell 的无文件攻击技术研究​www.anquanke.com

3. 基于javaagent修改Servlet处理流程中的字节码,工具:

rebeyond/memShell​github.com

前两种利用方式的利用场景要求为可以执行任意Java代码,比较常见的场景包括:反序列化,JNDI注入等场景,不过现在公开的工具,在一些场景利用起来依然不太方便,典型的比如shiro反序列化漏洞不出网的情况下利用后想要代理进内网的场景,所以能够利用反序列化直接注入一个可以使用一些功能比较强大的webshell管理工具(典型的比如冰蝎)的内存webshell 会比较方便后续的利用,由于各个师傅已经给出了比较详细的思路,所以我就做了一下整合,方便后续的测试。几个需要修改的地方:

冰蝎的客户端在很多景中,并没有jsp相关的依赖,需要把pageContext换掉。

摆脱Tomcat header的限制,需要缩小payload的体积,同时还需要处理一下冰蝎服务端原有的内部类。

工具地址:

buptchk/ysoserial​github.com

内存Webshell的检测

如何检测内存Webshell,之前有师傅提出了利用VisualVM监控mbean来检测,用上面的工具注入内存webshell之后确实可以在Filter中看到注入的Shell

这个的检测原理主要是在注册类似Filter的时候会触发registerJMX的操作来注册mbean,org.apache.catalina.core.ApplicationFilterConfig#initFilter

不过mbean的注册只是为了方便资源的管理,并不影响功能,所以攻击者植入内存Webshell之后,完全可以通过执行Java代码来卸载掉这个mbean来隐藏自己。

利用冰蝎运行自定义代码功能卸载mbean的demo:

import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.util.Set;
public class UnRegister {static  {try{Class registryClass = Class.forName("org.apache.tomcat.util.modeler.Registry");MBeanServer mBeanServer = (MBeanServer) registryClass.getMethod("getMBeanServer").invoke( registryClass.getMethod("getRegistry", Object.class, Object.class).invoke(null,null,null));Set<ObjectName> objectNameSet = null;objectNameSet = mBeanServer.queryNames(null, null);for (ObjectName objectName : objectNameSet) {if ("Filter".equals(objectName.getKeyProperty("j2eeType"))) {Object filterName = mBeanServer.getAttribute(objectName, "filterName");if ("litchi".equals((String) filterName)) {mBeanServer.unregisterMBean(objectName);}}}}catch (Exception e) {e.printStackTrace();}}
}

1、利用Java Instrument检测

对于内存马的检测,最后还是落在JVM的内存层面上的,所以想要比较精准的检测内存马的话,可以考虑利用Java Instrument技术,简单的思路比如:

对于敏感类(比如实现了javax.servlet.Filter接口的类)利用retransformClasses方法进行retransform,编写ClassFileTransformer实现类将这些敏感类加载的class dump出来,接着就可以使用反编译工具转换成源代码判断是否是Webshell,或者有一些webshell检测工具支持字节码的检测,比如:WebshellChop 就不用反编译可以进行批量的检测。

当然如果不想自己编写,在这里推荐一个工具可以比较方便的检测:Alibaba开源的Java诊断工具arthas,arthas也是利用了Java Instrument技术,能比较好的解决一些线上应用难调试,难监控的问题,功能比较强大,支持命令行交互模式,关于arthas的具体细节可以查看他的文档,我们先来直接看看检测的demo。

2、利用arthas检测Filter类型

由于arthas可以直接观察方法调用的情况,所以可以很直接的获取执行流程中准确的对象,以检测Filter为例子:在处理Filter的过程中ApplicationFilterChain来自于createFilterChain方法,所以我们可以直接watch这个方法的返回值来获取已经注册的Filter,启动arthas attach到指定进程上之后执行如下表达式

watch org.apache.catalina.core.ApplicationFilterFactory createFilterChain 'returnObj.filters.{?#this!=null}.{filterClass}'

访问url触发

接着利用jad命令观察可疑的filterClass的源代码:

jad ysoserial.payloads.TomcatShell

无论是从classLoader的信息,还是doFilter方法的实现都可以进行判断

3、结合牧云进行批量检测

如果攻击者隐藏的够好,要判断是否可疑还是不太容易的,这时候可以构造正则表达式一次性把所有的Filter导出来,直接扔到扫描器中进行批量检测。不过目前arthas的交互shell对于管道以及字符串操作的支持还不是特别好,可以先在外面的shell中先进行字符串处理

把dump出来的有class的文件夹直接丢到长亭的主机防护产品:牧云中就可以直接支持检测,牧云支持直接的针对class的字节码类型的检测

由于arthas也支持批处理的调用,这部分的处理流程也可以写成一个定时任务来进行定时的自动化检测,这样检测就比较方便。

4、利用arthas检测基于框架的类型

基于内存 Webshell 的无文件攻击技术研究​www.anquanke.com

为例子,可以直接观察DispatcherServlet匹配handler的过程,把所有的尝试匹配都找出来就可以找到所有的RequestMapping。

watch org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry getMappings "returnObj"
#访问随意一个url触发

拿到所有的RequestMapping对应的HandlerMethod之后就可以去检测对应的class了

5、利用arthas检测javaagent类型

memShell的检测为例子,这部分的检测效果不是特别好

原因如下:

1. 由于这种类型采用了增强字节码的机制来改变执行的流程,在处理请求的流程中,可以增强字节码的地方很多,检测起来比较无从下手

2. 由于在dump字节码的时候都是利用了retransformClasses,这个执行流程会造成互相干扰

以memshell的检测为例子,jad反编译memshell修改的ApplicationFilterChain可以看到并没有如预期一样打印出被修改过的代码,原因可以看

https://github.com/alibaba/arthas/issues/763​github.com

memshell中的ClassFileTransformer第二次执行的时候就会出现异常导致没有成功把ApplicationFilterChain修改掉,所以jad命令看到的也就是没有修改的字节码了,不过这也相当于已经把这个内存shell给删除了。

不过我们依然可以从其他特征来入手检测,比如考虑是不是添加了恶意的shutdownhook

ognl "@java.lang.ApplicationShutdownHooks@hooks.keySet().toArray().{getClass()}.{getName()}"

6、总结

其实利用类似的agent类型的思路可以做到比较精准的发现类似的内存Webshell,但是前提是你得知道内存Webshell大致隐藏在哪,这也是比较考验防守方的地方,需要对内存Webshell的注入场景有比较好的覆盖 ,将其转化为文件之后就可以利用支持字节码的检测工具批量进行定时自动化检测。

拓展:关于arthas思考

前几天在先知社区看到了关于openRasp的类加载机制的分析

以OpenRASP为基础-展开来港港RASP的类加载 - 先知社区​xz.aliyun.com

学习了一下关于OpenRasp的类加载机制,arthas作为同样是利用Java Instrument的类型的产品做到了比较好的类隔离机制来减少对于线上应用的侵入这里就arthas的类加载机制来进行一个简单的讨论。

首先为了做到类隔离,arthas-core是由agent利用自定义的类加载器加载的,来做到与业务方进行类隔离

接着我们把arthas的全局dump以及unsafe选项打开,来看看watch一个由启动类加载器加载的类的某个方法时arthas是如何进行增强的。

将dump下来的class进行一下反编译,这里以java.lang.ApplicationShutdownHooks的add方法为例子:

可以看到对于字节码的增强,是直接调用的SpyAPI的方法,而这个SpyAPI在启动Agent的时候就已经把他加入到了BootstrapClassLoader中,所以可以顺利调用他的atEnter方法,但是对于不同的指令来说,这个方法都需要具体的实现,最后实现肯定需要调用core里面的方法,那么是如何实现的呢?来看看SpyAPI类的实现

这个AbstractSpy的实例是什么呢?其实在使用的时候,这个实例被设置为SpyImpl的实例,而这个SpyImple类是由ArthasClassLoader加载的,这样就做到了可以在任意地方调用自定义类加载器中的方法。

本人水平有限,如果师傅发现文章中的疏漏错误,欢迎指出来可以一起探讨~

java批量实现1对1关系的自动匹配_杂谈Java内存Webshell的攻与防相关推荐

  1. 【杂谈Java内存Webshell的攻与防】

    侵刪 杂谈Java内存Webshell的攻与防 长小亭 网络安全知识的搬运工~ 这篇文章主要以Tomcat为例子记录了一些关于Java内存Webshell利用与检测以及相关的思考. 内存Webshel ...

  2. java语言程序设计教程课后题答案魏永红_《Java语言程序设计教程》习题参考答案...

    1 / 23 < Java 语 言 程 序 设 计 教 程 > 习 题 参 考 答 案 第 1 章 习题参考答案 一.选择题 1 . B 2 . D 3 . C 4 . B 5 . A 6 ...

  3. controller方法名一样参数传递不同如何根据参数匹配_【Java学习 | Javase】方法

    整理自:动力节点Javase基础讲义.<Java核心技术> 方法 前言 方法的出现是为了实现代码的复用,对于功能性代码,我们希望不要重复写,而是独立出来,可以被重复的调用 所以,方法是一段 ...

  4. java语言程序设计教程翁恺第二版课后答案_《JAVA语言程序设计教程(第2版)/翁恺 肖少拥》翁恺,肖少拥著【摘要 书评 在线阅读】-苏宁易购图书...

    第1章  Java语言概述 1.1  Java的历史 1.2  Java程序运行环境与特点 1.2.1  跨平台(Cross Platform)/可移植性(Portablc) 1.2.2  运行效率 ...

  5. java疯狂讲义第四版第五章答案_疯狂java讲义第五章笔记

    1 定义类,成员变量和方法 类和对象 定义类 java的类名由一个或者多个有意义的单词组合而成,每个单词的首字母大写,其他的全部消协,并且单词之间没有分隔符. 成员变量:用于定义该类或者实例的所包含的 ...

  6. java中bigdecimal除以int类型的数据怎么实现_大部分Java程序员都会忽略的几个问题,你中招没?...

    1. 正确使用 equals 方法 Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals. 举个例子: 运行上面的程序会抛出空指针异常,但是我们把第二行的条件 ...

  7. java正则表达式 匹配()_学习Java正则表达式(匹配、替换、查找)

    import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public c ...

  8. java求最后一位不为0的数字_【Java】 剑指offer(62) 圆圈中最后剩下的数字

    本文参考自<剑指offer>一书,代码采用Java语言. 题目 0, 1, -, n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字 ...

  9. java 重载匹配_关于Java重载方法匹配优先级

    今天看到了一条这样的题目: 写出以下程序的输出: public class Overload { public static void say(long arg) { System.out.print ...

最新文章

  1. Java代码块总结(速读版)
  2. python语言if语句-Python在if语句中等同于(logical-and)
  3. LeetCode 452 Minimum Number of Arrows to Burst Balloons(贪心法)
  4. 【Windows 逆向】OD 调试器工具 ( OD 附加进程 | OD 调试器面板简介 | 反汇编窗口 | 寄存器窗口 | 数据窗口 | 堆栈窗口 )
  5. 汇编:call指令的应用
  6. LOJ#6281. 数列分块入门 5
  7. 制作多域名(SAN/UCC)CSR(证书请求文件)
  8. 【Spring实战4】04---装配Bean(自动装配)
  9. 移动端web自适应适配布局解决方案
  10. 【英语学习】【WOTD】cacophony 释义/词源/示例
  11. javascript中的cookie问题
  12. 2020最常用的8个代码编辑器推荐
  13. 数据库sql操作实验报告
  14. Win7系统显示文件扩展名的方法
  15. 嵌入式开发培训好学吗?嵌入式培训课程怎么选?
  16. 名词用作动词举例_古语名词使动用法解析
  17. docker镜像仓库habor1.10.0安装配置-单机版
  18. 进位位判别法_图解停车进位方法及如何确定车距
  19. Windows图标-Icon文件格式分析
  20. Salesforce触发器面试题

热门文章

  1. android自定义属性dimen,Android获取非自定义属性值
  2. php网站怎么对接微信群,PHP对接微信公众平台消息接口开发流程教程
  3. ashx获取input file 文件_通过Ajax方式上传文件(input file),使用FormData进行Ajax请求...
  4. dat图片 电脑端微信_微信 PC 版迎来了重磅更新,可以在电脑端使用小程序了 !...
  5. CSS基础——CSS字体样式属性【学习笔记】
  6. 剑指offer面试题[10]-二进制中1的个数
  7. 2022春季“金三银四”跳槽必备:软件测试面试题(附带答案)
  8. 技术点:注意Java的java.util.List.subList的坑
  9. mysql 主从 索引_Mysql繁忙主从库在线修改表结构与添加索引问题
  10. mysql fulltext类型_mysql索引类型:FULLTEXT、NORMAL、SPATIAL、UNIQUE的详细介绍(转)