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
,意思是将输入的usr
和pwd
的值写入到
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
中首先创建了数据库,接着创建数据库表myuser
和user password
字段,为防止表重复还加上了IF NOT EXISTS
saveCredentials
中,初始化了两个编辑框, 向myuser
表添加usr
和pwd
数据行
输入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
并且设置了setJavaScriptEnabled
为true
,get
方法下使用WebView.loadUrl
加载网页,但其中并没有做验证,导致可以使用File进行本地文件读取等操作
演示
防范方法:
1.若需读取特定本地文件就应直接写死。
2.若不需读取JavaScript,setJavaScriptEnabled 就设为false,避免使用者使用旧版Android OS时受XSS风险影响。
访问控制问题 - 第1部分
将App拖入Jadx
中,找到MainActivity
,第九个Button
可以看到初始化intent
后,设置了一个Action
,后面判断这个隐式activity
是不是空
在AndroidManifest.xml
中搜索该Action
,隐式调用Intent
可以使用adb
或drozer
这里使用adb
防范方法:
1.使用显式Intent,确保不会遭其他App存取。
2.不该exported的component应设为false。
访问控制问题 - 第2部分
将App拖入Jadx
中,找到MainActivity
,第十个Button
viewAPICredentials
方法先初始化intent
, 单选按钮来作为布尔值默认True
,设置了action
用来隐式调用带有jakhar.aseem.diva.action.VIEW_CREDS2
的Activity
和传递字符串名称和布尔值
,最后判断这个隐式activity
是不是空
然后我们找到action
对应的Activity
APICreds2Activity
这里的就很简单了, 获取上一个Activity
的Intent
,intent.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
方法
getDefaultSharedPreferences
取preferences
的路径(/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.xml
中NotesProvider
的exported
状态是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
对应的文件,这是指要被compile
的c/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函数