DIVA通关详细攻略

不安全的日志记录

将App拖入Jadx中,找到MainActivity,第一个Button

从代码中查看,将获取到的字符串输出在Log日志中

通过运行cmder填入代码中的TAG即可查看到

防范方法:
1.AndroidManifest.xml内的android:debuggable设为false.不过你的App如果能被重包,或是我改掉了手机内的ro.debuggable,这设定了也没用。

硬编码问题 - 第1部分

App拖入Jadx中,找到MainActivity,第二个Button

获取到的字符串和vendorsecretkey123做比较

填入固定字符串

防范方法:
1.不要把敏感信息,如密码、加密的密钥等写在程序中。

不安全的数据存储 - 第1部分

将App拖入Jadx中,找到MainActivity,第三个Button

这里可以看到使用了SharedPreferences,意思是将输入的usrpwd的值写入到

SharedPreferences中,使用的getDefaultSharedPreferences方法去生成文件为{packageName_preferences}. PS:SharedPreferences数据则存储在应用程序私有目录中

输入admin admin显示保存成功

Jadx有包名,进入data/data/{Package name}/shared_prefs中查看

防范方法:
1.敏感数据应加密后再储存,且应使用安全的加密方式,详情参考 [NIST](http://csrc.nist.gov/groups/STM/cavp/validation.html)。

不安全的数据存储 - 第2部分

将App拖入Jadx中,找到MainActivity,第四个Button

onCreate中首先创建了数据库,接着创建数据库表myuseruser password字段,为防止表重复还加上了IF NOT EXISTS

saveCredentials中,初始化了两个编辑框, 向myuser表添加usrpwd数据行

输入admin,admin

这里使用安卓自带的sqlite3查看

防范方法:
1.敏感数据应加密后再储存,且应使用安全的加密方式,详情参考 [NIST](http://csrc.nist.gov/groups/STM/cavp/validation.html)。

不安全的数据存储 - 第3部分

将App拖入Jadx中,找到MainActivity,第五个Button

saveCredentials方法,里面有两个输入框,而后首先获取了应用数据存储路径, 创建一个文件前缀uinfo后缀为tmp的临时文件到获取的应用路径中,设置可读可写。创建文件写入对象FileWriter, 将输入框中的内容写入到uinfo

因此临时文件在私有目录下,输入admin1 admin2如下

防范方法:
1.敏感数据应加密后再储存,且应使用安全的加密方式,详情参考 [NIST](http://csrc.nist.gov/groups/STM/cavp/validation.html)。

不安全的数据存储 - 第4部分

将App拖入Jadx中,找到MainActivity,第六个Button

首先进入该方法中我们看到saveCredentials方法下,照旧两个输入框,

Environment.getExternalStorageDirectory这是获取外部存储目录的方法,那这样大概就能确定文件就在storage或者mnt目录下,后面的内容和上面的几乎相同

但是在测试中,可能模拟器版本过高未能创建成功

输入验证问题 - 第1部分

将App拖入Jadx中,找到MainActivity,第七个Button

这里我们拆开两份来看,这里可以看到INSECURE DATA STORAGE-PART 2和这一关代码是相识的,目的就是创建数据库并且插3个用户的字段

在查询这里,首先给了个输入框, 39行就看出了问题,将输入框的内容拼接到了搜索语句中,并且未做处理,最后还将异常抛出

所以我们可以使用adb logcat | grep TAG筛选

我们将其修改成永真

防范方法:
1.使用SQLite API
2.若要使用一般SQL语法,就不要拼接字符串,同时应过滤特殊字符串

输入验证问题 - 第2部分

将App拖入Jadx中,找到MainActivity,第八个Button

代码很简洁,初始化了Webview并且设置了setJavaScriptEnabledtrueget方法下使用WebView.loadUrl加载网页,但其中并没有做验证,导致可以使用File进行本地文件读取等操作

演示

防范方法:
1.若需读取特定本地文件就应直接写死。
2.若不需读取JavaScript,setJavaScriptEnabled 就设为false,避免使用者使用旧版Android OS时受XSS风险影响。

访问控制问题 - 第1部分

将App拖入Jadx中,找到MainActivity,第九个Button

可以看到初始化intent后,设置了一个Action,后面判断这个隐式activity是不是空

AndroidManifest.xml中搜索该Action,隐式调用Intent可以使用adbdrozer

这里使用adb

防范方法:
1.使用显式Intent,确保不会遭其他App存取。
2.不该exported的component应设为false。

访问控制问题 - 第2部分

将App拖入Jadx中,找到MainActivity,第十个Button

viewAPICredentials方法先初始化intent, 单选按钮来作为布尔值默认True,设置了action用来隐式调用带有jakhar.aseem.diva.action.VIEW_CREDS2Activity传递字符串名称和布尔值,最后判断这个隐式activity是不是空

然后我们找到action对应的Activity APICreds2Activity

这里的就很简单了, 获取上一个ActivityIntentintent.getBooleanExtra获取了check_pin参数和设置默认值的True,所以if判断默认式true但加了取反所以只要选择了单选框就一直为true, 只有值为false才能拉起APICreds2Activity

我们这里使用依旧使用adb

Adb shell  am start -a  jakhar.aseem.diva.action.VIEW_CREDS2  -n  jakhar.aseem.diva/.APICreds2Activity --ez check_pin false --ez 传递的参数就是check_pin 值为false

防范方法:
1.使用显式Intent,确保不会遭其他App存取。
2.不该exported的component应设为false。

访问控制问题 - 第3部分

将App拖入Jadx中,找到MainActivity,第十一个Button

进到AccessControl3Activity中,onCreate方法中17-26可以看到getDefaultSharedPreferences 取得 preferences 的路径,从SharedPreferences获取字符串到pin,并在下判断pin不能为空

addPin方法

getDefaultSharedPreferencespreferences的路径(/data/data/<package_name>/shared_prefs/<package_name>_preferences.xml),接着将用户输入的密码明文储存至该文件中,如果pin值为空则显示提示框,40-43 有一个按钮事件,向Shared写入参数:参数值,下面判断取当前控件的可见性状态 不等于0 意思是输入了pin后显示提示框

goToNotes会去启动AccessControl3NotesActivity,更入Activity,这里使用了ContentProvider,并且AndroidManifest.xml对应的Activity设置了可导出和可系统初始化

getContentResolver会根据query取得指定的信息,所以我们再来看一下NotesProvider内的CONTENT_URI

最后就是确认AndroidManifest.xmlNotesProviderexported状态是true即可,后面android:authorities标识这个ContentProvider其他第三方程序可以通过此标识来找到它

所以我们可以直接使用adb shell访问该uri

adb shell content query –-uri content://jakhar.aseem.diva.provider.notesprovider/notes

防范方法:
1.使用显式Intent,确保不会遭其他App存取。
2.不该exported的component应设为false。

硬编码问题 - 第2部分

将App拖入Jadx中,找到MainActivity,第十一个Button

onCreate方法新建了jni,access方法查看如下判断输入的内容是不是jni中的内容

找到加载的so

前面是会去 load divajni 这个 library,再来下面可看到它申明变量时使用了native

native 的作用大致上就是 java 可以借由 c传递、处理数据,而透过的这个机制叫 JNI。这边我们不用知道太复杂,先知道在使用这机制之前,必须先在 src 文件夹内建立 jni 的文件夹:

进入JNI文件夹中,再来看Android.mk,我们要找出LOCAL_SRC_FILES对应的文件,这是指要被compilec/c++ source code

拖入so程序到ida未有看到函数混淆,查看到Java_jakhar_aseem_diva_DivaJni_access函数,点击即可

这里的问题是使用JNI时与native对应的JNI function很容易被逆向人员追溯到敏感信息

 防范方法:
 1.加密so库
 2.混淆JNI function

输入验证问题 - 第3部分

将App拖入Jadx中,找到MainActivity,第十一个Button

于上面的题目差不多,但是使用到的是jni中的initiateLaunchSequence

我们接着看jni中的initiateLaunchSequence函数, strcpy函数没对字符串长度进行长度检测,

查看程序源代码, 前面的变量CODESIZEMAX值为20,一但用户输入值超过20,便可能造成溢出

防范方法:
1.限制用户输入的字符串长度。
2.使用安全的函数,停止使用strcpy函数

本文链接:

https://www.linqi.net.cn/index.php/archives/445/