专栏首页QA一隅App安全测试—Android安全测试规范

App安全测试—Android安全测试规范

安装包测试

安装包反编译测试

用例风险:源代码未做混淆使攻击者很轻易反编译出源代码导致代码泄漏风险。

执行步骤:使用反编译工具打开应用,如发现代码内未经过混淆,就说明存在应用可进行反编译,记录漏洞,停止测试。

预期结果:安装包中核心模块与敏感数据经过加密或者混淆

整改建议:建议使用Proguard等工具对源码进行进一步混淆,避免造成源码泄漏。

安装包签名测试

用例风险: Android签名机制是一种有效的身份标识,为了保证应用不被恶意修改后重新发布,需要检查应用签名是否有保护机制。

执行步骤

  1. 解压缩安装包.apk文件后,删除META-INF/目录下的xx.RSAxxx.SF文件
  2. 使用自己的私钥对删除过后的apk文件进行重新签名,首先生成自己的私钥
`keytool -genkey -v -keystore [keystore路径] -alias [密钥别名] -keyalg RSA -keysize 2048 -validity [有效天数]`
  1. 然后对apk进行二次签名,签名命令格式如下
jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore [keystore名称] [apk文件] [密钥别名] 


  • -sigalg:签名算法名称
  • -digestalg:信息摘要算法
  • -keystore:签名文件

执行签名命令

jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore android.keystore kaoyan.apk  android.keystore


  1. 安装重新签名后的apk文件,查看应用是否具有保护机制阻止程序运行。

预期结果: 更换签名后,触发应用防御机制,应用无法启动或提示

整改建议: 内部代码实现apk二次打包鉴别机制,在程序运行时校验apk签名是否由官方私钥签名而来。

应用权限测试

用例风险:应用权限分配不合理,可能导致用户隐私数据泄露。

执行步骤

  1. 使用反编译工具反编译
  2. 打开源码后,检查应用AndoridManifest.xml文件,将应用权限和业务功能需要权限做对比,检查申请应用权限是否大于业务需要权限,有即存在安全隐患。

预期结果:应用申请合理的系统权限

整改建议:为应用分配合理的系统权限

AllowBackup开启

用例风险:当allowBackup标志值为true时,即可通过adb backupadb restore来备份和恢复应用程序数据,导致应用数据泄露。

执行步骤

  1. 打开AndroidManifest.xml文件;
  2. 检查应用AndoridManifest.xml文件中的配置是否为:android:allowBackup="true",即为allowBackup开启,记录漏洞,停止测试。

预期结果:AllowBackup关闭

整改建议:在AndroidManifest.xml文件设置allowBackup属性值为False

备注:allowBackup属性未配置时默认为true

debuggable开启

用例风险:当debuggable标志值为true时,即表示是App可调试的,存在安全泄露风险。

执行步骤

  1. 打开解析的AndroidManifest.xml文件;
  2. 检查应用AndoridManifest.xml文件中的配置是否为:android: debuggable="true",即为debuggable开启。

预期结果 debuggable关闭

整改建议 在AndroidManifest.xml文件设置debuggable属性值,其默认值为false

备注 Debuggable属性未配置时默认为false

弱加密算法审查

用例风险

使用弱加密算法会大大增加黑客攻击的概率,黑客可能会破解隐私数据、猜解密钥、中间人攻击等,造成隐私信息的泄漏,甚至造成财产损失。容易被破解的加密算法被称为弱加密算法,例如可以使用穷举法在有限的时间内破解DES算法。

执行步骤

  1. 使用反编译工具进行反编译
  2. 打开源码后,查找代码中的敏感数据和敏感函数加密代码,是否使用DES弱加密算法,弱加密代码样例:
SecretKeySpec key = new SecretKeySpec(rawKeyData, "DES"); //指定加密方式
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); //设置加密填充模式
cipher.init(Cipher.DECRYPT_MODE, key);
  1. RSA中加密不使用PaddingRSA加密常用的填充模式有三种:
  • RSA_PKCS1_PADDING
  • RSA_PKCS1_OAEP_PADDING
  • RSA_NO_PADDING

使用RSA公钥时通常会绑定一个Padding,原因是为了防止对RSA算法的攻击。风险代码样例如下:扩展资料:RSA填充模式

Cipher rsa = null;
try {
  rsa = javax.crypto.Cipher.getInstance("RSA/NONE/NoPadding");
}
catch (java.security.NoSuchAlgorithmException e) {
}
catch (javax.crypto.NoSuchPaddingException e) {
}
SecretKeySpec key = new SecretKeySpec(rawKeyData, "RSA"); 
Cipher cipher = Cipher.getInstance("RSA/NONE/NoPadding"); //选择了NoPadding加密模式
cipher.init(Cipher.DECRYPT_MODE, key);
  1. 使用了不安全的密钥长度,如下演示代码所示密码长度为512bits

常用的密钥长度有1024bits2048bits等,使用RSA加密时,建议密钥长度大于1024bit

public static KeyPair getRSAKey() throws NoSuchAlgorithmException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(512);    //密码长度设置为512bits
        KeyPair key = keyGen.generateKeyPair();
        return key;
      }
  1. 使用了不安全的加密模式,如下示例代码中AES加密使用了ECB模式

ECB模式是最简单的模式,在其中明文和密文是一一对应的,相同的明文会被加密为相同的密文,这样可以通过观察密文得到明文中重复的组合,并以此为线索来破解密码。

SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, key);

预期结果:系统未使用包含风险的加密算法

整改建议

  • 使用对称加密算法时避免使用DES算法
  • 使用RSA算法加密时不使用NoPadding
  • 在选择加密模式时避免使用ECB模式
  • 使用RSA加密时,建议密钥长度大于1024bit

数据传输测试

敏感信息明文传输

用例风险:如果在传输过程中未对敏感数据进行加密传输,存在被恶意攻击者通过网络窃听等手段获取网络数据包中的敏感数据的威胁。

执行步骤

  1. 安装应用后,触发应用功能。
  2. 同时开启抓取数据包工具(如Charles),查看数据包中是否明文包含:用户名密码、IP地址、SIM序列号,或其他用户、系统等敏感信息。
  3. 如发现代码内包含以上信息,就说明存在应用中存在敏感数据,记录漏洞,停止测试。

预期结果:传输的数据包中未包含敏感信息

整改建议:确保包含重要敏感信息的数据均已加密的形式或者以https形式传输。

Java层ssl中间人攻击漏洞

用例风险

在密码学和计算机安全领域中,中间人攻击(Man-in-the-middle attack,缩写:MITM)是指攻击者与通讯的两端分别建立独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。在中间人攻击中,攻击者可以拦截通讯双方的通话并插入新的内容。

执行步骤

  1. 使用反编译工具打开应用,反编译出应用源码。
  2. 在源码中搜索类似写法:
 public class SSLSocketFactory_poc extends SSLSocketFactory {
            SSLContext sslContext = SSLContext.getInstance("TLS");            
            public SSLSocketFactory_poc(KeyManager[] keys,KeyStore truststore ) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
                super(truststore);

                TrustManager tm = new X509TrustManager() {
                    public void checkClientTrusted(X509Certificate[] chain, String authType)  {
                        if(true)
                        {}
                        try {
                            throw new CertificateException("illegal DN, reject the connection");
                        } catch (CertificateException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                    }

                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }

                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                };

                sslContext.init(keys, new TrustManager[] { tm }, null);
            }
            ...
        }s(), "js2java");
  1. 检测代码中是否实现域名判断逻辑,未实现域名判断逻辑的代码如下:
HostnameVerifier hostnameVerifier = new HostnameVerifier(){
        public boolean verify(String hostname, SSLSession session)
            {
                return true; #未实现任何判断语句,直接返回true
            };
        };
  1. 检测代码中是否允许所有域名,允许所有域名的代码如下:
SSLSocketFactory sf = new SSLSocketFactory_poc(null,trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  #允许所有域名
sf.setHostnameVerifier(new AllowAllHostnameVerifier());
  1. 如果在使用证书的时候,像示例代码中的写法类似,未进行域名相关判断、允许所有域名的证书,则风险存在。

预期结果:在使用证书的时候进行相关校验

整改建议:建议开发者对SSL证书进行强校验,包括证书是否合法、主机域名是否合法和证书的有效期。

数据存储测试

日志中包含敏感信息

安全风险

如果日志中包含用户信息、业务信息,攻击者可以通过抓取日志,搜集整理大量的有用信息。比如有时研发开发时为了调试方便会添加一些debug日志,如果在打正式发布包时不将这些log去掉那么很容易泄漏敏感信息。

执行步骤

  1. 安装应用后,对应用进行使用。
  2. 同时使用adb logcat | find "com.youku.phone"(包名)"捕获输出的日志
  3. 还可以使用命令adb logcat | find "com.youku.phone" >C:\Users\Shuqing\Desktop\log.txt将日志保存到指定文件。
  4. 如果输出的日志中包含敏感信息,记录漏洞,停止测试。

预期结果:日志中不包含敏感信息

整改建议:为了防止信息泄漏,不要在日志中输出敏感数据

敏感数据明文存储

安全风险:敏感数据明文存储在手机上增加了信息泄露的风险

执行步骤

  1. 使用软件(如:好压)打开apk安装文件查找是否明文存储用户信息、业务数据、服务信息或其他敏感信息。
  2. 如果存在,记录漏洞,停止测试。

预期结果:文件中未存放用户或系统敏感信息

整改建议:如果一定要在客户端存放系统敏感数据,建议加密后再存储。

安装文件权限检测

安全风险:应用文件被分配了不合理的权限,导致其他应用可以读取和获取文件内容,增加了内容泄露的风险。

执行步骤

  1. 使用adb shell连接设备
  2. 进入应用目录cd /data/data/xxxx(包名)
  3. 执行命令ls -al,查看当前目录下所有文件权限。
  4. r代表只读,w代表写,x代表可执行,d表示是一个目录。
  5. 文件权限为:文件主-组用户-其他用户

预期结果:

  • 目录权限为drwxrwx--x,允许多一个执行位x
  • 文件权限最后三位应为空(类似-rw-rw----),即除应用自己以外任何人无法读写;

整改建议

  • 避免使用MODE_WORLD_WRITEABLE(可写)和MODE_WORLD_READABLE(可读)模式创建进程间通信的文件,如果需要与其他进程应用进行数据共享,请考虑使用content provider
  • 避免使用MODE_PRIVATE模式创建内部存储文件,默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容。
  • 避免将密码等敏感数据信息明文存储在文件中;为文件使用合适的权限。

数据库敏感数据泄露

安全风险:敏感数据直接存储在sqlite数据库导致信息泄露的风险。

执行步骤

  1. 使用进入应用安装文件目录/data/data/[package name]/databases/,查找sqlite数据库文件并复制到PC端
  2. 使用DB.Browser.for.SQLite打开sqlite文件。
  3. 查看或检索文件中是否存在用户信息、业务数据、服务系统信息或其他敏感信息。如果存在,记录漏洞,停止测试。

预期结果:客户端数据库文件中不存在敏感数据。

整改建议:如果一定要在客户端存放系统或系统敏感数据,建议加密后再存储。

本地数据库注入/文件遍历检测

安全风险:获取或者篡改app中存储的敏感信息,如手机号、账号、密码等,在业务运行操作时无法保证数据安全。

执行步骤

  • 启动drozer连接测试设备
  • 获取开放的provider:run app.provider.info -a appname
  • 查找可用的URI:run scanner.provider.finduris -a appname
  • 执行SQL注入检测run scanner.provider.injection -a appname
  • 执行文件遍历检测 run scanner.provider.traversal -a appname

预期结果 无法获取到相关数据信息。

整改建议 使用参数化查询防御SQL注入,限制Provider组件的权限,取消不必要的Provider组件接口。

WebView组件安全测试

WebViewAndroid系统提供能显示Web页面的系统控件,例如混合类型的AppH5界面就是使用了WebView组件。

WebView远程代码执行漏洞

安全风险:Webview中接口addJavascriptInterface可通过webview对象向页面javascript导出java本地接口,可能导致任意命令执行。

执行步骤

  1. 使用反编译工具打开应用,反编译出应用源码。
  2. 在源码中搜索类似写法:
settings.setJavaScriptEnabled(true); //设置开启javascript
settings.setJavaScriptCanOpenWindowsAutomatically(true); //设置允许js弹出alert对话框
mWebView.addJavascriptInterface(new JSInvokeClass(), "js2java"); //注入javascript映射
  1. 如果源码存在上面代码,那么该处就可能存在Web组件远程代码执行的风险。
  2. 如果存在该风险,将会在该页面中显示出存在问题的接口。

预期结果:系统使用安全接口调用webview

整改建议

  • 建议禁用危险接口addJavascriptInterface导出Java类及方法,并加强访问的url的域控制;
  • 严格控制导出方法的权限,避免越权操作;

WebView密码明文保存漏洞

安全风险

  • 在使用WebView的过程中开启了setSavePassword保存密码,当用户在WebView中输入的用户名和密码,则会被明文保存到应用。
  • 用户数据保存到目录的databases/webview.db中。
  • 如果手机被root就可以获取明文保存的密码,造成用户的个人敏感数据泄露。

执行步骤

  1. 使用反编译工具打开应用,反编译出应用源码。
  2. 在源码中搜索类似写法:
mWebView.getSettings().setSavePassword(true); //设置开启保存密码
mWebView.loadUrl("http://www.example.com");
  1. 则说明风险存在,记录漏洞,停止测试。

预期结果:在调用setSavePassword时设定setSavePassword(false)

整改建议:使用WebView.getSettings().setSavePassword(false)来禁止保存密码

WebView组件忽略SSL证书验证错误漏洞

安全风险

Android WebView组件加载网页发生证书认证错误时,会调用WebViewClient类的onReceivedSslError方法,如果该方法实现调用了handler.proceed()来忽略该证书错误,则会受到中间人攻击的威胁,可能导致隐私泄露。

执行步骤

  1. 使用反编译工具打开应用,反编译出应用源码。
  2. 在源码中搜索类似写法:
mWebView.getSettings().setJavaScriptEnabled(true);
        mWebView.addJavascriptInterface(new JsBridge(mContext), JS_OBJECT);
        mWebView.loadUrl("http://www.example.org/tests/addjsif/");
        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed(); //忽略证书错误
            }
        });
  1. 如上所示代码在onReceivedSslError处理时没有进行cancel,还是使用了proceed(),忽略掉了发生的SSL异常。则说明风险存在。记录漏洞,停止测试。

预期结果:正确的处理SSL错误,避免证书错误的风险。

整改建议:当发生证书认证错误时,采用默认的处理方法handler.cancel(),停止加载问题页面。

Broadcast组件安全测试

空广播造成Broadcast组件拒绝服务

安全风险:攻击者可以发送恶意的消息,控制Receiver执行恶意动作或者造成信息泄露。

执行步骤

  1. 使用工具Drozer扫描暴露的broadcast组件run app.broadcast.info -a xxxx -i和相关action信息
  2. 尝试向应用程序的receiver组件发送空值,run app.broadcast.send --action xxx,查看是否能够造成应用程序崩溃,形成拒绝服务。

预期结果 系统为Broadcast组件分配了适当权限。

整改建议 AndroidManifest.xml文件的各receiver标签中,设置android:exported="false"BroadcastReceiver代码中增加消息异常处理机制。

未指定接收组件造成信息泄露

安全风险

应用程序在广播包含敏感信息的消息时,由于未指定具体的接收组件,攻击者可能仿冒receiver来接受来自应用程序的消息,从而窃取敏感信息。

执行步骤

  1. 反编译apk获取源代码,在源代码中搜索定位发送广播消息的位置,例如搜索sendBroadcast()
  2. 查看在新建Intent时,是否显式指定了接收该广播的组件名称,以及要发送的广播中是否包含敏感信息。示例代码如下:
public class ServerService extends Service {
  // ...
  private void d() {
    // ...
    Intent v1 = new Intent();//未显式指定接收组建名称
    v1.setAction("com.sample.action.server_running");
    v1.putExtra("local_ip", v0.h);
    v1.putExtra("port", v0.i);
    v1.putExtra("code", v0.g);
    v1.putExtra("connected", v0.s);
    v1.putExtra("pwd_predefined", v0.r);
    if (!TextUtils.isEmpty(v0.t)) {
      v1.putExtra("connected_usr", v0.t);
    }
  }
  this.sendBroadcast(v1);
}

3、 如果应用程序未指定接收组件并且广播中包含类似password等信息,则存在信息泄露的风险。

预期结果 :显式的制定接收组建、并且分配了合适的权限

整改建议

  1. 通常采用的安全方式有设置指定action与包名
intent.setAction("allow.package.recv.action"); //设置指定的action
intent.setPackage("allow.package.recv.packagename"); //设置指定的包名
sendBroadcast(intent); //发送广播

如果指定特殊的receiver接收可以指定component

intent.setComponent(newComponentName("allow.package.recv.packagename", "allow.package.recv.classname"));
sendBroadcast(intent);
  1. 广播如果是APP内部使用,使用LocalBroadcastManager,使广播的Intent仅在该进程内部,而不会让同一APP的其他进程或者其他APP接收到。
  2. 避免使用如下API:
  • sendStickyBroadcast
  • sendStickyBroadcastAsUser
  • sendStickyOrderedBroadcast
  • sendStickyOrderedBroadcastAsUser

Android SDK文档中也明确说明了存在安全问题, 如果必须使用,广播中不应包含敏感信息,另外需要设置接收权限:

//设置广播权限
sendBroadcast(intent,"broadcast.permission");
//向特定用户发送广播
this.sendBroadcastAsUser(i, null,"broadcast.permission");
this.sendOrderedBroadcastAsUser(i, null, "broadcast.permission", null, null, 0, null, null);
this.sendOrderedBroadcast(i, "broadcast.permission");
this.sendOrderedBroadcast(i, "broadcast.permission", null, null, 0, null, null);

同时在AndroidManifest.xml中如下配置:

<uses-permission android:name="broadcast.permission" /> 
<permission android:name="broadcast.permission" android:protectionLevel="signature" />

android:protectionLevelsignature,防止其他APP能够非常容易的窃取权限。

Broadcast组件越权漏洞

安全风险:攻击者可以发送恶意的消息,控制Receiver执行恶意动作或者造成信息泄露。

执行步骤

  1. 反编译后检索registerReceiver(),查找动态广播接收器。也可以使用命令:
run app.broadcast.info -a com.xxxx -i
  1. 同时留意android:exported="true"权限的组件。
  2. 在源代码中搜索receiver,找到应用程序定义的在接收到消息时的各项参数以及各种处理逻辑。
  3. 查看业务逻辑寻找是否能够直接调用Broadcast组件,是否越权进行操作。

预期结果:合理分配Broadcast组件权限

整改建议:

  • AndroidManifest.xml文件的receiver标签中设android:exported="false"
  • 或者在AndroidManifest.xml中,申明一个私有权限,级别为signature
  • 私有广播接收器设置exported='false',并且不配置intent-filter,对接收来的广播进行验证;

Activity组件安全测试

绕过认证调用activity

安全风险:攻击者可以绕过认证阶段,直接调用后续activity组件。

执行步骤

  1. 反编译查看配置文件AndroidManifest.xmlactivity组件(关注配置了intent-filter的及未设置export=“false”的组件)。
  2. 可使用工具Drozer扫描暴露的Activity:run app.activity.info -a packagename
  3. 执行命令run app.activity.start --component 包名 Activity名
  4. 查看在未经登录的情况下,登录之后的Activity能否被正常显示,如果可以则会形成越权、信息泄露等风险。

预期结果 设定正确的activity权限,避免造成越权或信息泄露。

整改建议

  • app内使用的私有Activity不应配置intent-filter,如果配置了intent-filter需设置exported属性为false
  • 谨慎处理接收的intent以及其携带的信息,当Activity返回数据时候需注意目标Activity是否有泄露信息的风险;

隐式启动intent包含敏感数据

安全风险

APP创建Intent传递数据到其他Activity,如果创建Activity时通过addFlags设置了FLAG_ACTIVITY_NEW_TASKActivity会在另一个Task中打开,

这种情况很可能被其他的Activity劫持读取到Intent内容,跨TaskActivity通过Intent传递敏感信息是不安全的,会导致intent中的敏感数据泄露。

执行步骤

  1. 使用反编译工具打开应用,反编译出应用源码。
  2. 在源码中查找以下示例源码(主要是FLAG_ACTIVITY_NEW_TASK标签):
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //设置了FLAG_ACTIVITY_NEW_TASK
startActivity(intent);
Intent i = new Intent("com.xiaomi.mipush.RECEIVE_MESSAGE");
startActivity(i);
  1. 如果FLAG_ACTIVITY_NEW_TASK标签就存在该风险,记录漏洞,停止测试

预期结果:不包含FLAG_ACTIVITY_NEW_TASK标志的Intent启动Activity

整改建议:避免使用包含FLAG_ACTIVITY_NEW_TASK标志的Intent启动Activity

Content Provider组件测试

Provider组件导致信息泄露

安全风险: 攻击者可以利用开放的Provider Content获取系统敏感资源

执行步骤

  1. 查看AndroidManifest.xml文件,定位各Provider,尤其是设置了android:exported="true"的。
  2. 可使用工具Drozer扫描:run scanner.provider.finduris -a com.mwr.example.sieve
  3. 如果存在Accessible content URIs说明存在注入风险。

预期结果:系统为Content Provider组件分配合适的权限,不存在信息泄露。

整改建议

  • AndroidManifest.xml文件的各provider标签中,设置android:exported="false"
  • 设置minSdkVersion不低于9
  • 内部app通过content provider交换数据设置protectionLevel=“signature”验证签名,仅授予那些和本程序应用了相同密钥来签名的程序
  • 公开的content provider确保不存储敏感数据;

文件遍历漏洞

安全风险

APP的实现中定义了一个可以访问本地文件的Content Provider组件,默认的android:exported="true",该Provider实现了openFile()接口

通过此接口可以访问内部存储app_webview目录下的数据,由于后台未能对目标文件地址进行有效判断,可以通过"../"实现目录跨越,导致对任意私有数据的访问。

执行步骤

  1. 使用drozer命令扫描run scanner.provider.traversal -a com.mwr.example.sieve
  2. 扫描结果中存在Vulnerable Providers说明存在文件遍历风险。

预期结果:不存在文件遍历漏洞。

整改建议:系统对在调用文件参数时添加防御。

Service组件测试

Service组件越权漏洞

安全风险:攻击者可以发送恶意的消息,控制Service执行恶意动作或者造成信息泄露。

执行步骤

  1. 使用drozer命令 run app.service.info -a xxxx查看service组件暴露。
  2. 通过定位的service,找到应用程序定义的在接收到消息时的各项参数以及各种处理逻辑。
  3. 查看业务逻辑寻找是否能够直接调用Service组件,能否能进行越权操作。如果可以风险存在,停止测试,记录漏洞。

预期结果 系统为Service组件分配了适当权限

整改建议

  • AndroidManifest.xml文件的各receiver标签中,设置android:exported="false"
  • 或者在AndroidManifest.xml中,申明一个私有权限,级别为signature
  • 只被应用本身使用的service应设置为私有;
  • 尽量不发送敏感信息,在service接收到的数据需需谨慎处理,对调用的接口做校验;

空广播造成Service组件拒绝服务

安全风险:攻击者可以发送恶意的消息,控制Receiver执行恶意动作或者造成信息泄露。

执行步骤

  1. 查看AndroidManifest.xml文件,定位各Receiver,尤其是设置了android:exported="true"的。
  2. 尝试调用服务组件,run app.service.start --action 服务名 --component 包名 服务名,查看是否能够造成应用程序拒绝服务。

预期结果:系统为Service组件分配了适当权限

整改建议: AndroidManifest.xml文件的各组件标签中,设置android:exported="false";组件接收消息代码中增加消息异常处理机制。

备注:其他类型的拒绝服务攻击参考SEC_AN_ PLUS_11.1 intent应用本地拒绝服务漏洞。

intent应用本地拒绝服务漏洞

安全风险

Android系统中提供了Intent机制来协助应用间的交互与通讯,例如:应用A发出一个intent信息,系统根据intent的描述,负责找到可以解析该intent消息的应用B

B应用负责接收intent的组件,在解析intent数据时,会通过IntentgetXXXExtra()函数,如果解析为空数据、异常、或是畸形数据,就可能会导致程序崩溃。

执行步骤

  1. 攻击者向Intent传入自定义的序列化对象,被攻击者在组件里解析该序列化数据,可能出现出现找不到类出现ClassNotFoundException异常而崩溃。攻击代码如下:
Intent intent = new Intent();
intent.setAction("serializable_action");
intent.setClassName("com.my.test", "com.my.test.MainActivity");  // 指定攻击目标的包名和Activity入口
intent.putExtra("serializable_obj",XXX);    //此处是传入畸形数据
startActivity(intent);
  1. 数组越界IndexOutOfBoundsException异常导致的拒绝服务,如果程序没有对getIntegerArrayListExtra()等获取到的数据数组元素大小的判断,从而导致数组访问越界而导致应用崩溃;攻击应用代码片段:
Intent intent = new Intent();
intent.setClassName("com.alibaba.jaq.pocforrefuseservice", "com.alibaba.jaq.pocforrefuseservice.MainActivity");
ArrayList<Integer> user_id = new ArrayList<Integer>(); //定义数组
intent.putExtra("user_id", user_id);
startActivity(intent);
)

预期结果:在使用Intent获取数据时对异常做了充分的处理。

整改建议

建议处理通过Intent.getXXXExtra()获取的数据时进行以下判断,以及用try catch方式进行捕获所有异常,以防止应用出现拒绝服务漏洞:

  • 空指针异常;
  • 类型转换异常;
  • 数组越界访问异常;
  • 类未定义异常;
  • 其他异常;

开放网络服务安全测试

安全风险

Android应用通常使用PF_UNIX、PF_INET、PF_NETLINK等不同域名的socket来进行本地进程间通信或者远程网络通信,这些socket暴漏了潜在的本地或远程攻击面,历史上也出现过不少利用socket进行拒绝服务、root提权或者远程命令执行的案例。

特别是PF_INET类型的网络socket,可以通过网络与Android应用通信,其原本用于linux环境下开放网络服务,由于缺乏对网络调用者身份或者本地调用者的安全检查机制,在实现不当的情况下,可以突破Android的沙箱限制,对被攻击的应用执行命令,导致比较严重的漏洞。

执行步骤

  1. 使用反编译工具打开应用,反编译出应用源码。
  2. 检测对收到socket数据是否进行处理,代码示例如下:
//定义读取socket命令
public static String readCMDFromSocket(InputStream in) {
        int MAX_BUFFER_BYTES = 2048;
        String msg = "";
        byte[] tempbuffer = new byte[MAX_BUFFER_BYTES];
        try {
            int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length);
            if( numReadedBytes > -1 )
                msg = new String(tempbuffer, 0, numReadedBytes, "utf-8");
            tempbuffer = null;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return msg;
    }
    ...
    //处理socket信息
    public void handlemsg()
    {
      ...
      msg = readCMDFromSocket(in)
      if ("exec" == msg)
      {
       //没有任何的socket命令校验
        ...
        ...
      }
      ...
    }
  1. 如果出现类似以上代码,未对接收到的socket和内容做任何校验检查,则风险存在。

预期结果 对socket数据内容进行校验。

整改建议 直接传递命令或者间接处理敏感信息时,避免使用socket实现。

运行其它可执行程序风险

安全风险

APP中使用了有运行其他程序的代码逻辑,如果执行的代码是第三方库中,可能会存在未知的恶意行为,如果是程序自身代码,若调用逻辑有缺陷可能会导致执行其他恶意的第三方程序,攻击者可能会利用该缺陷执行恶意代码。

执行步骤

  1. 使用反编译工具打开应用,反编译出应用源码。
  2. 在源码中查找使用Runtime.getRuntime().exec执行第三方程序的代码样例:
try {
            Process p1 = Runtime.getRuntime().exec(
                    new String[] { "/system/bin/ls", "-l" },
                    new String[] { "a=1", "b=2" });
            Runtime.getRuntime().load(
                    "/data/data/com.baidu.seclab/lib/libtest.so");
            Runtime.getRuntime().loadLibrary("test");
        } catch (IOException e) {
            e.printStackTrace();
        }
  1. 发现使用Runtime.getRuntime().exec执行第三方程序后,且检测到调用逻辑中存在缺陷,则风险存在。停止测试,记录漏洞。

预期结果 合理使用Runtime.getRuntime().exec等函数,防止恶意调用。

整改建议 合理设置程序逻辑防止恶意调用,如果该行为是非期望行为,移除相关代码。

数据的完整性进行校验

安全风险

App向服务器提交的数据易被中间人篡改,对用户数据的完整性造成影响,如用户信息被破解利用等问题。

执行步骤

  1. 使用Charles代理工具连接设备代理,启动app,正常操作app;
  2. 在app上对提交的数据进行修改,重新提交,查看这些参数的值有无变化;
  3. 对获取数据包参数进行修改并重放,查看是否可正常返回;
  4. 若数据正常返回,没有提示数据错误,说明app请求参数未进行完整性校验。

预期结果:请求数据中包含完整性校验字段;

整改建议:添加完整性校验逻辑。

键盘劫持测试

安全风险:

攻击者可以通过劫持键盘窃取用户输入数据,可能带来用户账号密码、敏感数据等泄露的风险,特别是银行金融类App。

执行步骤

  1. 打开应用,选择一处输入点进行输入
  2. 观察应用程序是否打开自带键盘,如果使用系统键盘输入,则问题存在。记录漏洞,停止测试。

预期结果:App在输入时使用自带键盘

整改建议:在App内集成自带键盘,并采用随机分布式键盘。

本文分享自微信公众号 - QA一隅(sutune2020),作者:Sutune

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-02-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • App安全测试

    在App项目中都会碰到三座App安全大山。App客户端安全、数据传输安全、App服务端安全。下面以分析检测的思路进行对App安全威胁的这三座大山进行一些剖析梳理...

    小道安全
  • Android之APP安全测试篇

    反编译 apk 文件,在AndroidManifest.xml 中查找Activity组件

    厦门-安仔
  • Android之APP安全测试篇

    反编译 apk 文件,在AndroidManifest.xml 中查找Activity组件

    洛米唯熊
  • iOS App 安全测试

    BinaryCookieReader.py (用法: 将cookie文件导出到PC端,python BinaryCookieReader.py [cookies...

    VV木公子
  • 【安全测试】Android APP安全测试之敏感信息本地存储

    aerfa
  • App安全测试——Android APK反编译

    我们下载到的Android App 安装包是 Apk文件(Android Application Package) 。通过 Apk 文件,我们也可以得到这个应用...

    清风穆云
  • APP安全测试点概述

    目的是为了保护公司的知识产权和安全方面的考虑等,一些程序开发人员会在源码中硬编码一些敏感信息,如密码。而且若程序内部一些设计欠佳的逻辑,也可能隐含漏洞,一旦源码...

    软件测试君
  • 安全测试|移动端安全测试drozer

    手机应用的快速增长,手机应用安全成为一个热门的话题,android的安全问题有一大部分的原因是因为android的组件暴露、权限使用不当导致的。

    测试邦
  • 安卓APP安全漏洞测试 如何对APP安全进行全方位的漏洞检测

    客户网站以及APP在正式上线之前,都会找专业的安全公司进行测试,检测网站、APP是否存在漏洞,以及一些安全隐患,大多数的运营者觉得安装一些安全防护软件就足以防止...

    网站安全专家
  • 安全测试Checklist

    安全性测试的实施,需要基于威胁分析方面考虑设置检查点,同时该阶段也是测试案例的设计阶段。一个优秀的测试策略的设计方案,可以发现更多的软件安全方面存在的安全隐患;...

    Altumn
  • 安全测试 一次关于WEB的URL安全测试

    时间精力问题,对web安全这块也没咋深入研究,但因为某个小插曲,公司要求先做个简单的安全测试,主要是针对URL的测试。

    授客
  • Android安全测试框架Drozer(安装篇)

    Android安全测试框架Drozer(安装篇) ...

    Java架构师必看
  • 安卓APP测试知识大全【面试储备】

    Android操作系统其实是一个多用户的linux操作系统,每个android应用使用不同的用户,运行在自己的安全沙盘里。系统为所有的文件设置权限,这样一来只有...

    FunTester
  • 安全测试 网上商城购买支付安全测试

    测试前,查看了关于支付宝接口的相关资料,包括一些处理流程,大概了解下,觉得关于支付的测试主要在数据提交、请求这块。于是便想能否通过获取相关请求,自己模拟浏览器...

    授客
  • APP端测试系列(1)——通信安全

    关于APK包、Android架构等基础知识这里先不做介绍,直接介绍测试项和测试方法。

    Jayway
  • WEB安全性测试

      所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用...

    小老鼠
  • iOS安全测试—Sandbox

    Sandbox 沙盒也叫沙箱,其原理是通过重定向技术,把程序生成和修改的文件定向到自身文件夹中。在沙盒机制下,每个程序之间的文件夹不能互相访问。

    清风穆云
  • iOS安全测试-KeyChain

    根据苹果的介绍,iOS设备中的Keychain是一个安全的存储容器,可以用来为不同应用保存敏感信息比如用户名,密码,网络密码,认证令牌。苹果自己用keychai...

    清风穆云
  • APP安全测试 从服务器端到网站端做全面的安全检测

    很多公司都有着自己的APP,包括安卓端以及ios端都有属于自己的APP应用,随着互联网的快速发展,APP安全也影响着整个公司的业务发展,前段时间有客户的APP被...

    网站安全专家

扫码关注云+社区

领取腾讯云代金券