本文共 1432 字,大约阅读时间需要 4 分钟。
android对联系人及短信等数据的数据库访问只能通过其提供的相关协议,如:
content://sms/
用getContentResolver()获得一个ContentResolver,
调用getContentResolver().query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
返回一个Cursor对象,获得需要的数据。
这种方式使用方便,却不利于控制,比如说query中没有group by,如果要做统计,收集到所有结果再自己实现统计肯定是不划算的。
很早就知道了在query的第二个参数可以hack得到想要的值,如new String[]{“max(_id)as id”},可以得到最大的_id,
于是想到在其后的参数做文章,由于group by语句要在order by之前,于是,只能在第三个参数,也就是where语句里下手了。
getContentResolver().query( Uri.parse(“content://sms/”) , new String[]{“id”}, “1=1 group by thread_id “, null, null);
想着用不存在的列名导致sql出错然后打印出sql语句,意外发现如下错误:
原来android组织where语句是将所有条件用()括起来,那么接下来的就好办了,拼接字符串吧
我需要的sql语句为
select count(thread_id) as count from sms where (type = 1) group by (thread_id) order by desc
那么,相应的query方法为
getContentResolver().query( Uri.parse("content://sms/") , new String[]{"count(thread_id) as count"}, "type = 1) group by (thread_id ", null, null)
呵呵,执行成功
仅仅到这一步,限制还是很多的,因为这个方法只能控制select与from,where与order by,order by与之后的语句,这样from与where之间的联表操作就无法控制了。
于是继续深挖,,记得接触过sql注入,里面时常会用到注释法,即拼接出完整sql语句后再连上注释符,其后的语句就没有任何作用了,得知sqlite3的注释符为- -,那么继续测试
select * from sms as a join threads as b where a._id = 1 order by a.date desc– from sms where () order by date desc
相应的query方法为
getContentResolver().query( Uri.parse("content://sms/") , new String[]{"* from sms as a join threads as b where a._id = 1 order by a.date desc--"}, null, null, null)
继续成功
这样,只要能有权限访问到系统数据库,不就任我为所欲为吗?
转载地址:http://wolli.baihongyu.com/