侵刪

杂谈Java内存Webshell的攻与防

长小亭

网络安全知识的搬运工~

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

内存Webshell的利用方式

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

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

基于tomcat的内存 Webshell 无文件攻击技术 - 先知社区

xz.aliyun.com/t/7388

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

基于内存 Webshell 的无文件攻击技术研究

www.anquanke.com/post/id/198886

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

rebeyond/memShell

github.com/rebeyond/memShell

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

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

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

工具地址:

buptchk/ysoserial

github.com/buptchk/ysoserial

内存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/post/id/198886

为例子,可以直接观察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/alibaba/arthas/issues/763

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/t/8148

学习了一下关于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加载的,这样就做到了可以在任意地方调用自定义类加载器中的方法。

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

发布于 2020-09-09 10:24

【杂谈Java内存Webshell的攻与防】相关推荐

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

    这篇文章主要以Tomcat为例子记录了一些关于Java内存Webshell利用与检测以及相关的思考. 内存Webshell的利用方式 现在的内存Websell的利用方式个人感觉可以分为以下三种: 1. ...

  2. 浅谈大规模红蓝对抗攻与防

    文|腾讯蓝军 深夜饮酒 & leonc 编者按 蓝军(Blue Team)的价值是站在攻击者的位置从实战角度协助防守方发现问题,避免防守方在进行安全建设时以自我为中心纸上谈兵,所谓以攻促防是也 ...

  3. 初识Java内存马检测

    近些年,无文件攻击技术越来越流行.本文旨在介绍无文件攻击中最为流行的一种技术--Java内存马,让企业.用户了解和重视其危害性,提高防范意识,降低安全风险. - 全文约1500字,预计阅读时间为4分钟 ...

  4. Java内存模型深度剖析

    作者:Hollis,阿里资深攻城狮 来自:Hollis 为什么要有内存模型 在介绍Java内存模型之前,先来看一下到底什么是计算机内存模型,然后再来看Java内存模型在计算机内存模型的基础上做了哪些事 ...

  5. 面试题:请介绍⼀下 JMM(Java 内存模型)

    面试题:请介绍⼀下 JMM(Java 内存模型) 关键词 CPU缓存一致性协议(例如MESI),多个CPU核心之间缓存不会出现不同步的问题 Store Buffer.Load Buffer和L1之间却 ...

  6. JVM学习-Java内存模型JMM

    目录 1.Java内存模型概述 2.原子性 2.1.问题提出 2.2.问题分析 2.3.解决办法 3.原子性 3.1.退不出的循环 3.2 解决方法 3.3 可见性 4.有序性 4.1.诡异的结果 4 ...

  7. Java内存马攻防实战——攻击基础篇

    ​ 在红蓝对抗中,攻击方广泛应用webshell等技术在防守方提供的服务中植入后门,防守方也发展出各种技术来应对攻击,传统的落地型webshell很容易被攻击方检测和绞杀.而内存马技术则是通过在运行的 ...

  8. 明翰中高级Java后端面试题攻略v0.3(持续更新)

    文章目录 前言 Java基础 Java综合 请按顺序并按分类写出java的8种基本数据类型? Integer与int的区别? Object类中的方法的有什么,其作用? equals()与==的区别? ...

  9. 不好意思,我和 Java 内存模型杠上了!

    昨天发完 深入理解 Java 内存模型 后将文章转发到朋友圈后(附带开玩笑的说了句:拿着这篇文章.携上 JSR 133,老艿艿再也问不倒我了),刚好彤哥做了下点评(加上 CPU 缓存的架构来类比会更好 ...

最新文章

  1. PDF与doc格式互换
  2. url编码混乱下下载工具如何应对
  3. 【机器视觉】 dev_set_paint算子
  4. Kubernetes集群安全概述
  5. 提高编程能力的7条建议
  6. Transformer好文章阅读链接
  7. skynet源码阅读7--死循环检测
  8. 奇安信代码安全实验室帮助谷歌修复高危漏洞,获官方致谢
  9. WebBrowser.ObjectForScripting 属性的使用
  10. 资管运营BAND原创 | 他山之石:境外基金业绩报酬计算方法(二)
  11. php ksc歌词,KSC字幕制作方法 KSC歌词编辑教程
  12. 基于springboot的科技馆设备巡检系统
  13. linux下maxwell安装教程,Ubuntu下若干软件的安装方法
  14. 多种前端框架的优缺点
  15. KendoGrid的使用
  16. Tor出现需要控制密码的解决办法
  17. 模数转换 A/D 与数模转换 D/A介绍
  18. 使用web3.py获取zkSync中的数据
  19. 开源框架XWIKI搭建介绍
  20. 物联网在车联网中的应用

热门文章

  1. 阿里云 Aliplayer高级功能介绍(二):缩略图 1
  2. moto z2 force ATT版升级至8.0教程
  3. php实现九宫格连线,小程序之页面用九宫格及item跳转的功能实现
  4. GSMA世界移动大会:上海将移动科技融入大众生活
  5. 目标检测-小目标检测技巧
  6. 鸿蒙和小米和魅族,拒绝华为鸿蒙后,中兴给出新选择,魅族小米坐不住了
  7. ArcGIS for Android 100.3.0(6):动态地图图层(ArcGISMapImageLayer和ArcGISMapImageSublayer)
  8. 学习php要有什么基础_学习php需要什么基础?(附php学习路线图)
  9. 关于db2中的NOT LOGGED INITIALLY
  10. C++牛顿迭代法求根,用递归方法实现分析及代码