Android应用面临的安全漏洞种类繁多,要想从细节上吃透各类隐患并有针对性地布防,确实是一件相当耗费精力的事情。为了帮助大家建立相对完整的认知体系,我们特邀资深安全工程师,将常见的Android漏洞逐一拆解、深入剖析,希望能为你的安全防护工作提供有价值的参考。
第一大类:Android Manifest配置相关的风险或漏洞
1、程序可被任意调试
风险详情:在APK的AndroidManifest.xml中,android:debuggable=true,即调试开关处于开启状态。
危害情况:任何人均可对该App进行调试。
修复建议:将android:debuggable设置为false,关闭调试开关。
2、程序数据任意备份
风险详情:android:allowBackup=true,数据备份开关处于开启状态。
危害情况:App的应用数据可以被直接备份并导出。
修复建议:将android:allowBackup设置为false。如果涉及组件暴露,建议使用android:protectionLevel="signature"来验证调用来源。
3、Activity组件暴露
风险详情:当Activity的exported属性设为true,或者未设置但IntentFilter不为空时,该Activity被视为导出,可通过Intent唤起。
危害情况:攻击者可能构造恶意数据,对导出的Activity实施越权攻击。
修复建议:如果不需要与其他App共享,请设置为exported="false"。若确实需要共享,则必须添加权限控制与参数校验。
4、Service组件暴露
风险详情:当Service的exported属性设为true,或者未设置但IntentFilter不为空时,Service被视为导出,可通过Intent唤起。
危害情况:同样,攻击者可能利用导出的Service实施越权攻击。
修复建议:同上——不需要共享则关闭,需要共享则添加权限控制与参数校验。
5、ContentProvider组件暴露
风险详情:当ContentProvider的exported设为true,或者Android API ≤ 16时,ContentProvider被视为导出。
危害情况:攻击者可能访问到应用本不想共享的数据或文件。
修复建议:不需要共享则关闭,需要共享则添加权限控制与参数校验。
6、BroadcastReceiver组件暴露
风险详情:当BroadcastReceiver的exported设为true,或者未设置但IntentFilter不为空时,视为导出。
危害情况:导出的广播可能导致数据泄露或越权操作。
修复建议:不需要共享则关闭,需要共享则添加权限控制与参数校验。
7、Intent Scheme URLs攻击
风险详情:在AndroidManifest.xml中设置了Scheme协议后,可通过浏览器打开对应的Activity。
危害情况:攻击者通过浏览器构造Intent语法唤起App组件,轻则引发拒绝服务,重则可能导致越权调用甚至提权漏洞。
修复建议:对外部调用过程及传输数据进行安全检查,配置category filter,并添加android.intent.category.BROWSABLE以规避风险。
第二大类:WebView组件及与服务器通信相关的风险或漏洞
1、WebView存在本地Java接口
风险详情:WebView有一个特殊接口addJavascriptInterface,可以实现本地Java与JS的交互。
危害情况:在targetSdkVersion小于17时,攻击者可以利用该接口添加的函数远程执行任意代码。
修复建议:尽量不使用addJavascriptInterface,改用注入JavaScript或第三方协议替代。
2、WebView组件远程代码执行(调用getClassLoader)
风险详情:使用低于17的targetSDKVersion,并且在Context子类中用addJavascriptInterface绑定this对象。
危害情况:通过调用getClassLoader可绕过Google底层对getClass方法的限制。
修复建议:将targetSDKVersion升级到17以上。
3、WebView忽略SSL证书错误
风险详情:重写onReceivedSslError方法时,直接执行handler.proceed()忽略证书错误。
危害情况:忽略SSL证书错误可能引发中间人攻击。
修复建议:不要重写onReceivedSslError,或者根据业务场景判断,避免造成数据明文传输。
4、WebView启用访问文件数据
风险详情:setAllowFileAccess(true),App可通过WebView访问私有目录下的文件。
危害情况:默认值为true,在File域下可执行任意JavaScript,若绕过同源策略,就能访问私有文件,导致隐私泄露。
修复建议:使用mWebView.getSettings().setAllowFileAccess(false)禁止访问私有文件。
5、SSL通信服务端检测信任任意证书
风险详情:自定义SSL X509 TrustManager,重写checkServerTrusted方法,但方法内不做任何校验。
危害情况:攻击者可通过中间人攻击获取加密内容。
修复建议:严格校验服务端和客户端证书,异常事件禁止返回空或null。
6、HTTPS关闭主机名验证
风险详情:构造HttpClient时,HostnameVerifier参数使用ALLOW_ALL_HOSTNAME_VERIFIER或空的HostnameVerifier。
危害情况:关闭主机名校验,导致攻击者可通过中间人攻击获取加密内容。
修复建议:使用SSL时务必对证书的主机名进行校验,否则加密通信将被还原为明文。
7、SSL通信客户端检测信任任意证书
风险详情:自定义TrustManager,重写checkClientTrusted,不校验服务端证书。
危害情况:同样,中间人攻击可获取加密内容。
修复建议:严格校验,异常事件禁止返回空或null。
8、开放socket端口
风险详情:App绑定端口监听,建立连接后可接收外部数据。
危害情况:攻击者构造恶意数据对端口进行测试,绑定IP 0.0.0.0的App可被远程攻击。
修复建议:如无必要,仅绑定本地IP 127.0.0.1,并对接收数据做过滤和验证。
第三大类:数据安全风险
1、数据存储
SD卡数据被第三方程序访问
漏洞描述:调用getExternalStorageDirectory存储内容到SD卡,可被任意程序访问。
安全建议:敏感信息应存储到程序私有目录,并对数据进行加密。
全局File可读写漏洞——openFileOutput
风险详情:openFileOutput创建内部文件时,设置了全局可读权限MODE_WORLD_READABLE。
危害情况:攻击者恶意读取文件内容,获取敏感信息。
修复建议:确认文件是否包含敏感数据,如果是,则去除全局可读属性。
全局文件可写
风险详情:openFileOutput设置了全局可写权限MODE_WORLD_WRITEABLE。
危害情况:攻击者恶意写入文件内容,破坏App完整性。
修复建议:去除全局可写属性。
全局文件可读可写
风险详情:openFileOutput设置了全局可读写权限。
危害情况:攻击者既可读取也可写入,导致信息泄露和完整性被破坏。
修复建议:去除全局可读写属性。
2、私有文件泄露风险——getSharedPreferences
配置文件可读
风险详情:getSharedPreferences第二个参数设为MODE_WORLD_READABLE。
危害情况:文件可被其他应用读取,导致信息泄露。
修复建议:如果必须全局可读,需确保数据非隐私或已加密。
配置文件可写
风险详情:第二个参数设为MODE_WORLD_WRITEABLE。
危害情况:文件可被其他应用写入,内容被篡改,影响正常运行。
修复建议:第二个参数改为MODE_PRIVATE。
配置文件可读可写
风险详情:第二个参数设为MODE_WORLD_READABLE或MODE_WORLD_WRITEABLE。
危害情况:可读可写,既泄露信息又可能被篡改。
修复建议:使用MODE_PRIVATE,禁止使用MODE_WORLD_READABLE | MODE_WORLD_WRITEABLE。
3、数据加密
明文数字证书漏洞
APK的数字证书用于校验服务器身份和传输加密。若明文存储被篡改,客户端可能连接到假冒服务器;若证书被盗,传输数据可能被截获解密。
修复建议:证书应加密存储或做安全处理。
AES弱加密
风险详情:使用AES/ECB/NoPadding或AES/ECB/PKCS5padding模式。
危害情况:ECB分块加密,破解难度降低。
修复建议:禁止使用ECB模式,显式指定CBC或CFB模式,可带PKCS5Padding。密钥长度至少128位,推荐256位。
随机数不安全使用
风险详情:调用SecureRandom类的setSeed方法。
危害情况:生成的随机数具有确定性,可能被破解。
修复建议:使用/dev/urandom或/dev/random初始化伪随机数生成器。
AES/DES硬编码密钥
风险详情:密钥硬编码在程序中。
危害情况:反编译后直接获取密钥,轻易解密通信数据。
修复建议:密钥应加密存储或变形后使用,不要硬编码。
数据传输:这部分与WebView相关的内容有重叠,可归入此类。
第四大类:文件目录遍历类漏洞
1、Provider文件目录遍历
风险详情:Provider被导出且覆写了openFile方法,但未对Content Query Uri做有效过滤。
危害情况:攻击者利用openFile()进行目录遍历,访问任意可读文件。
修复建议:一般无需覆写openFile,若确有必要,需对提交的参数做../目录跳转符校验。
2、unzip解压缩漏洞
风险详情:解压zip文件时,使用getName()获取文件名后未做校验。
危害情况:攻击者构造恶意zip,解压时目录跳转,覆盖其他文件,导致任意代码执行。
修复建议:解压时判断文件名是否包含../。
第五大类:文件格式解析类漏洞
1、FFmpeg文件读取
风险详情:使用低版本FFmpeg库进行视频解码。
危害情况:某些版本存在本地文件读取漏洞,通过构造恶意文件可获取本地文件内容。
修复建议:升级FFmpeg库到最新版。
2、安卓“Janus”漏洞
漏洞详情:向原始APK前部添加一个攻击的classes.dex文件(A),系统校验时计算A的hash并以“classes.dex”为key保存,然后计算原始classes.dex(B),再次以“classes.dex”为key保存,覆盖了A的hash,导致系统认为APK未被修改,实际执行时优先执行A,绕过签名机制。
危害情况:绕过signature scheme V1签名,直接篡改App,相当于绕过整个安全机制。
修复建议:禁止安装包含多个同名ZipEntry的APK文件。
第六大类:内存堆栈类漏洞
1、未使用编译器堆栈保护技术
风险详情:Stack Canaries技术会在函数调用时向栈帧压入随机数(canary),溢出时canary先被覆盖,函数返回前检查canary是否一致。若不使用,栈溢出发生时系统不会提供保护。
危害情况:没有栈保护,溢出攻击更容易得手。
修复建议:NDK编译so时,在Android.mk中添加:LOCAL_CFLAGS := -Wall -O2 -U_FORTIFY_SOURCE -fstack-protector-all
2、未使用地址空间随机化技术
风险详情:PIE(Position Independent Executables)使so加载时内存地址随机分配。
危害情况:不使用PIE,shellcode执行难度降低,攻击成功率增加。
修复建议:NDK编译so时加入LOCAL_CFLAGS := -fpie -pie。
3、libupnp栈溢出漏洞
风险详情:使用低于1.6.18版本的libupnp库。
危害情况:构造恶意数据包可造成缓冲区溢出,导致代码执行。
修复建议:升级libupnp到1.6.18以上。
第七大类:动态类漏洞
1、DEX文件动态加载
风险详情:使用DexClassLoader加载外部apk、jar或dex,若来源不可控或被篡改,加载的文件可能不安全。
危害情况:加载恶意dex文件会导致任意命令执行。
修复建议:加载前必须校验签名或MD5,确认文件安全。
2、动态注册广播
风险详情:使用registerReceiver动态注册的广播在组件生命周期内默认是导出的。
危害情况:导出的广播可导致拒绝服务、数据泄露或越权。
修复建议:使用带权限检验的registerReceiver API进行注册。
第八大类:校验或限定不严导致的风险或漏洞
1、Fragment注入
风险详情:通过导出的PreferenceActivity子类,未正确处理Intent的extra值。
危害情况:攻击者可绕过限制访问未授权界面。
修复建议:targetSdk大于等于19时,强制实现isValidFragment方法;小于19时,也要在子类中加入该方法,并在方法内对fragment名进行合法性校验。
2、隐式意图调用
风险详情:封装Intent时仅使用隐式设置(只设action,不限定接收对象),导致Intent可被其他应用获取并读取数据。
危害情况:隐式调用发送的意图可被第三方劫持,导致隐私数据泄露。
修复建议:将隐式调用改为显式调用。
第九大类:命令行调用类相关的风险或漏洞
1、动态链接库中包含执行命令函数
风险详情:native程序中有时需要执行系统命令,接收外部参数执行时未进行过滤或检验。
危害情况:攻击者传入任意命令,导致恶意命令执行。
修复建议:对传入参数做严格过滤。
