android app代码审计,常规漏洞/缺陷整理(持续更新)

app源代码安全缺陷分析报告

  • 前言
  • 高等级缺陷
    • 代码注入--WebView远程代码执行
    • 代码质量--不安全的SSL:主机名验证功能被禁用
    • 资源管理--通过共享存储安装APK
    • 跨站脚本--反射型XSS
  • 中等级缺陷
    • 代码注入--资源注入
    • 代码质量--Activity劫持
    • 代码质量--Android程序:缺少网络安全配置
    • 代码质量--不安全的SSL:自定义SSL接口
    • 代码质量--不安全的信息传输
    • 代码质量--不必要的权限申请
    • 代码质量--危险的Intent权限
    • 代码质量--双重检查锁定
    • 代码质量--硬编码IP
    • 代码质量--系统信息泄露:外部
    • 代码质量--非静态内部类导致内存泄漏
    • 密码管理--不安全的随机数
    • 密码管理--弱加密:密钥长度不足
    • 密码管理--硬编码加密密钥
    • 资源管理--格式化缺陷
    • 资源管理--资源未释放:流
    • 输入验证--拒绝服务
  • 低等级缺陷
    • API误用--仅重写了equals()和hashCode()中的一个
    • API误用--使用不必要的线程安全类
    • API误用--忽略返回值
    • 代码质量--APP允许备份
    • 代码质量--Webview允许DOM存储
    • 代码质量--Webview允许内容访问
    • 代码质量--Webview允许文件访问

前言

鉴于目前国内app安全方面抓的越来越紧,不仅apk会拿去做安全检测,apk的源码也是拿去做相关的安全检测。这无疑中给我们开发增加了不少工作量,以下就列举了一些博主开发时被检测出来的代码漏洞。

高等级缺陷

代码注入–WebView远程代码执行

详细信息:

Android API level 16以及之前的版本存在远程代码执行安全漏洞,该漏洞源于程序使用
WebView.addJavascriptInterface可以实现网页JS与本地JAVA的交互,但是没有限制已注册
JAVA类的方法调用,类中的任何public函数都可以在JS代码中访问,这就导致可以调用
getClass通过java反射机制来执行任意Java对象的方法。
例如:利用addJavascriptInterface方法注册可供JavaScript调用的Java对象
injectedObj,利用反射机制调用Android API getRuntime执行shell命令:
java代码:

...
WebView webView1 = (WebView)findViewById(R.id.webView1); 
JavaScriptInterface myJavaScriptInterface = new JavaScriptInterface(); 
webView1.addJavascriptInterface(myJavaScriptInterface,"injectedObj"); 
webView1.loadUrl("http://www.example.com");
...

js代码:

<html> 
 <body> 
 <script> 
 function execute(cmdArgs) { 
 return
injectedObj.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,n
ull).exec(cmdArgs); 
 } 
 var res = execute(["/system/bin/sh", "-c", "ls -al /mnt/sdcard/"]); 
 document.write(getContents(res.getInputStream())); 
 script> 
 body> 
html>

修复建议:

1.避免调用addJavascriptInterface()方法(如果只是展示页面数据,而不做数据通信,完全可以不使用),或者将API等级设为17或者更高级别,对于这
些API等级,只有被标注了JavascriptInterface的公共方法才可以从JavaScript访问。
2.webview组件会默认内置一个searchBoxJavaBridge_接口,故需要使用
removeJavascriptInterface移除searchBoxJavaBridge_
3.调用了Android/webkit/AccessibilityInjector组件的应用在开启辅助功能选项中第三方服务
的安卓系统会默认添加accessibilityaccessibilityTraversal接口,同样需要使用
removeJavascriptInterface进行移除。

代码质量–不安全的SSL:主机名验证功能被禁用

详细信息:

采用SSL进行连接时,使用AllowAllHostnameVerifier()
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER将会关闭主机名验证功能。这相
当于信任所有证书。
例如:下列代码SSLSocketFactory调用setHostnameVerifier方法,将
SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER作为参数,将会关闭主机名验证
功能。

... 
KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType()); 
store.load(null, null); 
SSLSocketFactory sf = new SSLSocketFactory(store); 
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
HttpParams params = new BasicHttpParams(); 
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); 
SchemeRegistry registry = new SchemeRegistry(); 
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 
registry.register(new Scheme("https", sf, 443)); 
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); 
...

修复建议:
采用SSL连接时,不应放弃服务器验证检查。可考虑采用StrictHostnameVerifer建立服务
器身份和安全SSL连接。

资源管理–通过共享存储安装APK

详细信息:

应用程序如果通过共享存储安装应用程序,如果攻击者使用恶意应用程序将下载的
APK文件替换为恶意APK文件,安装进程会使用该恶意APK文件取代合法APK。
例如:在以下代码片段中,通过共享存储安装应用程序。

Intent myIntent = new Intent(Intent.ACTION_VIEW); 
Uri apkUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" +
"install.apk")), "application/vnd.android.package-archive"); 
myIntent.setDataAndType(apkUri); 
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
myContext.startActivity(intent);

修复建议:
检查代码逻辑,不要共享存储安装应用程序,防止被替换为恶意文件。
以上检测的是android7.0以下的写法,在android7.0以上使用的是FileProvider.getUriForFile来获取Uri(这是安全的),这算是以前老系统的一个漏洞了。而为了适配7.0以下的系统,必须得使用Uri.fromFile,可以在代码检测时先把这句话注释掉。因为代码检测并不智能,所以只能暂时这么做

        if (Build.VERSION.SDK_INT >= 24) {
            File file = new File(pathstr);
            //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致   参数3  共享的文件
            Uri apkUri = FileProvider.getUriForFile(mContext, "com.dlwq.android.file.provider", file);
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
//            intent.setDataAndType(Uri.fromFile(new File(mContext.getExternalCacheDir(), name)), "application/vnd.android.package-archive");
        }

跨站脚本–反射型XSS

详细信息:

反射型XSS是指应用程序通过Web请求获取不可信赖的数据,并在未检验数据是否存在
恶意代码的情况下,将其发送给用户。反射型XSS一般可以由攻击者构造带有恶意代码参
数的URL来实现,在构造的URL地址被打开后,其中包含的恶意代码参数被浏览器解析
和执行。这种攻击的特点是非持久化,必须用户点击包含恶意代码参数的链接时才会触
发。
例如:下面JSP代码片段的功能是从HTTP请求中读取输入的用户名(username)并显示
到页面。

<%
String name= request.getParameter("username"); %> 
...
姓名: <%= name%> 
...

如果name里有包含恶意代码,那么Web浏览器就会像显示HTTP响应那样执行该代码,应
用程序将受到反射型XSS攻击。

修复建议:
为了避免反射型XSS攻击,建议采用以下方式进行防御:
1.对用户的输入进行合理验证(如年龄只能是数字),对特殊字符(如<、>、'、"以及

你可能感兴趣的:(android,android)