Skip to content

Most visited

Recently visited

navigation

Atualizar seu provedor de segurança para proteger-se contra explorações de SSL

O Android depende de um Provider de segurança para oferecer comunicações de rede seguras. No entanto, de tempos em tempos, são encontradas vulnerabilidades no provedor de segurança padrão. Para proteger-se contra essas vulnerabilidades, o Google Play Services oferece uma maneira de atualizar automaticamente o provedor de segurança de um dispositivo, proporcionando uma proteção contra explorações conhecidas. Ao chamar os métodos do Google Play Services, sei aplicativo pode garantir que ele seja executado em um dispositivo que tenha as últimas atualizações para protegê-lo contra explorações conhecidas.

Por exemplo, foi descoberta uma vulnerabilidade no OpenSSL (CVE-2014-0224) que pode deixar aplicativos abertos a um ataque de interceptação que descriptografa tráfego seguro sem o conhecimento de qualquer um dos lados. Com o Google Play Services versão 5.0, uma correção é disponibilizada, mas os aplicativos devem garantir que ela seja instalada. Ao usar os métodos do Google Play Services, seu aplicativo pode garantir que ele seja executado em um dispositivo protegido contra esse ataque.

Atenção: Atualizar o Provider de segurança de um dispositivo não atualiza o android.net.SSLCertificateSocketFactory. Em vez de usar essa classe, incentivamos os desenvolvedores de aplicativos a usar métodos de alto nível para interagir com criptografia. A maioria dos aplicativos usam APIs como a HttpsURLConnection sem precisar definir um TrustManager personalizado ou criar um SSLCertificateSocketFactory.

Aplicação de patch no provedor de segurança com ProviderInstaller

Para atualizar o provedor de segurança de um dispositivo, use a classe ProviderInstaller. Você pode verificar se o provedor de segurança está atualizado (e, se necessário, atualizá-lo) chamando o método installIfNeeded() (ou installIfNeededAsync()) dessa classe.

Quando você chama installIfNeeded(), o ProviderInstaller faz o seguinte:

O método installIfNeededAsync() se comporta de forma semelhante, mas, em vez de acionar exceções, ele chama o método de retorno de chamada apropriado para indicar um sucesso ou uma falha.

Se installIfNeeded() precisar instalar um novo Provider, esse processo pode durar de 30-50 ms (em dispositivos mais recentes) a 350 ms (em dispositivos mais antigos). Se o provedor de segurança já estiver atualizado, a duração do método é mínima. Para evitar impactos na experiência do usuário:

Aviso: Se o ProviderInstaller não conseguir instalar um Provider atualizado, o provedor de segurança do seu dispositivo poderá estar vulnerável a explorações conhecidas. Seu aplicativo se comportará como se todas as comunicações HTTP estivessem descriptografadas.

Quando o Provider for atualizado, todas as chamadas para APIs de segurança (incluindo APIs SSL) serão roteadas por ele. (No entanto, isso não se aplica ao android.net.SSLCertificateSocketFactory, que permanece vulnerável a explorações como a CVE-2014-0224.)

Aplicação de patch síncrona

A maneira mais simples de aplicar um patch no provedor de segurança é chamar o método síncrono installIfNeeded(). Essa ação é apropriada se a experiência do usuário não for afetada pelo bloqueio de threads enquanto a operação não é concluída.

Por exemplo, veja aqui uma implementação de um adaptador de sincronização que atualiza o provedor de segurança. Como um adaptador de sincronização é executado em segundo plano, não tem problema se o encadeamento for bloqueado enquanto a atualização do provedor de segurança é realizada. O adaptador de sincronização chama installIfNeeded() para atualizar o provedor de segurança. Se o método for retornado normalmente, o adaptador de sincronização saberá que o provedor de segurança está atualizado. Se o método acionar uma exceção, o adaptador de sincronização poderá realizar a ação apropriada (como solicitar que o usuário atualize o Google Play Services).

/**
 * Sample sync adapter using {@link ProviderInstaller}.
 */
public class SyncAdapter extends AbstractThreadedSyncAdapter {

  ...

  // This is called each time a sync is attempted; this is okay, since the
  // overhead is negligible if the security provider is up-to-date.
  @Override
  public void onPerformSync(Account account, Bundle extras, String authority,
      ContentProviderClient provider, SyncResult syncResult) {
    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.
      GooglePlayServicesUtil.showErrorNotification(
          e.getConnectionStatusCode(), getContext());

      // Notify the SyncManager that a soft error occurred.
      syncResult.stats.numIOExceptions++;
      return;

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

      // Notify the SyncManager that a hard error occurred.
      syncResult.stats.numAuthExceptions++;
      return;
    }

    // If this is reached, you know that the provider was already up-to-date,
    // or was successfully updated.
  }
}

Aplicação de patch assíncrona

A atualização do provedor de segurança pode levar até 350 milissegundos (em dispositivos mais antigos). Se você estiver realizando a atualização em um encadeamento que afete diretamente a experiência do usuário, como o encadeamento de IU, não é recomendável realizar uma chamada síncrona para atualizar o provedor, pois isso poderá fazer com que o aplicativo ou o dispositivo congele até que a operação seja concluída. Em vez disso, use o método assíncrono, installIfNeededAsync(). Esse método indica seu sucesso ou falha chamando callbacks.

Por exemplo, apresentamos aqui um código que atualiza o provedor de segurança em uma atividade no encadeamento da IU. A atividade chama installIfNeededAsync() para atualizar o provedor e se designa como ouvinte para receber notificações de sucesso ou falha. Se o provedor de segurança estiver atualizado ou se for atualizado com êxito, o método onProviderInstalled() da atividade será chamado e a atividade saberá que as comunicações estão seguras. Se não for possível atualizar o provedor, o método onProviderInstallFailed() da atividade será chamado e a atividade poderá realizar a ação apropriada (como solicitar que o usuário atualize o Google Play Services).

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

  private static final int ERROR_DIALOG_REQUEST_CODE = 1;

  private boolean mRetryProviderInstall;

  //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) {
    if (GooglePlayServicesUtil.isUserRecoverableError(errorCode)) {
      // Recoverable error. Show a dialog prompting the user to
      // install/update/enable Google Play services.
      GooglePlayServicesUtil.showErrorDialogFragment(
          errorCode,
          this,
          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 is not 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 GooglePlayServicesUtil.showErrorDialogFragment
      // before the instance state is restored throws an error. So instead,
      // set a flag here, which will cause the fragment to delay until
      // onPostResume.
      mRetryProviderInstall = true;
    }
  }

  /**
   * On resume, check to see if we flagged that we need to reinstall the
   * provider.
   */
  @Override
  protected void onPostResume() {
    super.onPostResult();
    if (mRetryProviderInstall) {
      // We can now safely retry installation.
      ProviderInstall.installIfNeededAsync(this, this);
    }
    mRetryProviderInstall = false;
  }

  private void onProviderInstallerNotAvailable() {
    // This is reached if the provider cannot be updated for some reason.
    // App should consider all HTTP communication to be vulnerable, and take
    // appropriate action.
  }
}
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Siga o Google Developers no WeChat

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience. (Dec 2017 Android Platform & Tools Survey)