SSL suistimallerine karşı koruma sağlamak için güvenlik sağlayıcınızı güncelleyin

Android, güvenli ağ iletişimi sağlamak için bir güvenlik Provider kullanır. Ancak zaman zaman varsayılan güvenlik sağlayıcıda güvenlik açıkları bulunur. Karşı koruma için Google Play hizmetleri, cihazın güvenlik sağlayıcısını otomatik olarak güncellemenin bir yolunu sunar. bilinen istismarlara karşı koruma sağlar. Google Play Hizmetleri yöntemlerini çağırarak, uygulamanızın bilinen kötüye kullanımlara karşı koruma sağlamak için en son güncellemeleri içeren bir cihazda çalıştığından emin olabilirsiniz.

Örneğin, OpenSSL'de bir güvenlik açığı keşfedildi (CVE-2014-0224) saldırıya açık bırakabilen uygulamalar, güvenlik açığını çözen mahsuru yoktur. Google Play Hizmetleri 5.0 sürümü bir düzeltme sunar ancak uygulamaların bu düzeltmenin yüklü olup olmadığını kontrol etmesi gerekir. Ölçüt Google Play Hizmetleri yöntemlerini kullanarak, uygulamanızın çalıştığından emin olmanıza yardımcı olabilirsiniz. güvenli bir cihaz kullanıyorsanız.

Dikkat: Cihazın güvenliği güncelleniyor Provider güncellenmiyor android.net.SSLCertificateSocketFactory, hale gelir. Kullanımdan kaldırılan bu sınıfı kullanmak yerine, uygulama geliştiricilerin Kriptografiyle etkileşim için üst düzey yöntemler kullanır (ör. HttpsURLConnection

ProviderInstaller'ı kullanarak güvenlik sağlayıcıya yamalar uygulama

Bir cihazın güvenlik sağlayıcısını güncellemek için ProviderInstaller sınıfını kullanın. Güvenlik sağlayıcısının güncel olduğunu onaylayabilir (ve güncelleyebilir, (gerekirse) şu numarayı arayarak bu sınıfın installIfNeeded() (veya installIfNeededAsync()) yöntemidir. Bu bölümde bu seçenekler genel hatlarıyla açıklanmaktadır. Sonraki bölümlerde, ayrıntılı adımlara ve örneklere göz atın.

installIfNeeded()'ü aradığınızda ProviderInstaller şu işlemleri yapar:

  • Cihazın Provider yöntemi başarıyla tamamlandıysa güncellendiğinde (veya zaten güncelse) yöntem bir istisna olmadan geri döner.
  • Cihazın Google Play Hizmetleri kitaplığı güncel değilse yöntem atar GooglePlayServicesRepairableException. Daha sonra uygulama bu istisnayı yakalayıp Google Play Hizmetleri'ni güncellemek için kullanıcıya uygun bir iletişim kutusu.
  • Kurtarılamaz bir hata oluşursa yöntem GooglePlayServicesNotAvailableException öğesi Provider güncellenemez. Uygulama daha sonra istisnayı yakalayabilir ve standart düzeltme akış şemasını görüntüleme gibi uygun bir işlem seçebilir.

installIfNeededAsync() yöntemi de benzer şekilde çalışır. Bununla birlikte, istisna atma yerine başarı veya başarısızlığı belirtmek için uygun geri çağırma yöntemini çağırır.

Güvenlik sağlayıcı zaten güncelse installIfNeeded(), unutmayın. Yöntem yeni bir Provider yüklemesi gerekiyor. Bu işlem 30-50 ms (daha yeni cihazlarda) - 350 ms (eski cihazlarda) cihazlar). Kullanıcı deneyimini etkilememek için:

  • installIfNeeded() mesaj dizisinin ağı kullanmayı denemesini beklemek yerine, mesaj dizisi yüklendiğinde hemen arka plandaki ağ mesaj dizilerinden çağırın. (Güvenlik sağlayıcının güncellenmesi gerekmiyorsa yöntem hemen döndürüldüğünden, yöntemi birden çok kez çağırmanın bir zararı yoktur.)
  • Kullanıcı deneyimi, ileti dizisi engellemesinden etkilenebiliyorsa (ör. çağrı, kullanıcı arayüzü ileti dizisindeki bir etkinlikten geliyorsa) yöntemin installIfNeededAsync() adlı ayarsız sürümünü çağırın. (Bunu yaparsanız işlemin bitmesini beklemeniz gerekir) inceleyin. ProviderInstaller dinleyicinizin onProviderInstalled() yöntemini çağırarak başarıyı bildirir.)

Uyarı: ProviderInstaller güncel bir Provider yükleyemezse cihazınızın güvenlik sağlayıcısı bilinen güvenlik açıklarına karşı savunmasız olabilir. Uygulamanız, tüm HTTP iletişimleri şifrelenmemiş gibi davranmalıdır.

Provider güncellendiğinde, güvenlik API'leri (SSL API'leri dahil) bunun üzerinden yönlendirilir. (Ancak bu durum, CVE-2014-0224 gibi saldırılara karşı savunmasız kalan android.net.SSLCertificateSocketFactory için geçerli değildir.)

Eşzamanlı olarak yama uygula

Güvenlik sağlayıcısına yama uygulamanın en basit yolu, eşzamanlı yöntem installIfNeeded(). Kullanıcı deneyimi, ileti dizisi engellemesinden etkilenmeyecekse bu uygun bir seçenektir tamamlanması beklenir.

Örneğin, güvenlik sağlayıcısını güncelleyen bir çalışanın uygulamasını görebilirsiniz. İşçiler arka planda çalıştığından, güvenlik sağlayıcının güncellenmesini beklerken iş parçacığının kilitlenmesi normaldir. Çalışan, güvenlik sağlayıcıyı güncellemek için installIfNeeded() ile iletişime geçer. Yöntem normal şekilde döndürülürse işleyici, güvenlik sağlayıcının güncel olduğunu bilir. Yöntem bir istisna atarsa uygun eylemde bulunabilir (örneğin, kullanıcıdan Google Play Hizmetleri'ni güncelleyin).

Kotlin

/**
 * Sample patch Worker using {@link ProviderInstaller}.
 */
class PatchWorker(appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {

  override fun doWork(): Result {
        try {
            ProviderInstaller.installIfNeeded(context)
        } catch (e: GooglePlayServicesRepairableException) {

            // Indicates that Google Play services is out of date, disabled, etc.

            // Prompt the user to install/update/enable Google Play services.
            GoogleApiAvailability.getInstance()
                    .showErrorNotification(context, e.connectionStatusCode)

            // Notify the WorkManager that a soft error occurred.
            return Result.failure()

        } catch (e: GooglePlayServicesNotAvailableException) {
            // Indicates a non-recoverable error; the ProviderInstaller can't
            // install an up-to-date Provider.

            // Notify the WorkManager that a hard error occurred.
            return Result.failure()
        }


        // If this is reached, you know that the provider was already up to date
        // or was successfully updated.
        return Result.success()
    }
}

Java

/**
 * Sample patch Worker using {@link ProviderInstaller}.
 */
public class PatchWorker extends Worker {

  ...

  @Override
  public Result doWork() {
    try {
      ProviderInstaller.installIfNeeded(getContext());
    } catch (GooglePlayServicesRepairableException e) {

      // Indicates that Google Play services is out of date, disabled, etc.

      // Prompt the user to install/update/enable Google Play services.
      GoogleApiAvailability.getInstance()
              .showErrorNotification(context, e.connectionStatusCode)

      // Notify the WorkManager that a soft error occurred.
      return Result.failure();

    } catch (GooglePlayServicesNotAvailableException e) {
      // Indicates a non-recoverable error; the ProviderInstaller can't
      // install an up-to-date Provider.

      // Notify the WorkManager that a hard error occurred.
      return Result.failure();
    }

    // If this is reached, you know that the provider was already up to date
    // or was successfully updated.
    return Result.success();
  }
}

Eşzamansız olarak yama yap

Güvenlik sağlayıcının güncellenmesi 350 ms'ye kadar sürebilir ( eski cihazlarda kullanılabilir). Güncellemeyi kullanıcı deneyimini doğrudan etkileyen bir iş parçacığında (ör. kullanıcı arayüzü iş parçacığı) yapıyorsanız sağlayıcıyı güncellemek için senkronize bir çağrı yapmak istemezsiniz. Bu, işlem tamamlanana kadar uygulamanın veya cihazın donmasına neden olabilir. Bunun yerine, installIfNeededAsync() ayarlarını kullanın. Bu yöntem, geri çağırma işlevlerini çağırarak başarısını veya başarısızlık durumunu belirtir.

Örneğin, kullanıcı arayüzü iş parçacığındaki bir etkinlikte güvenlik sağlayıcıyı güncelleyen kod aşağıda verilmiştir. Etkinlik, sağlayıcıyı güncellemek için installIfNeededAsync() çağrısı yapar ve başarı veya başarısızlık bildirimlerini almak için kendisini dinleyici olarak tanımlar. Güvenlik sağlayıcı güncelse veya başarıyla güncellendiyse etkinliğin onProviderInstalled() yöntemi çağrılır ve etkinlik, iletişimin güvenli olduğunu bilir. Öğe sağlayıcı güncellenemiyor. Etkinlik onProviderInstallFailed() yöntemi çağrılır ve etkinlik uygun eylemi gerçekleştirebilir (örneğin, kullanıcıdan Google Play hizmetlerini güncellemesini isteme).

Kotlin

private const val ERROR_DIALOG_REQUEST_CODE = 1

/**
 * Sample activity using {@link ProviderInstaller}.
 */
class MainActivity : Activity(), ProviderInstaller.ProviderInstallListener {

    private var retryProviderInstall: Boolean = false

    // Update the security provider when the activity is created.
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ProviderInstaller.installIfNeededAsync(this, this)
    }

    /**
     * This method is only called if the provider is successfully updated
     * (or is already up to date).
     */
    override fun onProviderInstalled() {
        // Provider is up to date; app can make secure network calls.
    }

    /**
     * This method is called if updating fails. The error code indicates
     * whether the error is recoverable.
     */
    override fun onProviderInstallFailed(errorCode: Int, recoveryIntent: Intent) {
        GoogleApiAvailability.getInstance().apply {
            if (isUserResolvableError(errorCode)) {
                // Recoverable error. Show a dialog prompting the user to
                // install/update/enable Google Play services.
                showErrorDialogFragment(this@MainActivity, errorCode, ERROR_DIALOG_REQUEST_CODE) {
                    // The user chose not to take the recovery action.
                    onProviderInstallerNotAvailable()
                }
            } else {
                onProviderInstallerNotAvailable()
            }
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int,
                                  data: Intent) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == ERROR_DIALOG_REQUEST_CODE) {
            // Adding a fragment via GoogleApiAvailability.showErrorDialogFragment
            // before the instance state is restored throws an error. So instead,
            // set a flag here, which causes the fragment to delay until
            // onPostResume.
            retryProviderInstall = true
        }
    }

    /**
     * On resume, check whether a flag indicates that the provider needs to be
     * reinstalled.
     */
    override fun onPostResume() {
        super.onPostResume()
        if (retryProviderInstall) {
            // It's safe to retry installation.
            ProviderInstaller.installIfNeededAsync(this, this)
        }
        retryProviderInstall = false
    }

    private fun onProviderInstallerNotAvailable() {
        // This is reached if the provider can't be updated for some reason.
        // App should consider all HTTP communication to be vulnerable and take
        // appropriate action.
    }
}

Java

/**
 * Sample activity using {@link ProviderInstaller}.
 */
public class MainActivity extends Activity
    implements ProviderInstaller.ProviderInstallListener {

  private static final int ERROR_DIALOG_REQUEST_CODE = 1;

  private boolean retryProviderInstall;

  // Update the security provider when the activity is created.
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ProviderInstaller.installIfNeededAsync(this, this);
  }

  /**
   * This method is only called if the provider is successfully updated
   * (or is already up to date).
   */
  @Override
  protected void onProviderInstalled() {
    // Provider is up to date; app can make secure network calls.
  }

  /**
   * This method is called if updating fails. The error code indicates
   * whether the error is recoverable.
   */
  @Override
  protected void onProviderInstallFailed(int errorCode, Intent recoveryIntent) {
    GoogleApiAvailability availability = GoogleApiAvailability.getInstance();
    if (availability.isUserRecoverableError(errorCode)) {
      // Recoverable error. Show a dialog prompting the user to
      // install/update/enable Google Play services.
      availability.showErrorDialogFragment(
          this,
          errorCode,
          ERROR_DIALOG_REQUEST_CODE,
          new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
              // The user chose not to take the recovery action.
              onProviderInstallerNotAvailable();
            }
          });
    } else {
      // Google Play services isn't available.
      onProviderInstallerNotAvailable();
    }
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode,
      Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == ERROR_DIALOG_REQUEST_CODE) {
      // Adding a fragment via GoogleApiAvailability.showErrorDialogFragment
      // before the instance state is restored throws an error. So instead,
      // set a flag here, which causes the fragment to delay until
      // onPostResume.
      retryProviderInstall = true;
    }
  }

  /**
  * On resume, check whether a flag indicates that the provider needs to be
  * reinstalled.
  */
  @Override
  protected void onPostResume() {
    super.onPostResume();
    if (retryProviderInstall) {
      // It's safe to retry installation.
      ProviderInstaller.installIfNeededAsync(this, this);
    }
    retryProviderInstall = false;
  }

  private void onProviderInstallerNotAvailable() {
    // This is reached if the provider can't be updated for some reason.
    // App should consider all HTTP communication to be vulnerable and take
    // appropriate action.
  }
}