本文由360雲安全-jweny原創發佈
原文鏈接:https://www.anquanke.com/post/id/230935
0x01 漏洞描述
Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼和會話管理。使用Shiro的易於理解的API,您可以快速、輕鬆地獲得任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序。
當它和 Spring 結合使用時,在一定權限匹配規則下,攻擊者可通過構造特殊的 HTTP 請求包完成身份認證繞過。
影響範圍:Apache Shiro < 1.7.1
0x02 漏洞環境搭建
shiro 1.7.0
https://github.com/jweny/shiro-cve-2020-17523
0x03 poc測試
http://127.0.0.1:8080/admin/%20
使用空格等空字符,可繞過shiro身份驗證。
0x04 漏洞分析
漏洞環境中,/admin/*
所匹配的url都應在shiro的鑑權範圍內。shiro校驗path的函數爲pathMatches。pathMatches返回true時,匹配命中的url纔會進入後續的鑑權邏輯。
在org.apache.shiro.util.AntPathMatcher#doMatch方法的pathMatches處下斷點。
先手工驗證下漏洞產生原因:
調出Evaluate,計算一下pathMatches("/admin/*","/admin/1")
,正常匹配,返回true。
計算一下pathMatch("/admin/*","/admin/ "),正常失敗了,返回false,不會鑑權,但是spring接受到的是url是/admin/%20
,返回正產頁面admin page。
開始跟隨調試:
調試開始會經過一陣無聊的F7。一直到doMatch("/admin/*","/admin/ ")
。
可見,tokenizeToStringArray
返回的pathDirs已經沒有空格了。因此會導致/admin/*
和/admin/
不匹配。
這裏簡單說一下爲什麼不是shiro的匹配函數matchStrings()
的問題。matchStrings()
在匹配*
時,只要要匹配的字符串不是空,均返回匹配成功。因此只有空格被刪的情況下,纔會出現與*
匹配失敗。
可見是tokenizeToStringArray
造成的。跟一下tokenizeToStringArray
方法,發現其調用tokenizeToStringArray
方法時的trimTokens
參數爲true。
而tokenizeToStringArray
方法,在參數trimTokens
爲true時,會經過trim()
處理,因此導致空格等空白字符被清除。
總結一下:存在漏洞的shiro版本,由於調用tokenizeToStringArray
方法時,trimTokens
參數默認爲true,導致空格等空白字符被刪,因此無法與pattern*
匹配,導致該路徑無法經過鑑權。但是spring接受到的訪問路徑爲/admin/%20
,按照正常邏輯返回響應,因此導致權限被繞過。
0x05 官方的修復方案
經過以上的分析,修復方案已經很明確了,將trimTokens
設置爲false。
0x06關於trim
原理上來說trim()
會清空字符串前後所有的whitespace,空格只是其中的一種,但是在測試中發現除了空格以外的其他whitespace,例如%08
、%09
、%0a
,spring處理時都會返回400。
因此除了空格,尚未發現其他好用的payload。
本文由 Seebug Paper 發佈,如需轉載請註明來源。本文地址:https://paper.seebug.org/1478/