Android 作为一个普及度、成熟度极高的平台,每天都有大量新 APP 涌现。开发一款 Android 应用,除了要有新颖的创意和高效的性能,保证安全性也是不容忽视的问题。俗话说打铁还需自身硬。接下来,我们会陆续与大家分享一些常见、不常见的代码风险问题,希望对您的 Android 开发工作有一定的启发和助益。

01

调试日志函数调用风险
调试日志函数可能输出重要的日志文件,其中包含的信息可能导致客户端用户信息泄露,暴露客户端代码逻辑等,为发起攻击提供便利。例如:Activity 的组件名,是 Activity 劫持需要的信息;通信交互的日志,会成为发动服务器攻击的依据;跟踪的变量值,可能泄露一些敏感数据,输入的账号、密码等。

这是一个极其常见的问题,虽然正常情况下我们的日志输出应该通过工具统一接管,正式发版时通过编译参数自动关闭日志输出。但是在日常调试的过程中,难免有时会随意输出。关闭调试日志函数调用,或者确保日志的输出使用了正确的级别,涉及敏感数据的日志信息在发布版本中被关闭,这些基本的检查还是不能省去的。

02

密钥硬编码漏洞
密钥硬编码是指在代码中直接将加密算法的密钥设置为一个固定值。通常加密算法本身都是公开的,而加密内容的保密则主要是依赖于加密密钥。如果密钥泄露,根据加密算法和加密后的密文,很容易得到加密前的明文。而密钥硬编码在代码中,通过反编译攻击者可以直接查看密钥内容,整个加密算法将形同虚设。密钥硬编码,可直接造成加密数据被破解,客户端与服务器之间的通信内容被破解,导致应用内的加密文件被破解,或是用户的敏感信息泄露。

若条件允许,最好使用专业的加固方案或者密钥白盒来保护加密算法源代码,防止被逆向获取到;或者参考下面的代码,动态生成密钥:

public String DemoEncrypt(String paramString){
      Key keySpec = new SecretKeySpec(paramString.getBytes(), "AES");
  Cipher cipher = Cipher.getIntance("AES/CBC/PKCS5Padding"); 
      cipher.init(Cipher.ENCRYPT_MODE,keySpec); 
  }

03

Fragment 注入攻击漏洞
Activity 可包含多个 Fragment 来展示界面,PreferenceActivity 是支持 Fragment 的基类 activity,其根据传入的参数 EXTRA_SHOW_FRAGMENT,(‘:android:show_fragment’) 动态创建 fragment 实现界面展示。
当 PreferenceActivity 的 activity 是属性为 export,PreferenceActivity 不检查传入的参数直接根据其构建对象时,可以构造 intent 中的 extra 数据,调用应用内部的任意 fragment。fragment 注入攻击可导致应用的敏感信息泄露、远程代码执行或者应用崩溃。
当 targetSdk 大于等于 19 时,强制实现了 isValidFragment 方法;小于 19 时,在 PreferenceActivity 的子类中都要加入 isValidFragment,两种情况下在 isValidFragment 方法中进行 fragment 名的合法性校验。

04

Intent Scheme URL 攻击漏洞
利用 intent scheme URLs(意图协议 URL),可以通过 web 页面发送 intent 来启动 App 应用。攻击者可构造特殊格式的 URL 直接向系统发送意图,启动 App 应用的 Activity 组件或者发送异常数据,导致应用的敏感信息泄露或者应用崩溃。
避免这个漏洞,我们需要为需要启用浏览器调用功能的 activity 组件配置 category filter, 使用 " android. intent. category. BROWSABLE "限制调用的发起者。以下代码供参考:

Intent intent = Intent.parseUri(uri);  
intent.addCategory("android.intent.category.BROWSABLE");  
intent.setComponent(null);  
intent.setSelector(null);  
context.startActivityIfNeeded(intent, -1); 

05

Webview File 同源策略绕过漏洞
JavaScript 的延时执行能够绕过 file 协议的同源检查,并能够访问受害应用的所有私有文件,即通过 WebView 对 Javascript 的延时执行和将当前 Html 文件删除掉并软连接指向其他文件就可以读取到被符号链接所指的文件,然后通过 JavaScript 再次读取 Html 文件,即可获取到被符号链接所指的文件。大多数使用 WebView 的应用都会受到该漏洞的影响。恶意应用通过该漏洞,可在无特殊权限下盗取应用的任意私有文件。尤其是浏览器,可利用该漏洞,获取到浏览器所保存的密码、Cookie、收藏夹以及历史记录等敏感信息,从而造成敏感信息泄露。

所以我们需要自查代码,重点在以下几个方面:

1、将不必要导出的组件设置为不导出,并显式设置所注册组件的 “android:exported” 属性为 false;

2、如果需要导出组件,禁止使用 File 域 WebView. getSettings. set Allow File Access (false);
3、如果需要使用 File 协议,禁止 File 协议调用 JavaScript:WebView. getSettings. setJava Script Enabled (false)

06

Webview 远程代码执行漏洞
Webview 是 Android 用于浏览网页的组件。其包含的接口函数 addJavascriptInterface 可以将 Java 类或方法导出以供 JavaScript 调用,实现网页 JS 与本地 JAVA 的交互。由于系统没有限制已注册 JAVA 类的方法调用,因此未注册的其它任何 JAVA 类也可以被反射机制调用,这样可能导致被篡改的 URL 中存在的恶意代码被执行,用户手机被安装木马程序,发送扣费短信,通信录或者短信被窃取,甚至手机被远程控制。
避免入坑需要从以下几个方面考虑:
1、Android 系统在 4.2 以上(包含 4.2):Android 在 4.2 版本之后,要求允许被调用的函数需要使用@JavascriptInterface对被调用函数进行进行注解;
2、Android 系统在 4.2 以下:建议不要使用 addJavascriptInterface 方法,一定要使用该接口的情况下,可使用下面方式降低风险:
a)使用 HTTPS 加载页面时,利用证书校验机制防止访问的页面被替换或者被挂马。
b)使用 HTTP 加载页面时,应该对页面进行完整性校验等方式,确认页面未被更改或替换。
c)加载本地页面时,在程序中也应对页面进行完整性校验。
3、移除 webkit 中默认内置接口,除了 addJavascriptInterface 接口,还有 webkit 默认的内置接口会导致同样的问题。故开发者在使用 webview 时,需要移除以下三个默认接口:

removeJavascriptInterface("searchBoxJavaBridge_")
removeJavascriptInterface("accessibilityTraversal")
removeJavascriptInterface("accessibility")

07

InnerHTML 的 XSS 攻击漏洞
H5 在 Android 的开发中也是非常常见的技术方案。DOM 型 XSS 漏洞是基于文档对象模型(Document Object Model)的一种漏洞。它的攻击代码不需要服务器解析响应,而是通过浏览器端的 DOM 解析触发 XSS。客户端上的 JavaScript 脚本可以访问浏览器的 DOM,并修改页面的内容,不依赖服务器的数据,直接从浏览器端获取数据并执行。在 JavaScript 中给 DOM 的 innerHTML 属性赋值一个 script 标签,是一个非常普遍的 xss 注入点。如果攻击者利用该漏洞进行攻击,可能会导致账号或 Cookie 信息被窃取,从而冒充管理者登录后台进行数据篡改等恶意操作。
防止此类漏洞有两条原则:过滤输入和转义输出。
输入:过滤双引号,单引号,分号。
输出:对上述字符进行 HTML 实体编码即可。

本文分享了一些经典的代码风险问题。有些问题官方升级已经修正,但仍有探讨的价值。在开发的漫漫长河中,不断地发现和解决问题是永恒的话题,我们的警惕心理不能懈怠。今后,我们会持续地针对这一话题与大家进行分享,敬请期待!

* 版权声明:本文作者 优测团队 Android 测试专家 李忠丞。


↙↙↙阅读原文可查看相关链接,并与作者交流