前言:
最近入门开始玩android的安全,但是国内研究的真的很少,国外有本牛逼的书《Android Hacker's Handbook》,写的不错,但是看着睡着了好几次。泪奔。前几天测试了下drozer,感觉挺好用,应xsser要求写一篇关于APP中sql注入的文章。由于本人刚入门,描述或者说法难免有错误,还望大牛们跟贴指正。
1. android中的数据存储与查询
1.1 数据存储
众所周知,Android中的数据多是存储在Sqlite数据库中,这个文件一般在手机的系统路径如:/data/data/com.xx.yy/databases/zzz.db。其中com.xx.yy为包名。zzz.db名字随意,为数据库文件。
在安卓应用程序中,有一个非常重要的组件,即“content provider”
当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。
可以看出,该组件的目的就是将自己的数据暴露出去,也就是说程序A提供了一个provider,然后程序B可以通过访问这个provider来获取A暴露的数据。如此一来即达到了数据共享的目的。那么程序B又是如何访问这个provider的呢?
1.2 数据查询
一个程序要访问暴露的provider,首先要知道访问的目标地址,类似http协议,provider也有自己的规范,即类似content://com.aaaa.bbb.class/tablename
其中,com.aaaa.bbb为包名,class为类名,tablename为表名,一般是这样子,具体看自己定义了。
看一个查询例子:
Cursor cursor = contentResolver.query( Words_CONTENT_URI, new String[]{"user","pwd"}, null, null, null);
这是调用contentResolver的query方法进行数据库查询,返回一个cursor对象,即类似DataReader的东西,里面是返回结果。
来看看query的参数
Cursor android.content.ContentResolver.query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
uri即content://com.aaaa.bbb.class/tablename
projection即你要查询的列名
selection和selectionArgs共同控制后面的sql语句中的where内容.
sortOrder即order by xxx的内容。
那么例子中的查询整个构造的语句即:
select user,pwd from tablename;
2.Sql注入问题
综合上面的内容,我们可以看到,query里至少两个参数我们可控,一个是projection,一个是selection,这两个都会影响SQL与的组成,也就为注入提供了可能。
这里以某app为例(虽然感觉漏洞影响有限,但是为了尊重厂商,请允许打码处理),该app对外暴露了一个content provider,uri为:content://com.masaike.mobile.downloads/my_downloads,其中com.masaike.mobile为包名,downloads为库的名字,my_downloads为表名(不一定,可自定义的哦)。
现在语句这么写:
Cursor cursor = contentResolver.query("content://com.masaike.mobile.downloads/my_downloads", new String[]{"_id'","method"},null, null, null);
其中_id和method为两个字段名,我们在_id后面加个单引号,运行下看logcat内容:
从上图很容易看出来,SQL语句因为有个单引号,导致出错。所以注入是存在的。
而如果我们修改projection的内容为"* from sqlite_master where type='table';--",这样子即在闭合后面查询的情况下显示出来全部的表名。当然也可以构造其他语句了。
3. 延伸问题
3.1.update
如果有些敏感配置文件存放在库里面,并且存在注入,我们可以通过contentResolver的update方法去修改配置文件,达到间接控制的目的,这个可以用来修改敏感配置、生成短消息钓鱼之类的。
3.2. 跨库
很多情况下,暴露的是一些无关紧要的东西,比如“downloads”这个库,里面仅仅放了一些下载历史。还有些比如message,里面只放了一些通知。这个时候影响很有限,但是同时,在download.db的同目录下还有个account.db,这个里面存放了所有用户名和密码,如果可以跨到这个库,我们会收获更多。而sqlite本身是支持attach来跨库操作的,但是我测试的时候无法在一个完整的sql语句中完成跨库读取,具体问题见:http://zone.wooyun.org/content/15084
3.3. 任意文件读取
数据存储的uri很多时候并不依赖于sqlite库,还有些是本地文件,会根据content/com.xx.yy/filepath 这种uri来读取文件,当这个filepath可控的时候,我们就可以借助这个uri读取任意文件,当然得是应用程序有权限读取的文件。某漏洞
4. 自动化发现漏洞
推荐工具:drozer
使用参考案例:http://www.freebuf.com/tools/26503.html
练手可以看下官方的文档即可。
自动化语句:run scanner.provider.injection 即可自动化发掘已安卓的app中的SQL注入问题。
5. 总结
这个漏洞的影响点我个人认为有两个问题,一是content provider不应该暴露让任意程序都可访问。二是其他程序是否可以update数据库,比如直接修改配置参数之类的。如果仅仅是读取一些不敏感信息,影响有限,但是如果update的话,影响就会变大。如果可以跨库读取内容,那影响就会变得更大。
留言评论(旧系统):