Tomcat-Executor

0x01 Conntector Architecture

在Tomcat架构中,我们讲到Connector用于和客户端交互(socket通信),承担了HTTP服务器的功能。Connector主要由ProtocolHandler与Adapter构成。

image-20230204104009226

Connector就是依靠ProtocolHandler来处理网络连接和应用层协议。

ProtocolHandler构成:

  • Endpoint

  • Processor

ProtocolHandler下面有好几个子实现类

  • Ajp和Http11是不同的协议

  • Nio、Nio2、Apr是不同的通信方式

image-20230204122631635

我们关注Http11NioProtocol这个实现

EndPoint:通信监听的接口,是具体的 Socket 接收和发送处理器,是对传输层的抽象,可见EndPoint 是用来实现 TCP/IP 协议的,而Processor是用来实现HTTP协议的(NioEndpointHttp11NioProtocol中的实现。)

EndPoint五大组件:

  • LimitLatch:连接控制器,控制Tomcat所能接收的最大数量连接

  • Acceptor:负责接收新的连接,然后返回一个Channel对象给Poller

  • Poller:可以将其看成是NIO中Selector,负责监控Channel的状态

  • SocketProcessor:可以看成是一个被封装的任务类

  • Executor:Tomcat自己扩展的线程池,用来执行任务类

(NIO即New IO,高效率的IO)

0x02 Analysis

在Tomcat中Executor由Service维护,因此同一个Service中的组件可以共享一个线程池。如果没有定义任何线程池,相关组件( 如Endpoint)会自动创建线程池,此时,线程池不再共享。

org.apache.tomcat.util.net.NioEndpoint#run => processKey => processSocket

这里的executor是endpoint自己启动的ThreadPoolExecutor

接着调用了org.apache.tomcat.util.threads.ThreadPoolExecutor#execute

我们可以创建一个恶意的Executor类继承ThreadPoolExecutor,并重写其中的execute方法,那么在调用该方法的时候将会执行恶意代码

通过AbstractEndpoint#setExecutor将原本的executor换为我们构造的恶意executor

接下来还得思考怎么做到可以交互的内存马

命令获取以及回显

标准的ServletRequest需要经过Adapter的封装后才可获得,这里还在Endpoint阶段,其后面封装的ServletRequest和ServletResponse是不能直接获取的

NioEndpointnioChannels下的appReadBufHandler存放在HTTP请求信息

image-20230204152208896

可以把命令参数藏在HTTP请求头中

org.apache.catalina.connector.Response继承了HttpServletResponse

image-20230204145828153

AbstractProcessor在初始化时就会进行Tomcat Request与Response的创建,继承了AbstractProcessorHttp11Processor也是

可以通过上面这些方法把数据回显,选择addHeader来存放返回结果

(response结构体中的buffer不好扩容,后面可能出现问题)

0x03 POC

image-20230204170329107

感觉这个executor马不是很稳定。。。

参考:Executor内存马的实现 - 先知社区 (aliyun.com)

Last updated

Was this helpful?