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
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
2.2 命令执行时的漂移
对,你没听错,在这样的环境下我们发出去的webshell执行命令时,会发生严重的漂移现象。你永远不知道命令在哪台服务器上执行。
假设我们解决了第一个难点,webshell均匀的出现在了后端节点服务器上。
我们将先前失效的webshell复活:
root@bab0805650c1:/usr/local/tomcat/webapps/ROOT# mv ant ant.jsp
到命令执行界面尝试执行命令:
执行查看IP地址的命令:
2.3 大工具投放失败
当我们解决了上面两个难点,想要进一步渗透时,此时投放一些工具是很必要的工作。但是碍于 antSword 上传文件时,采用的分片上传方式。把一个文件分成了多次HTTP请求发送给了目标,所以尴尬的事情来了,两台节点上,各一半,而且这一半到底是怎么组合的,取决于 LBS 算法。也就是说,我们的工具一旦大于这个最小分片大小。就会被拆分成碎片传递给节点服务器。
2.4 内网穿透工具失效
由于目标机器不能出外网,想进一步深入,只能使用 reGeorg/HTTPAbs 等 HTTP Tunnel,可在这个场景下,这些 tunnel 脚本全部都失灵了。
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”; f
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
这样一来,确实是能够保证执行的命令是在我们想要的机器上了,可是这样执行命令,不够丝滑。甚至其在蚁剑的中断内运行会出问题。在真机上测试正常。
这样的方案确实很麻烦,并且并不能解决我们内网穿透的需求,所以不推荐使用。