CVE-2019-6447_ES文件浏览器

CVE-2019-6447_ES文件浏览器

​ ES 文件浏览器,是一款基于 Android 系统的多功能手机文件、程序和进程管理器,它支持在手机、电脑、远程和蓝牙间浏览管理文件,在全球有超过亿次的下载量。
​ 基于 Android 平台的 ES File Explorer File Manager application 4.1.9.7.4 及之前版本中存在安全漏洞,该漏洞源于 ES 应用程序在运行一次之后(CVE-2019-6447),该端口并未关闭依旧可以通过 HTTP 协议 POST 请求接收 JSON 数据,进行解析执行返回结果。攻击者可通过向 TCP 59777 端口发送请求利用该漏洞读取任意文件或执行应用程序。

  • ES 文件浏览器在运行时会创建一个绑定在 59777 端口的 HTTP 服务,在该服务提供了 10+ 个命令,用于访问用户手机的数据以及执行应用程序;但该服务并没有对请求进行校验,从而导致出现安全漏洞。

触发条件

  • 版本 v4.1.9.7.4 或之前(修复该漏洞的版本为 v4.1.9.9 )
  • 复现设备与手机需处于同一局域网

复现环境

版本:v4.1.8.3.1(另外还有v4.1.6.7.2(返回500),v4.1.9.4(返回400))

工具:Android killer v1.3.1、dex2jar v2.1、jd-gui v1.6.6 (爱盘下载即可)

雷电模拟器 v4.0.27(模拟型号 HUAWEI WLZ-AN00)

ES文件浏览器工作原理

参考链接

基本原理:使用SMB协议和http服务器来实现

SMB协议的作用是访问局域网中的共享文件
http服务器作用是像我们平时访问网页视频那样,可以在线实时播放局域网视频

http服务器在手机里面,电脑和手机在同一个局域网内

SMB协议:SMB协议_百度百科
SMB(Server Message Block)通信协议是微软(Microsoft)和英特尔(Intel)在1987年制定的协议,主要是作为Microsoft网络的通讯协议。Windows系统就可以使用该协议进行文件传输。但是Android 不支持直接访问局域网的共享文件,所以要用到其它的开源库,来实现文件的访问

SMB协议和http服务器的实现
jcifs 实现smb协议 http://jcifs.samba.org/
实现http服务器 https://clinkc.svn.sourceforge.net/svnroot/cgupnpjava/trunk/
(或者用apache来实现http服务器 )Apache Commons Net

复现过程

先贴上程序运行的结果

POC

弹计算器(直接从雷电下载的小牛计算器)

当然也可以不使用poc,有一种更优雅的验证方式:curl,来自大佬的文章(是我太菜了555)

在复现过程中,遇到了不同类型的错误(400和500),专门查了一下错误原因:

1
2
3
4
5
6
7
8
9
10
HTTP状态码(HTTP Status Code)是用bai以表示网页服务器duHTTP响应状态的3位数字代码。它由 RFC 2616 规范定义的,并得到RFC 2518、RFC 2817、RFC 2295、RFC 2774、RFC 4918等规范扩展。
表示页面请求的状态值,分别有:
200 表示请求成功
303 表示重定向
400 表示请求错误,服务器不理解请求的语法
401 表示未授权
403 表示禁止访问
404 表示文件未找到
500 (服务器内部错误),服务器遇到错误,无法完成请求
更详细的可见https://www.cnblogs.com/buwang/p/9995738.html

由于是第一次复现移动端的CVE,一直不知道问题出在哪里。开始我一直以为是我模拟器的配置问题,或者是poc的py版本不对,但是在网上找大佬的笔记,怎么都不是这样的问题。一拍脑袋,试一下别的ES文件浏览器版本,先是返回500错误变成了400,最终直接用已经证实可以复现的版本,成功复现。

一开始是用Android killer反编译,确实很好用。拖进去,点一下,啪的一下就出来了,很快啊。

初步可以看出工程信息是大概的文件信息,工程管理器是文件的代码结构,具体可见这篇博客。再加上上面的工具栏,功能就更多了,以后会不断了解的。挖个坑Android killer使用

根据参考的文章,可以在工程管理器里找到对应的文件路径,但是点开的却是smali文件,如上图。于是我又不得不去查阅了一下安卓的各种文件格式,具体可以看我另一篇文章安卓文件格式(先挖个坑自己填)。

在对其他几个版本反编译的时候,出现了AndroidKiller APK 反编译失败的错误提示,在这篇文章找到了解决方式,其实不需要用到后面一个的方式,在这篇文章中提到的Debug工具,执行后会在其目录下的/temp路径出现反编译好的文件(下图为执行成功),直接将dex文件转为jar文件,再用jd-gui就可查看源码

关键步骤:dex –> jar

当然也可以直接用android killer直接转

右键将apk解压到本路径下,在文件夹中可以找到dex文件,利用dex2jar转换为jar文件,并用jd-gui打开。这里我试了linux下执行没能成功,不过直接用windows下的命令也问题不大。

漏洞分析

本次漏洞主要在:
com.estrongs.fs.impl.adb.c
com.estrongs.android.f.a

com.estrongs.android.f.a

在这个部分可以看到poc一样的内容,是ES浏览器自带的一些获取APP信息的函数,可以利用。我们追踪几个函数看看具体做了些什么

  • getDeviceInfo

如果字符串是”getDeviceInfo”,那么会返回b()

可以看出每个函数(不知道对不对,晚点再补一下java的知识)都有类似的结构,若request state code是200,则返回ok,若是400,500则有对应的错误处理机制

  • appLaunch

同样,查找a(),和查询设备信息同样的结构

传入appPackageName,从而打开app

其他功能也大同小异

com.estrongs.fs.impl.adb.c

关键字符串59777一共出现了三次,分别对应查找是如何利用59777端口的

根据函数参数类型查找对应的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public static boolean a(String paramString, int paramInt1, int paramInt2)
{
boolean bool2 = false;
for (;;)
{
int i = paramInt2 - 1;
boolean bool1 = bool2;
if (paramInt2 > 0)
{
if (b(paramString, paramInt1)) {
bool1 = true;
}
}
else {
return bool1;
}
if (e) {
com.estrongs.android.util.k.b(a, "adb list try count " + i);
}
try
{
Thread.sleep(200L);
paramInt2 = i;
}
catch (Exception localException)
{
localException.printStackTrace();
paramInt2 = i;
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
public static boolean b(String paramString, int paramInt)
{
try
{
Socket localSocket = new Socket();
localSocket.connect(new InetSocketAddress(paramString, paramInt), 2000);
localSocket.close();
return true;
}
catch (Throwable paramString) {}
return false;
}
  • adb

Android Debug Bridge (adb) 是一个android开发人员必会的多功能的调试工具,如它的名字一样,它在开发者和目标机器之间,架起了一座bridge。参考链接

补丁分析

用到了TraceReader等工具

https://www.androiddevtools.cn/

https://www.sohu.com/a/250396062_741445

参考链接:

https://www.freebuf.com/vuls/195069.html

https://blog.csdn.net/weixin_34248705/article/details/92250456

参考文章:

https://www.52pojie.cn/thread-856993-1-1.html

https://github.com/fs0c131y/ESFileExplorerOpenPortVuln


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!