负载均衡下的 WebShell 连接

目录

  • 负载均衡简介
    • 负载均衡的分类
    • 网络通信分类
  • 负载均衡下的 WebShell 连接
    • 场景描述
    • 难点介绍
    • 解决方法
      • **Plan A** **关掉其中一台机器**(作死)
      • **Plan B** **执行前先判断要不要执行**
      • **Plan C** 在Web 层做一次 HTTP 流量转发 (重点)

负载均衡简介

负载均衡(Load Balance,简称 LB)是高并发、高可用系统必不可少的关键组件,目标是 尽力将网络流量平均分发到多个服务器上,以提高系统整体的响应速度和可用性。

负载均衡的主要作用如下:

高并发:负载均衡通过算法调整负载,尽力均匀的分配应用集群中各节点的工作量,以此提高应用集群的并发处理能力(吞吐量)。

伸缩性:添加或减少服务器数量,然后由负载均衡进行分发控制。这使得应用集群具备伸缩性。

高可用:负载均衡器可以监控候选服务器,当服务器不可用时,自动跳过,将请求分发给可用的服务器。这使得应用集群具备高可用的特性。

安全防护:有些负载均衡软件或硬件提供了安全性功能,如:黑白名单处理、防火墙,防 DDos 攻击等。

负载均衡的分类

硬件负载均衡
硬件负载均衡,一般是在定制处理器上运行的独立负载均衡服务器,价格昂贵,土豪专属。硬件负载均衡的主流产品有:F5 和 A10。

硬件负载均衡的 优点:

功能强大:支持全局负载均衡并提供较全面的、复杂的负载均衡算法。

性能强悍:硬件负载均衡由于是在专用处理器上运行,因此吞吐量大,可支持单机百万以上的并发。

安全性高:往往具备防火墙,防 DDos 攻击等安全功能。

硬件负载均衡的 缺点:

成本昂贵:购买和维护硬件负载均衡的成本都很高。

扩展性差:当访问量突增时,超过限度不能动态扩容。

软件负载均衡
软件负载均衡,应用最广泛,无论大公司还是小公司都会使用。

软件负载均衡从软件层面实现负载均衡,一般可以在任何标准物理设备上运行。

软件负载均衡的 主流产品 有:Nginx、HAProxy、LVS。

LVS 可以作为四层负载均衡器。其负载均衡的性能要优于 Nginx。

HAProxy 可以作为 HTTP 和 TCP 负载均衡器。

Nginx、HAProxy 可以作为四层或七层负载均衡器。

软件负载均衡的 优点:

扩展性好:适应动态变化,可以通过添加软件负载均衡实例,动态扩展到超出初始容量的能力。

成本低廉:软件负载均衡可以在任何标准物理设备上运行,降低了购买和运维的成本。

软件负载均衡的 缺点:

性能略差:相比于硬件负载均衡,软件负载均衡的性能要略低一些。

网络通信分类

软件负载均衡从通信层面来看,又可以分为四层和七层负载均衡。

  1. 七层负载均衡:就是可以根据访问用户的 HTTP 请求头、URL 信息将请求转发到特定的主机。

DNS 重定向

HTTP 重定向

反向代理

  1. 四层负载均衡:基于 IP 地址和端口进行请求的转发。

修改 IP 地址

修改 MAC 地址

负载均衡下的 WebShell 连接

其中像 HTTP 重定向方式、DNS方式等能够直接访问到单一机器的情况,不在我们本文讨论范围内。连接的时候,URL处按 IP 格式来填,然后把域名加在 Host 头处,就完事了。我们重点讨论不能直接访问到跑着具体业务的某个节点的情况,比如说「反向代理方式」。

反向代理方式其中比较流行的方式是用 nginx 来做负载均衡。我们先简单的介绍一下 nginx 支持的几种策略:

名称 策略
轮询(默认) 按请求顺序逐一分配
weight 根据权重分配
ip_hash 根据客户端IP分配
least_conn 根据连接数分配
fair (第三方) 根据响应时间分配
url_hash (第三方) 根据URL分配

其中 ip_hash、url_hash 这种能固定访问到某个节点的情况,我们也不讨论,跟单机没啥区别么不是。

我们以默认的「轮询」方式来做演示。
负载均衡下的 WebShell 连接_第1张图片
为了方便解释,我们只用两个节点,启动之后,看到有 3 个容器(你想像成有 3 台服务器就成)。
负载均衡下的 WebShell 连接_第2张图片
Node1 和 Node2 均是 tomcat 8 ,在内网中开放了 8080 端口,我们在外部是没法直接访问到的。
我们只能通过 nginx 这台机器访问。nginx 的配置如下:
负载均衡下的 WebShell 连接_第3张图片

场景描述

OK,我们假定在真实的业务系统上,存在一个 RCE 漏洞,可以让我们获取 WebShell。

我们先按常规操作在蚁剑里添加 Shell
负载均衡下的 WebShell 连接_第4张图片
然后连接目标,因为两台节点都在相同的位置存在 ant.jsp,所以连接的时候也没出现什么异常。

难点介绍

难点一:我们需要在每一台节点相同位置都上传相同内容的 WebShell

一旦有一台机器上没有,那么在请求轮到这台机器上的时候,就会出现 404 错误,影响使用。是的,这就是你出现一会儿正常,一会儿错误的原因。

难点二:我们在执行命令时,无法知道下次的请求交给哪台机器去执行

我们执行 ip addr 查看当前执行机器的 ip 时,可以看到一直在飘,因为我们用的是轮询的方式,还算能确定,一旦涉及了权重等其它指标,就让你好好体验一波什么叫飘乎不定。

难点三:当我们需要上传一些工具时,麻烦来了
我们本地的 111.png 大小是 2117006, 由于 antSword 上传文件时,采用的分片上传方式,把一个文件分成了多次HTTP请求发送给了目标,所以尴尬的事情来了,两台节点上,各一半,而且这一半到底是怎么组合的,取决于 LBS 算法,这可怎么办?

难点四:由于目标机器不能出外网,想进一步深入,只能使用 reGeorg/HTTPAbs 等 HTTP Tunnel,可在这个场景下,这些 tunnel 脚本全部都失灵了。

如果说前面三个难点还可以忍一忍,那第四个难点就直接劝退了。这还怎么深入内网?

解决方法

Plan A 关掉其中一台机器(作死)

是的,首先想到的第一个方案是关机/停服,只保留一台机器,因为健康检查机制的存在,很快其它的节点就会被 nginx 从池子里踢出去,那么妥妥的就能继续了。

但是这个方案实在是饮鸩止渴,影响业务,还会造成灾难,直接 Pass 不考虑。(实验环境下,权限够的时候是可以测试可行性的)。

*综合评价*:真实环境下千万不要尝试!!!!

Plan B 执行前先判断要不要执行

我们既然无法预测下一次是哪台机器去执行,那我们的 Shell 在执行 Payload 之前,先判断一下要不要执行不就行了?

以执行命令时 Bash 为例,在执行前判断一下 IP:
负载均衡下的 WebShell 连接_第5张图片
效果大概就是这个样子:

负载均衡下的 WebShell 连接_第6张图片
这样一来,确实是能够保证执行的命令是在我们想要的机器上了,可是这样执行命令,不够丝滑,一点美感都没有。另外,上传文件、HTTP 隧道 这些要怎么解决?

综合评价:该方案 「勉强能用**」**,仅适合在执行命令的时候用用,不够优雅。

Plan C 在Web 层做一次 HTTP 流量转发 (重点)

没错,我们用 AntSword 没法直接访问 LBSNode1 内网IP(172.23.0.2)的 8080 端口,但是有人能访问呀,除了 nginx 能访问之外,LBSNode2 这台机器也是可以访问 Node1 这台机器的 8080 端口的。
负载均衡下的 WebShell 连接_第7张图片
还记不记得 「PHP Bypass Disable Function」 这个插件,我们在这个插件加载 so 之后,本地启动了一个 httpserver,然后我们用到了 HTTP 层面的流量转发脚本 「antproxy.php」, 我们放在这个场景下看:

负载均衡下的 WebShell 连接_第8张图片
我们一步一步来看这个图,我们的目的是:所有的数据包都能发给「LBSNode 1」这台机器。

首先是 第 1 步,我们请求 /antproxy.jsp,这个请求发给 nginx

nginx 接到数据包之后,会有两种情况:

我们先看黑色线,第 2 步把请求传递给了目标机器,请求了 Node1 机器上的 /antproxy.jsp,接着 第 3 步,/antproxy.jsp 把请求重组之后,传给了 Node1 机器上的 /ant.jsp,成功执行。

再来看红色线,第 2 步把请求传给了 Node2 机器, 接着第 3 步,Node2 机器上面的 /antproxy.jsp 把请求重组之后,传给了 Node1 的 /ant.jsp,成功执行。

优点:

  • 低权限就可以完成,如果权限高的话,还可以通过端口层面直接转发,不过这跟 Plan A 的关服务就没啥区别了
  • 流量上,只影响访问 WebShell 的请求,其它的正常业务请求不会影响。
  • 适配更多工具

缺点:

  • 该方案需要「目标 Node」和「其它 Node」 之间内网互通,如果不互通就凉了

你可能感兴趣的:(负载均衡,运维)