diva write-up
diva是一个移动安全测试app,专门给开发者和安全人员演示用的app,里面包含很多的安全问题。
地址:https://github.com/payatu/diva-android
通过它能比较好的测试一些常见的andrid安全案例。下面是记录的测试过程。
不安全的日志输出
1.adb logcat
2.输入用户凭证,观察日志输出。
3.源码中:Log.e()
查看源码中代码
硬编码
硬编码是开发人员将一些密钥等重要信息保存到了代码中。
用jd查看HardcodeActivity.class
攻击者只需要在app中输入秘钥vendorsecretkey就可以访问成功。
不安全的存储1(shared_prefs/xxx.xml)
不安全的数据存储也是App常见的安全问题之一,主要有三种方式:
1将敏感数据保存到配置文件中;
2将敏感数据保存在本地的sqlite3数据库中;
3将敏感数据保存在临时文件或者sd卡中。
SharedPreferences类存储的数据会以.xml的形式存储在:
/data/data/jakhar.aseem.diva/shared_prefs
源代码
不安全的存储2(databases/xxx.db)
用户的敏感信息存储到本地的数据库中,一般app对应的数据库目录:/data/data/apppackagename/databases
本例中是:/data/data/jakhar.aseem.diva/databases
如图:
源代码
不安全的存储3(临时文件)
文件在 /data/data/jakhar.aseem.diva/
源代码
不安全的存储4(SD卡)
存储在sd卡中,漏洞代码片段:
不安全的输入1(sqli)
打开日志:adb logcat
输入一个单引号,在日志中可以看到报错信息,存在sql注入。
输入’ or ‘1’=’1,可返回所有用户密码。
没有验证输入,直接带入sql语句查询
不安全的输入2(读取本地文件)
这个activity的功能是显示用户输入的网页。如图,当你输入www.baidu.com它会使用一个webview去加载这个页面。
目标是使用此功能访问设备上的敏感信息。先来看看它的源代码,在InputValidation2URISchemeActivity.java中
用loadUrl方法加载用户输入的URL,这个方法也可以加载本地文件。
读取本地文件:file:///data/data/jakhar.aseem.diva/shared_prefs/jakhar.aseem.diva_preferences.xml
访问控制1(Activity 1)
目的是在不点击此按钮的情况下访问这些信息。看看AndroidManifest.XML文件中与Vendor API Credentials activity相关的信息。
activity是通过intent filter“保护”的。intent filter不应该被作为一种保护机制。当intent filter和像activity这样的组件一起使用时,组件是被暴露在外的。这里的activity可以被其它应用从外部加载,这是非常不安全的。我们可以通过终端中下面的命令来验证。
利用am(Activity Manager tool)启动暴露的组件,来绕过权限控制:adb shell am start jakhar.aseem.diva/.APICredsActivity
或者
adb shell am start -n jakhar.aseem.diva/.APICredsActivity -a jakhar.aseem.diva.action.VIEW_CREDS
使用drozer绕过权限
访问控制2(Activity 2)
如果你是注册用户,你就能访问tweeter API的凭据。我们的目标是在不注册的情况下访问它。再次看看AndroidManifest.XML文件。
尝试相同的命令发现并不能绕过,出现了pin码,看看源代码文件APICreds2Activity.java
可以看出,当我们用ADB命令启动intent时需要一个额外的布尔类型参数。下面这一行解析字符串chk_pin。
boolean bcheck=i.getBooleanExtra(getString(R.string.chk_pin),true);
我们可以在strings.xml中查找它实际对应的值。
这个条件是用来验证用户是否已经注册的,可以从AccessControl2Activity.java的以下代码中看出。
如果 chk_pin = true 说明需要现在注册,跳转到注册页面;如果 chk_pin = false 说明不需要注册,或者说已经完成注册,就会跳到认证后的界面
据此我们需要设置 chk_pin = false 来控制页面跳转完成破解
使用adb下面命令绕过
adb shell am start -a jakhar.aseem.diva.action.VIEW_CREDS2 -n jakhar.aseem.diva/.APICreds2Activity --ez check_pin false
或者drozer命令run app.activity.start --component jakhar.aseem.diva jakhar.aseem.diva.APICreds2Activity --extra boolean check_pin false
访问控制3(Content Providers)
笔记pin码保护,发现注册笔记生成一个pin码,必须通过pin码才能绕过,查看AndroidManifest.xml中关于此案例的描述
发现有个 exported = true 的 provider 注册。content providers 使用URI,通常开头是 content://
使用搜索功能查找关键字:content://
找到 NotesProvider.smali 中重要信息
根据以上smail代码,找到路径content://jakhar.aseem.diva.provider.notesprovider/notes
根据xml中属性信息,这个content 是exported = true 的,也就意味着可以直接外部访问
输入命令adb shell content query --uri content://jakhar.aseem.diva.provider.notesprovider/notes
就可以查询到认证后的私有笔记信息
使用drozerrun scanner.provider.finduris -a jakhar.aseem.diva
run app.provider.query content://jakhar.aseem.diva.provider.notesprovider/notes/
硬编码
在Hardcode2Activity. class中
activity在加载时创建了DivaJni class的一个对象。查看其它文件发现有一个叫做DivaJni.class的文件
程序加载了一个名为divajni的库,解压apk进入lib目录。对于每种架构,都有一个libdivajni.so的实例。随便找一个运行strings命令
olsdfgad;lh找到了这个key。这个写法是 java调用c/cpp程序常用的jni接口。可以ida反编译so文件
发现是在比较olsdfgad;lh这个字符串
或者有源代码,查看源码发现确实存在jni文件夹以及 divajni.c程序
很显然,将字符串硬编码在so文件中也同样是不安全的
输入验证问题
翻译一下是:
目标:这是一个导弹发射程序,我们应当传播爱与和平而不是战争0.0。让此程序失效,你的任务不是找到代码发射导弹,而是让应用崩溃(并找到崩溃原因)。
提示:不正确或不存在的输入验证会导致应用漏洞。外部的输入必须得进行验证。这是一个经典的缓冲区溢出漏洞。如果你可以实现代码执行,那就太nb了。
然提示是缓冲区溢出类漏洞,那主要工作就是要确定缓冲区的长度。
查看反编译代码 InputValidation3Activity.class 发现验证需要 djni.initiateLaunchSequence() 来确定
分析代码,仍然需要System.loadLibrary(“divajni”)中jni接口调用的 divajni.c程序,查看 divajni.c 源码,找到 initiateLaunchSequence()的定义
查看 divajni.c 源码,找到 initiateLaunchSequence()的定义
分析代码,问题出在strcpy(code,pcode),没有对pcode的长度做判断就直接给了code,而code的长度之前定义的为20,所以这里就会出现很明显的缓冲区溢出。
也可以通过ida查看so文件
测试时发现,当输入字符 大于32 时,才可以引发程序崩溃。可以使用 adb logcat查看崩溃时堆栈数据