ES文件瀏覽器CVE-2019-6447漏洞分析
漏洞名稱
ES File Explorer Open Port Vulnerability - CVE-2019-6447
漏洞簡介
ES文件瀏覽器在啟動時創建了一個HTTP伺服器,在本地打開了59777埠。攻擊者通過構造指定的payload可以獲取用戶手機文件,安裝apk等操作。
影響範圍
4.1.9.7.4 and below(部分版本可能不支持,也可能和應用市場有關)
漏洞分析
從fs0c131y所給出的信息來說
CVE-2019-6447影響的ES應用版本為4.1.9.7.4以下,
但是在某些版本的應用該漏洞卻無法利用,例如從華為和google play商店下載的ES就無法順利復現該漏洞,向59777埠發送payload一直會回復500 ERROR報錯,下面將詳細對該漏洞進行分析。4.1.9.4版本應用分析
以下是選擇了
4.1.9.4版本的ES文件瀏覽器進行了分析,該版本ES能夠成功利用該漏洞。
首先對APK解包後發現存在三個DEX文件。
先簡單看了下lib中的庫發現應用沒有加殼,用grep篩查以下59777確定相關代碼可能在classes2.dex中。
把classses2.dex反編譯後,全局搜索command發現存在漏洞的類在com/estrongs/android/f/a之中,而觸發漏洞的函數為com/estrongs/android/f/a.a。
簡單看下來a.class,b.class,c.class可能都和該漏洞的服務相關,其中a.class繼承了c.class。
下面來看下整個漏洞的觸發過程,由於混淆代碼不管是丟進jeb中還是smali閱讀起來都比較費力,為此我們可以先動態的將程序跑一邊後記錄trace,分析android trace文件來查看函數調用棧(利用TraceReader讀取)。
記錄trace的方法如下:
在DDMS上成功打開Trace之後,我們就要去構造payload去觸發該漏洞,漏洞具體利用payload見github(https://github.com/fs0c131y/ESFileExplorerOpenPortVuln)。
curl --header "Content-Type: application/json" --request POST --data "{"command":getDeviceInfo}" http://192.168.13 7.10:59777 -vvv
把tracer文件丟到TraceReader查看調用棧,可以發現程序進入com/estrongs/android/f/c$a.run()V來處理了我們的請求,注意這裡的類的實例化對象其實是a.class而不是c.class。:
首先接受socket然後讀到buffer中提取數據
然後判斷是不是post數據,如果是post請求則對content-type進行解析,當所有的前置解析完成後最後程序會來到label_189處
label189中,執行了v27 = this.a.aparseurlotherdata(v9, v10, v11, v6, v7);來進一步解析並執行相應的command。
這裡有一個問題,如果JEB直接雙擊來跟蹤函數會跳轉到自己類中的函數,而實際真正調用的是a.class(com/com/estrongs/android/f/a)中的函數aparseurlotherdata(這裡我對混淆函數名重命名了實際上原本的函數名是a)。
下圖是JEB錯誤跳轉到函數的位置,實際上我們應該分析的是a.class中的aparseurlotherdata:
繼續追蹤下去來到就來到了我們一開始漏洞觸發的地方(com/estrongs/android/f/a.a):
關於這個地方的分析其實有很多文章以及做過了,這裡就不再過多提及了。
解析對應的command調用對應的功能函數後返回json:
最後進入com/estrongs/android/f/c$a.a(Ljava/lang/String;Ljava/lang/String;Ljava/util/Properties;Ljava/io/InputStream;)V將response寫回。
該函數將輸出的結果寫入到OutputStream中然後將其返回。
該ES版本整個漏洞的觸發流程大致就如上所示。
這裡有一個需要注意的地方,如果是不存在漏洞的ES應用v2_7是為null的也就會進入this.a("500 Internal Server Error", "SERVER INTERNAL ERROR: Serve() returned a null response.");中,這也是很多應用市場上的ES應用都會到報500錯誤的原因。
4.1.6.6.1版本應用分析
以下將對4.1.6.6.1版本ES文件管理器進行分析,該版本的ES文件管理器沒有順利觸發漏洞。
直接curl個看看,500報錯了。
拆包靜態看一遍,代碼基本上還是在f包中,但是多了很多其他的類,a.class依然是ESHttpServer實現的地方。
再curl一個包抓取一下調用棧。
curl --header "Content-Type: application/json" --request POST --data "{"command":getDeviceInfo}" http://192.168.0. 122:59777 -vvv
錯略比對發現在這個版本的ES中多了一些函數,可能是做了某一些的校驗邏輯。
靜態分析代碼,發現前面的邏輯和之前app差不多,但是在執行完com.estrongs.android.f.h.a(Ljava/lang/String;Ljava/util/Properties;)V後又調用了bJ。
跟入bJ,bJ驗證了了url並且ap.a()方法檢測當前環境是否處於WIFI環境下。
繼續往下跟蹤,我們來到問題點!bp.q() || !f.e(v8)) && !f.a(v8, v25)這裡返回了true導致flagobject為null值所以伺服器返回了500。
bq.q()為true或者f.e以及f.a為true才能進入邏輯
跟蹤進入bq.q(),要滿足bp.p()和cw.e()都為true。
而FexApplication.a().getSystemService("uimode").getCurrentModeType() == 4成立的時候bp.p()才能為true,根據官方文檔4的uimode為UIMODETYPE_TELEVISION。
在cw.e中需要滿足一定的界面長寬需求
boolean v0_1 = Math.sqrt(Math.pow((((double)v0.heightPixels)) * 1 / (((double)v0.densityDpi)), 2) + Math.pow((((double)v0.widthPixels)) * 1 / (((double)v0.densityDpi)), 2)) >= 20 ? true : false;
而另外的f.e(v8),f.a(v8, v2_5)函數則負責校驗了我們的ip。
此外存在另外一種情況是當我們的ip為127.0.0.1時候flag_object能不為null,但首先你要滿足v4=null這個先覺條件。
查看v4 = as.bJ(v9),之前已經說過bJ函數負責校驗了url,我們再重新回到bJ發現return null好像不太可能,v9不管uri如何構造都會以"/"開始。
也就是說在應用市場上的ES版本不管是走if((!bp.q() || !f.e(v8)) && !f.a(v8, v25))還是走if(v4 != null && as.I(v4) != 0)似乎都不能出發到flagobject = v8_1.a(v9, v10, v11, v6, v7)的邏輯,這樣該漏洞就沒法觸發,但說不定還有其他的繞過方法,希望大家能夠多多補充。
參考資料
https://www.chainnews.com/articles/873565939043.htm
https://www.52pojie.cn/thread-856993-1-1.html
https://blog.csdn.net/caiqiiqi/article/details/86558862
https://bbs.ichunqiu.com/thread-49689-1-1.html
*
本文作者:xcy_merlin;轉載請註明來自 FreeBuf.COM
※看我如何通過ASP Secrets讀取獲得了1.7萬美金的漏洞獎勵
※圖文詳解Google緣何遭「5000萬歐元罰單滑鐵盧」
TAG:FreeBuf |