产品人气榜

Android App安全质量保障实践分享

2020-05-15 19:00:20473人阅读

互联网公司的移动端业务基本都是基于各类App来承载,如果业务种类较多,那么App自身的安全质量(功能设计与编码实现等)保障就是一个比较有挑战的工作。一方面App本身数量较多、更新比较频繁,但是还需要每次针对各个App做到各有侧重的安全保障;另一方面,在人力投入上和其他安全建设方向一样,需要做到尽可能高的投入产出比,避免陷入重复工作困境。那么怎么尽可能以少而优的人力去批量、规模化解决App安全质量保障的问题呢?基于实际工作总结,Android App中的安全问题大部分都集中在容易产生的各类同质安全漏洞上,同时内部的轻量级SDL能力平台也具备了成熟实践的基础,基于这些条件并经过我们一段时间的实践,落地了一套适合大型企业级场景的Android App安全质量保障实践方案,在这里和大家分享交流。

整体上,App安全保障实践方案整体流程如图1.1所示:

1.png

图1.1 App安全保障实践流程图

在具体落地层面,要规模化保障App编码层面的安全,还需要解决如下头、尾两个问题

1) 如何确保业务线提交app代码进行白盒漏洞检测?

有两种方法,a)在研发流水线中,拉取提交到仓库的代码进行白盒扫描,检出结果通过漏洞处理平台来流程化的推进修复;b)申请人工评估的项目,业务线需要主动先进行白盒扫描并修复扫描出的典型漏洞,然后在评估申请中填写白盒扫描任务号

2) 如何统计该方案运行实践流程的实际落地效果呢?

白盒扫描的效果可以直接统计,SDL-SDK的使用效果则是通过在代码仓库中进行SDL-SDK的代码特征扫描,来进行SDL-SDK使用覆盖情况的统计

       整体上,此保障实践方案的优点主要有如下几个方面:

1) 业务方直接在编码阶段应用安全代码库、代码提交阶段使用白盒代码自动化安全审计,可以发现并自行解决约70%-80%的典型安全漏洞,避免在开发后期发现进而带来大量的修复与升级工作量
2) 针对典型漏洞的安全代码库简单易用,不会增加业务方额外开发量
3) 复用编码库,可以提高业务线典型场景的安全编码一致性并提高开发效率

下面主要从安全编码方案(SDL-SDK)和App代码白盒扫描这两个方面,来实例化介绍下具体的技术实现思路与Case。


1
安全编码方案(SDL-SDK)


App在编码实现过程中,经常容易产生一些典型安全漏洞,因此设计提供通用型SDL-SDK是可行的方式(为业务方提供一些常见安全功能服务组件,如安全webview、APK应用更新、IPC通信安全等等)。目前SDL-SDK已经在百度的多个核心App中集成使用,SDL-SDK极大的简化业务方相关开发时间/漏洞修复时间,同时也可以显著提高安全性,减少相关漏洞的重复产生。

以Android App中Binder IPC通信为例,应用A通过AIDL接口定义了并通过Service公开了如下接口:getUserInfo,根据用户名返回用户信息(包含手机号等敏感信息):


interface IMyAidlInterface {
    String getUserInfo(String userName);
}
 
public class MyBinder extends IMyAidlInterface.Stub{

    
@Override
    
public String getUserInfo(String userName) throws RemoteException {
        
if(userName.equals("zhangsan")){
            String jsonStr = 
"{'username':'zhangsan', 'telephone':'110','address','某市某区某街道**'}";
            
return jsonStr;
        }
        
return null;
    }
}

其他应用则可以随意调用‘getUserInfo’接口,获取用户的敏感信息:



public   void onServiceConnected(ComponentName name, IBinder service) {
    myaidlInterface =   IMyAidlInterface.Stub.asInterface(service);
    ... ...
}
...   ...
Strign   str = myaidlInterface.getUserInfo("zhangsan");

上述Binder IPC通信就存在典型的安全漏洞,攻击者可以通过调用Service暴露的AIDL接口,进行提权或者窃取用户信息。实际评估中也发现Binder IPC漏洞出现比较高频。另外少部分App使用socket端口通信的方式进行应用间进程通信,同样易产生安全漏洞。

针对上述安全漏洞,在规避/修复上主要需要完善安全可靠的身份校验机制,以确保对外提供服务接口的安全性。IPC通信安全流程如图1.2所示:

2.png

图1.2 IPC通信安全流程图

上述技术方案在技术实施的过程中,有如下两点需要注意:

A. 在Server的OnBind函数中,并不能通过“Binder.getCallingPid()”函数来获取调用者的“身份信息”,只能在Binder对外服务”接口的实现类”中进行;

B. Binder对外服务接口有如下两种方式,因此需在重要的AIDL接口和自己实现的onTransaction函数里都要对Client进行身份校验,避免遗漏。

1) AIDL接口;

2) 继承Binder实现并覆写onTransaction函数。




白盒扫描


白盒扫描是基于源码的静态漏洞扫描,其效果和准确性,严格依赖于代码的数据流和控制流分析,目前对于源代码静态扫描,通常可以可以分为三类:纯自研、开源+自研、商业,最终选用何种方式,可以根据团队人数、资金状态等综合考虑来选择。

目前百度的白盒扫描引擎一共支持20+多类Android App漏洞类型扫描,漏洞扫描检出准确率基本在98%以上(以确保准确率为前提,允许存在一些漏报case),下面以典型的top5类漏洞为例,进行白盒检测思路介绍,并选取“ZIP目录穿越漏洞”为例,进行更加详细的漏洞扫描检测规则设计介绍。


漏洞名称
检测思路
注意事项
Webview File域同源策略绕过
检测WebSetting. setJavaScriptEnabled(true)和WebSetting.setAllowFileAccess(true)是否都为true
setAllowFileAccess默认true,并且注意排除一些case,如:
if(url.trim().startsWith("file:"))
webView.getSettings().setJavaScriptEnabled(false)
Webview 远程命令执行
1)判断App最低版本是否小于17,然后判断WebSetting. setJavaScriptEnabled是否为true,为true的话进一步判断是否调用addJavascriptInterface添加任何JS和native交互接口,并且移除默认的3个JS交互接口;
2)addJavascriptInterface添加JS和native交互接口时,是否对加载的url做校验,未做校验的话则需要判定交互接口是否涉及敏感信息读取或者命令执行
1)域名校验需要时严格的host匹配
2)敏感信息接口除了系统API,一些涉及公司数据,要根据公司的业务方现状来定义API
Zip目录穿越
定位API:ZipEntry. getName,然后检测Zip文件解压的源文件是否来自SD卡,确定来自SD卡后,进一步判断是否对解压的文件名进行了“../”过滤
特列:下载外部传入的zip文件url,并保存到私有目录
应用安装/加载签名绕过漏洞
提取应用安装和动态加载的API,对APK的数据流处理进行分析,判断是否对APK进行了签名校验

binder不安全通信
获取所有AIDL接口实现函数和onTransact  ()函数,判断所有实现函数中是否调用了“Binder.getCallingPid()”对调用者进行身份校验
排除Biner service未导出的情况

ZIP目录穿越漏洞检测

漏洞产生原因:

因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件。如果被覆盖掉的文件是动态链接so、dex或者odex文件,轻则产生本地拒绝服务漏洞,影响应用的可用性,重则可能造成任意代码执行漏洞,危害用户的设备安全和信息安全。

Java代码在解压ZIP文件时,会使用到ZipEntry类的getName()方法,如果ZIP压缩的文件名中包含“../”字符串,该方法返回值里面原样返回,如果没有过滤掉getName()返回值中的“../”字符串,继续解压缩操作,就会覆盖其他目录中的文件。

漏洞演示:


    private void unzip(File zipFile, String destDir) throws IOException {
        ZipInputStream zipInputStream = new ZipInputStream(new CheckedInputStream(new FileInputStream(zipFile),new CRC32()));
        ZipEntry zipEntry;
        while ((zipEntry = zipInputStream.getNextEntry()) != null) {
            System.out.println(zipEntry.getName());
            File f = new File(destDir + zipEntry.getName());   //未做任何判断和过滤
            if(zipEntry.getName().endsWith("/")){
                f.mkdirs();
            }else {
//                f.createNewFile();
                FileOutputStream fileOutputStream = new FileOutputStream(f);
                byte[] buf = new byte[1024];
                int len = -1;
                while ((len = zipInputStream.read(buf)) != -1) {  // 直到读到该条目的结尾
                    fileOutputStream.write(buf, 0, len);
                }
                fileOutputStream.flush();
                fileOutputStream.close();
            }
            zipInputStream.closeEntry();  //关闭该条目
        }
        zipInputStream.close();
    }


漏洞检测规则:
1)通过代码索引,定位到API:“ZipEntry. getName”,然后获取到对象ZipEntry和函数ZipEntry. getName()的返回值;
2)判断第1步中的对象ZipEntry的数据流来源,对其进行数据流追踪,判断ZipEntry是否来源于SD卡上的文件,如果是来源于SD卡上的文件,则进行第3步,否则继续查找下一个ZipEntry对象;
3)进行API定位:String.contains("../")[通过字符串”../”查找函数contains],然后获取调用contains方法的对象,如果其是String类型,则对其进行数据流追踪,判断来源是否是“ZipEntry. getName()的返回值”,如果是就判定不存在该漏洞,否则判定存在该漏洞。

漏洞扫描流程如图1.3所示:

3.png

图1.3 目录穿越漏洞检测流程图




落地及效果


       在安全解决方案的落地实践上,我们主要聚焦于效能提升的思路来进行推广落地:(1)优先确保解决方案中关键能力的有效性(能解决关键安全问题);(2)在安全、业务侧的投入成本上要有清晰的收益并清晰的传达到业务侧。

       业务方在平时基本都聚焦在自己的需求研发工作中,在安全问题规避或解决上,业务方希望是能够投入尽可能少的人力或者最好不投入人力。因此对于我们实践方案的落地上,业务方一开始是容易有判断误区的,因为他们不会去细算这里的投入成本,通常习惯性做法就是:把需要安全review的交给安全,然后等着反馈问题并根据建议修复问题,甚至自己直接开发测试上线绕过安全(然后等着线上暴露安全问题,最后专门花人力来修复)。那我们的App安全保障实践方案刚开始落地时就需要做一些针对性运营工作:

1) 第一步:先找协同紧密且业务重要的业务线,针对其App进行试点性落地实践,让业务线负责人和核心研发非常了解保障实践方案的明确安全收益,进而做到落地实践的试点;
2) 第二步:基于标杆性试点效果case,进行内部定点的宣传,可以选择App产品和漏洞比较多的部门,可以对SDL-SDK的使用方式、白盒检测能力、相关漏洞危害、‘保障实践方案落地标杆’效果进行宣传,在方案的落地收益上让业务方逐步有认知。
3) 另外为了便于根据反馈来进一步完善App安全保障实践方案,需要建立一些咨询、交流可达性比较好的渠道来获取反馈,比如讨论组、‘App安全保障实践方案公开介绍’WIKI等等
4) 最后在整体方案落地实践已成熟的情况下,会进一步协同安全管理角色、研发流水线等一道,将方案落地执行以安全质量基准要求的规范方式来运营,以确保公司级App的基础安全质量做到切实保障。

基于我们的运营实践,18年至今App安全保障实践方案取得了很明显的收益:白盒扫描检出效果显著 (数据不便给出),SDL-SDK已经在10+多个业务线中集成使用。

整体上,一方面节省了安全工程师的时间、提高了工作效率,同时也让安全工程师能够从普遍性安全问题中解脱出来。



总结


本文主要基于我们的实践工作,总结分享了一套适合大规模场景的Android App安全质量保障实践方案。该保障实践方案主要基于安全编码方案(SDL-SDK)和源码白盒扫描,并辅助一些有效的推广运营落地策略,达到了规模化解决Android App安全质量保障的问题。


0
现金券
0
兑换券
立即领取
领取成功