(本文作者:VisualThreat 车联网安全公司 CEO 严威)
最近的比亚迪云服务漏洞事件,实际上映射出一种不对称的比赛: 缺少安全防护近似裸奔的车厂和全副武装的安全公司的对峙。车厂在小心翼翼推出其车联网云服务的时候,不时会受到安全公司的阻击,曝光其安全漏洞。由于采用简单粗暴的直接媒体点名曝光的方式,汽车厂商会觉得沮丧和懊恼。当然,这不能怪车厂,连美国三大汽车厂商都没有一支人数众多专业的安全团队,连特斯拉和宝马车载云服务都之前都被 KO,我们对国内厂商又能有多高的期望呢?
问题在于:面对这场必输的被点名参战的比赛,车厂能否输的体面些或者尽力避免这样的比赛?对于比亚迪破解事件而言,之前的两件事可能会引出这一事件的另外一种结局。
时间回到 2015 年 4 月,VisualThreat 车联网安全公司在汽车科技媒体 geekcar 上发布了业界第一份车联网应用安全现状报告。基于对近 15 大类 300 个汽车应用的安全分析,报告研究表明,汽车应用安全漏洞隐患 2015 年比 2014 年更严重,市场需要专门针对汽车应用的安全审计机制。
2015 年 6 月 8 日 VisualThreat 的车联网应用漏洞自动监控平台捕获到比亚迪云服务应用 V2.5 版本有多个高危漏洞(本文后面会详细说明)。两个星期之后,360 团队爆出比亚迪云服务漏洞。VisualThreat 还专门和 360 该团队沟通了他们发现的安全漏洞, 确认双方发现的高危漏洞一致,如果这些漏洞事先得到修补,会使得攻击技术门槛提高很多。
假设一下,如果是比亚迪自己先于媒体渠道知晓其应用中存在的漏洞并且进行了修复和版本更新,或者能避免被曝光。退一步讲,至少在攻防赛中也能和 360 的团队鏖战几十回合虽败犹荣。
言归正传,下面把比亚迪云服务应用的安全性和业界平均水平进行比较来说明:为什么比亚迪输的一点都不冤。
FACT1:通信没有加密
《2015 汽车移动应用安全现状报告》中的一项指标是通信加密。77%的汽车应用通信没有加密,比亚迪的这次被破解恰恰被利用到了这一点漏洞,也就是说,比亚迪的应用很不幸属于这 77%之中。
FACT2:平均每个汽车应用有 5-7 个中高危安全漏洞
比亚迪的这款应用属于「车厂定制」的分类。4 月份出炉的《2015 汽车移动应用安全现状报告》有一段原话:另外一个有趣的发现是,虽然车厂对汽车的协议、用户数据有得天独厚的占有优势,但是整车厂针对自己品牌汽车定制的移动应用在安全方面却让人大跌眼镜,平均 7.5 个安全漏洞也是「高居榜首」。这句话不幸被言中了,比亚迪中枪了。比亚迪云服务应用除了低危漏洞,还包括 9 个中高危漏洞,比平均水平还要高许多。换句话说:不欺负你还欺负谁啊!
FACT3:常见安全漏洞
汽车应用中最常见安全漏洞排名前三的是通信不安全,代码无混淆,和中间人攻击。如下图所示。比亚迪的应用至少有两项都占了。
如果我们要细分,下表是按照应用的不同分类总结出来的安全数据,最后一行是车厂定制类。
表 2. 汽车行业应用细分安全漏洞分布图
Vulnerability | URI Exposure |
URL Exposure |
Component Exposure |
Exposed Access Privilege |
Repackage | Code Confusion |
Unsecured Communication |
Man-in-the-Middle Attack |
Number Of Vulnerabilities |
160 | 217 | 168 | 124 | 124 | 215 | 226 | 176 |
OBD | 36.9% | 75.4% | 40.0% | 36.9% | 58.5% | 67.7% | 95.4% | 41.5% |
导航地图 | 60.6% | 63.6% | 66.7% | 51.5% | 30.3% | 69.7% | 66.7% | 66.7% |
租车 | 74.2% | 90.3% | 58.1% | 38.7% | 22.6% | 80.6% | 96.8% | 87.1% |
保养 | 67.9% | 60.7% | 67.9% | 53.6% | 42.9% | 67.9% | 67.9% | 46.4% |
汽车诊断 | 56.0% | 60.0% | 60.0% | 32.0% | 64.0% | 88.0% | 88.0% | 56.0% |
汽车资讯 | 52.9% | 82.4% | 52.9% | 41.2% | 70.6% | 76.5% | 70.6% | 70.6% |
购车 | 52.9% | 52.9% | 58.8% | 35.3% | 17.6% | 88.2% | 41.2% | 52.9% |
驾驶习惯 | 37.5% | 37.5% | 56.3% | 50.0% | 68.8% | 81.3% | 81.3% | 37.5% |
违章 | 80.0% | 50.0% | 90.0% | 40.0% | 20.0% | 30.0% | 40.0% | 90.0% |
打车 | 90.0% | 100.0% | 70.0% | 30.0% | 20.0% | 60.0% | 80.0% | 80.0% |
车厂定制 | 33.3% | 100.0% | 66.7% | 33.3% | 33.3% | 66.7% | 100.0% | 33.3% |
后面附上比亚迪 V2.5 版本的漏洞分析报告,如有不正确的地方,欢迎指正。
VisualThreat 安全测试报告
1. 软件概况
应用名称 | 比亚迪云服务 | 版本号 | 2.5.0 | |
文件大小 | 12520.6KB | 提交时间 | 2015-06-08 22:19:52 | |
MD5 值 | 8369878A566CB65D355C80D8E3D46418 | 处理时间 | 2015-06-08 23:05:43 |
这款应用是 2015 年 6 月 8 号通过应用商店下载后进行分析。
2. VisualThreat 汽车应用安全漏洞测试
2.1. 测试结论
分类 | 监测点 | 中高等级风险 |
代码安全 | 应用重打包 | 高 |
网络通信 | HTTPS 服务器未验证 | 高 |
网络通信 | HTTPS 证书未校验 | 高 |
网络通信 | WebView 远程代码攻击 | 高 |
数据存储 | 代码包含敏感信息 | 中 |
数据存储 | 程序数据任意备份 | 中 |
数据存储 | 资源文件包含敏感信息 | 中 |
功能安全 | 组件间通信中的隐式发送 | 中 |
代码安全 | Log 信息未清除 | 中 |
2.2 部分安全漏洞说明
漏洞现象
以下信息存在有 HTTPS 通信服务器未校验的问题。这次攻击就利用了这点。
#1 [SDK]:cn.sharesdk.framework.network.i.a()Lorg/apache/http/client/HttpClient;||||sget-object v0, Lorg/apache/http/conn/ssl/SSLSocketFactory;->ALLOW_ALL_HOSTNAME_VERIFIER:Lorg/apache/http/conn/ssl/X509HostnameVerifier;||||invoke-virtual {v1, v0}, Lorg/apache/http/conn/ssl/SSLSocketFactory;->setHostnameVerifier(Lorg/apache/http/conn/ssl/X509HostnameVerifier;)V||||
#2 [SDK]:m.framework.network.NetworkHelper.getSSLHttpClient()Lorg/apache/http/client/HttpClient;||||sget-object v0, Lorg/apache/http/conn/ssl/SSLSocketFactory;->ALLOW_ALL_HOSTNAME_VERIFIER:Lorg/apache/http/conn/ssl/X509HostnameVerifier;||||invoke-virtual {v1, v0}, Lorg/apache/http/conn/ssl/SSLSocketFactory;->setHostnameVerifier(Lorg/apache/http/conn/ssl/X509HostnameVerifier;)V||||
漏洞风险
即使做了对证书有效性的判断,但是如果没有验证云端服务器本身是否可信,仍然会造成伪装云端服务器而发生的中间人攻击。例如,攻击者可以盗用云服务平台可信证书,伪装服务器建通信对话,解密客户端发送的敏感信息,比如车主的信息(姓名、车牌号、车架号、身份证号、第二联系人姓名、手机号等)和控制密码,获取这些信息后伪装成用户通过云平台对车辆进行非法控制。
解决方案
移动软件大多只和固定的云服务器通信,因此可以在代码中更精确地直接验证是否某信任的服务器。
漏洞现象
以下信息存在有证书未校验的问题
#1 [SDK]:cn.sharesdk.framework.network.m.checkClientTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.method public checkClientTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.locals 0||||return-void||||.end method||||
#2 [SDK]:cn.sharesdk.framework.network.m.checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.method public checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.locals 0||||return-void||||.end method||||
#3 [SDK]:com.amap.api.services.core.k$b.checkClientTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.method public checkClientTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.locals 0||||return-void||||.end method||||
#4 [SDK]:com.amap.api.services.core.k$b.checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.method public checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.locals 0||||return-void||||.end method||||
#5 [SDK]:m.framework.network.SSLSocketFactoryEx$1.checkClientTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.method public checkClientTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.locals 0||||return-void||||.end method||||
#6 [SDK]:m.framework.network.SSLSocketFactoryEx$1.checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.method public checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;)V||||.locals 0||||return-void||||.end method||||
漏洞风险
客户端通过数字证书判断服务器是否可信,并采用证书中的公钥与服务器进行加密通信。开发者在代码中不检查服务器证书的有效性,或选择接受所有的证书,这种做法可能导致的问题是中间人攻击。
解决方案
移动软件大多只和固定的云服务器通信,因此可以在代码中更精确地直接验证是否某张特定的证书。
漏洞现象
以下代码进行了 Log 输出
#1 com.byd.aeri.caranywhere.CarStateDetail.a()V||||invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I||||
#2 com.byd.aeri.caranywhere.CarStateDetail.onCreate(Landroid/os/Bundle;)V||||invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I||||
#3 com.byd.aeri.caranywhere.CarStateDetail.onDestroy()V||||invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I||||
#4 com.byd.aeri.caranywhere.CarStateDetail.onPause()V||||invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I||||
#5 com.byd.aeri.caranywhere.CarStateDetail.onResume()V||||invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I||||
#6 com.byd.aeri.caranywhere.CarStatus.a(Landroid/graphics/Bitmap;Ljava/lang/String;Ljava/lang/String;)V||||invoke-static {v0, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I||||
#7 com.byd.aeri.caranywhere.CarStatus.a(Landroid/graphics/Bitmap;Ljava/lang/String;Ljava/lang/String;)V||||invoke-static {v1, v2}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I||||
#8 com.byd.aeri.caranywhere.CarStatus.j()V||||invoke-static {v0, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I||||
#9 com.byd.aeri.caranywhere.CarStatus.j()V||||invoke-static {v0, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I||||
#10 com.byd.aeri.caranywhere.CarStatus.j()V||||invoke-static {v0, v1}, Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I||||
由于篇幅限制还有更多……
漏洞风险
应用程序中 Log 调试开关未关闭,可能会导致被黑客利用熟悉业务流程。由于核心业务逻辑通过 Log 方式泄露,大大降低了对智能汽车的攻击门槛。这种攻击方式经常会被用到。
解决方案
在产品应用最终打包和发布的过程中移除相关的 Log 函数,避免敏感信息被攻击者截获,进而利用来对车辆进行控制。
漏洞现象
移动应用被反编译并且成功二次打包。
漏洞风险
攻击者将应用反汇编,然后在其中添加、修改、删除等一些指令序列;最后,将这些指令重新汇编并打包成新的 APK 文件,再次签名,就可以给其他手机安装了。通过重打包,攻击者可以加入恶意代码、改变软件的数据或指令,而软件原有功能和界面基本不会受到影响,用户难以察觉。比如通过应用重打包进行控制车辆的提权指令,在有效的云服务器授权期间,执行开启发动机行为。
漏洞现象
以下组件间通信未指定接收方,为隐式发送
#1 [SDK]:cn.sharesdk.framework.utils.e$b.b(ILjava/lang/String;)I||||invoke-direct {v0}, Landroid/content/Intent;-><init>()V||||invoke-virtual {v1, v0}, Landroid/content/Context;->sendBroadcast(Landroid/content/Intent;)V||||
漏洞风险
如果组件间通信为隐式调用,任何软件都可以响应这个调用请求。攻击者可以通过构造伪造的恶意组件,响应隐式调用的 Intent,可以读取请求组件间传输的数据,包括车主的信息和控制密码等,弹出虚假的用户界面以展开进一步钓鱼攻击。比如授权用户对车身的远程开关车门指令未到达执行组件,进而造成车身控制的失效。
漏洞现象
以下代码有被远程代码执行的可能
#1 com.byd.aeri.caranywhere.JoinEnergyCmpt.a()V||||invoke-virtual {v0, v1}, Landroid/webkit/WebSettings;->setJavaScriptEnabled(Z)V||||
#2 com.byd.aeri.caranywhere.Settings_Help.a()V||||invoke-virtual {v0, v1}, Landroid/webkit/WebSettings;->setJavaScriptEnabled(Z)V||||
#3 com.byd.aeri.caranywhere.Videoweb.onCreate(Landroid/os/Bundle;)V||||invoke-virtual {v0, v1}, Landroid/webkit/WebSettings;->setJavaScriptEnabled(Z)V||||
#4 com.byd.aeri.caranywhere.fz.run()V||||invoke-virtual {v0, v1}, Landroid/webkit/WebSettings;->setJavaScriptEnabled(Z)V||||
#5 [SDK]:cn.sharesdk.framework.authorize.g.b()Lcn/sharesdk/framework/authorize/RegisterView;||||invoke-virtual {v1, v4}, Landroid/webkit/WebSettings;->setJavaScriptEnabled(Z)V||||
漏洞风险
WebView 通过 JS 同服务器端交互在用户移动设备上展示页面,JS 可能包含恶意代码,造成恶意代码远程执行,实现对车辆的远程控制。