As permissões de Android em defesa e ataque

By | 04.08.2017

Todos os dias nos aparelhos móveis revelam vulnerabilidades que podem ser exploradas por intrusos. Eles podem enviar SMS para um número pago, eles podem coletar um grande banco de dados de contatos e vendê-lo, ou podem comprometer uma pessoa em particular. A exploração bem sucedida de uma vulnerabilidade geralmente envolve uma série de condições. Mas você pode fazer de outro jeito também! Passa ao usuário o aplicativo certo (brinquedo com pássaros) no manifest do que seria gravada uma lista de informações interessantes sobre o dispositivo. Neste artigo, veremos maneiras de obter e armazenar informações importantes de um aparelho de Android.

A arquitetura do sistema Android é construída de forma que permite trocar diferentes tipos de informações entre aplicativos. Um aplicativo que opera com mapas, precisa de um local, um gravador de voz precisa acesso a um microfone. Assim, tudo é claro e transparente.

Nós prescrevemos claramente os dados ou recursos necessários no manifest de aplicativo e obtenha-os ao instalar. Ninguém não engana ninguém, tudo é voluntário. Mas o problema é que os usuários são extremamente não expertos em tecnologia da informação. Poucas pessoas pensam por que esse gravador de voz requer sua localização ou acesso a SMS. O aplicativo declara todas suas intenções no manifesto e seria estranho esperar dele outro comportamento.

Bem antes de todas as revelações conhecidas, eu já percebi que um brinquedo com pássaros irritados (Angry Birds) no seu dispositivo é um espião, pois quer ler o ID do dispositivo e os dados sobre chamadas além das outras coisas. A simples pergunta: “Você precisa desses dados?” revela as verdadeiras intenções dos seus criadores.

O usuário quando instala aplicativo fica escolhendo “ou permitir tudo o que ele precisa, ou você vai ficar sem aplicativo”. Apenas alguns vão para market procurando outro aplicativo com mesma funcionalidade. Mas com pouco pedidos (pode não haver análogo absoluto) de modo que os usuários rapidamente tenham o hábito de pressionar “sim-sim-sim” para todas as perguntas .

Concordo, é fácil acostumar-se quando durante muitos anos de vida offline, os usuários desenvolveram um reflexo para assinar automaticamente contratos de muitas páginas de acordo com o princípio “bem, eu assino, provavelmente não há nada de errado nisso mas tem apenas uma saída – ou eu assino agora, ou não entendi por que ele veio”.

Após a instalação o aplicativo de espião nem precisa ser iniciado pois pode ter um mecanismo para receber mensagens de transmissão (BroadcastReceiver), que ao receber uma mensagem do sistema iniciará um serviço de coleta.

Se a gente retira todas as pemissões de aplicativo, o sistema simplesmente vai passar para aplicativo valores vazios para evitar a queda do programa. Você pode enganar o aplicativo informando os dados falsos (a localização do Pólo Norte) ou apenas zeros. Por exemplo, um aplicativo pode solicitar uma lista de contatos do dispositivo, e o desenvolvedor assume que lista pode estar vazia (o aparelho completamente novo). Não há nada para suspeitar porque os dados estão seguros e o aplicativo não deu queda.

Tais truques foram úteis até versão de Android 6.0 Marshmallow. Neste versão apareceu um novo mecanismo para operar com permissões.

Ele permite que você habilita e desabilita permissões enquanto o próprio aplicativo está sendo executado. Para a compatibilidade com versões anteriores de aplicativos antigos (ou seja o valor de targetSdkVersion é menor do que 23), funciona mecanismo antigo para solicitar permissões de instalação. Os aplicativos atualizados devem solicitar permissão no processo. Nas configurações do aplicativo podemos ver para onde aplicativo tem acesso e, se precisa, retirar esse acesso.

Considere a operação desse mecanismo num aparelho com versão do Android 6.0.

Vamos instalar o Angry Birds mas antes de primeiro lançamento vamos tirar todas as permissões. Ao solicitar permissões quando instala de Google Play, vemos que o targetSdkVersion do aplicativo é inferior a 23. A tela de configurações nós informa sobre algumas interesses exageradas de criadores do aplicativo.

Que tal diminuir um pouco?

Depois de desabilitar permissões eu comecei jogar e percebi que não impedi o funcionamento normal do jogo. Aparentemente, o serviço de coleta de dados em segundo plano não afeta a interface principal do jogo.

Agora vamos ver nosso trabalho com aplicativo Skype atualizado. Aqui nós temos uma parte de manifest do um aplicativo “semelhante”. A lista de permissões e requisitos do manifest do aplicativo impressiona:

<uses-feature
  android:name="android.hardware.camera"
  android:required="false" />
<uses-feature
  android:name="android.hardware.camera.autofocus"
  android:required="false" />
<uses-feature
  android:name="android.hardware.telephony"
  android:required="false" />
<uses-feature
  android:name="android.hardware.microphone"
  android:required="false" />
<uses-feature
  android:name="android.hardware.bluetooth"
  android:required="false" />
<uses-feature
  android:name="android.hardware.wifi"
  android:required="false" />
<uses-feature
  android:name="android.hardware.location"
  android:required="false" />
<uses-feature
  android:name="android.hardware.location.network"
  android:required="false" />
<uses-feature
  android:name="android.hardware.location.gps"
  android:required="false" />

<permission
  android:name="com.skype.android.permission.READ_CONTACTS"
  android:permissionGroup="android.permission-group.PERSONAL_INFO"
  android:protectionLevel="normal" />
<permission
  android:name="com.skype.android.permission.WRITE_CONTACTS"
  android:protectionLevel="signature" />

<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />

<permission
  android:name="com.skype.raider.permission.C2D_MESSAGE"
  android:protectionLevel="signature" />

<uses-permission android:name="com.skype.raider.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<permission
  android:name="com.skype.raider.permission.RECEIVE_ADM_MESSAGE"
  android:protectionLevel="signature" />

<uses-permission android:name="com.skype.raider.permission.RECEIVE_ADM_MESSAGE" />
<uses-permission android:name="com.amazon.device.messaging.permission.RECEIVE" />
<uses-permission android:name="com.nokia.pushnotifications.permission.RECEIVE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />

<permission
  android:name="com.skype.permission.ACCOUNT"
  android:protectionLevel="signature" />
<uses-permission android:name="com.skype.permission.ACCOUNT" />
<uses-feature
  android:glEsVersion="0x20000"
  android:required="true" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<uses-permission android:name="com.sec.android.provider.badge.permission.READ" />
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE" />
<uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.htc.launcher.permission.UPDATE_SHORTCUT" />
<uses-permission android:name="com.sonyericsson.home.permission.BROADCAST_BADGE" />
<uses-permission android:name="com.anddoes.launcher.permission.UPDATE_COUNT" />
<uses-permission android:name="com.majeur.launcher.permission.UPDATE_BADGE" />

Se os usuários pudesse ver isso…

Se nós queremos manter em segredo pelo menos uma pequena parte da nossa vida privada, resta confiar só no sistema operacional. Vamos considerar o processo de instalação do aplicativo. Ao instalar do market nenhuma janela de diálogo não é exibida, assim todas as permissões aplicativo vai pedir depois. Vamos verificar as configurações.

Ligamos aplicativo. Temos as 7 solicitações seguidas.

Um por um rejeitamos todos os pedidos, e o Skype se transforma em um bate-papo de internet :).

Pare, eu diz: “bate-papo online”? E por que ele não pediu permissão para acessar a internet? Isso tudo porque as permissões são divididas em dois grupos: ordinário e perigoso. Assim agora deve solicitar o segundo. Uma lista de solitações normais pode ser encontrada aqui. E  aqui são permissões perigosas (e seus grupos). Para criar solicitação de permissão existem materiais específicos: exemplos para o uso de solicitações de permissões, recomendações para acessar permissões e uma lista completa de permissões.

Mais ou menos acabamos com teoria e agora vamos passar para prática.

Entramos na lista de contatos (de jeito legal)

Enriquecido com este novo conhecimento, vamos criar um pequeno aplicativo que vai ler dados sobre contatos do usuário através de solicitações de interface e serviço. Como foi revelado recentemente, muitas vezes alguns aplicativos gostam de ler esses dados (não é surpreendente, talvez de repente algo mudou e os criadores de “bons” aplicativos não sabem).

Clique no botão, verificamos a versão do sistema operacional e se for 23 e superior, fazemos um pedido de direitos:

public void setRequestReadContacts(View view) {
  // Verifique as permissões já dadas
  if (hasSelfPermission(this, Manifest.permission.READ_CONTACTS)) {
    // A permissão é que mostramos contatos
    showContacts();
  } else {
    // A permissão não está presente, enviamos um pedido
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS);
    }
  }
}

Após o diálogo no método onRequestPermissionsResult, você precisa processar a resposta:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
  if (requestCode == REQUEST_READ_CONTACTS) {
    if (verifyAllPermissions(grantResults)) {
    // Permission is, we show contacts
    showContacts();
    } else {
      Toast.makeText(this, "Permission REQUEST_READ_CONTACTS was not obtained", Toast.LENGTH_SHORT).show();
    }
  } else {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }
}

Leia os contatos numa linha com passo para outra nova linha:

private String readContacts() {
  Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
  String names = "";
  while (phones.moveToNext()) {
    names = names + phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)) + "\n";
  }
  phones.close();
  return names;
}

Mostramos contatos na janela mas quando você clica na janela ela desaparece:

public void createWindow(String contacts) {
  LayoutInflater layoutInflater
    = (LayoutInflater) getBaseContext()
    .getSystemService(LAYOUT_INFLATER_SERVICE);
  View popupView = layoutInflater.inflate(R.layout.popup_window, null);
  if (mPopupWindow != null)
    mPopupWindow.dismiss();
  mPopupWindow = new PopupWindow(
    popupView,
    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    mPopupWindow.setAnimationStyle(android.R.style.Animation_Dialog);
  LinearLayout ll = (LinearLayout) popupView.findViewById(R.id.PopUp);
  TextView tv_message = (TextView) popupView.findViewById(R.id.tv_message);
  tv_message.setText(contacts);
  ll.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      mPopupWindow.dismiss();
    }
  });
  mPopupWindow.showAtLocation(mMainLayout, Gravity.CENTER, 0, (int) (mSidePopup * 0.3));
}

Aqui o resultado da leitura de contatos:

Entramos na lista de contatos (de jeito ilegal)

Agora faremos o mesmo mas pelo serviço como deveria fazer um aplicativo ruim. O serviço não mostrará nenhum pedido mas tentará somente ler os contatos direto.

Vamos iniciar o serviço no evento de conexão ao Wi-Fi.

Código de serviço:

public class ReadContactsService extends Service {
  public ReadContactsService() {
  }

  @Override
  public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    throw new UnsupportedOperationException("Not yet implemented");
  }

  private String readContacts() {
    Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
    String names = "";
    while (phones.moveToNext()) {
      names = names + phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)) + "\n";
    }
    phones.close();
    return names;
  }

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(getBaseContext(), readContacts(), Toast.LENGTH_SHORT).show();
    return START_STICKY;
  }
}

Código do receptor:

public class WifiReceiver extends BroadcastReceiver {
  public WifiReceiver() {
  }

  @Override
  public void onReceive(Context context, Intent intent) {
    NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    if (info != null && info.isConnected()) {
      // Doing our work
      Toast.makeText(context, "Connected", Toast.LENGTH_LONG).show();
      Intent myIntent=new Intent(context,ReadContactsService.class);
      context.startService(myIntent);
    }
  }
}

Se o aplicativo tem permissões, o serviço vai mostrar Toas de mensagem com lista de contatos. Se não for correto, isso causará um erro com a mensagem. Agora examine o comportamento do aplicativo se você definiu o targetSdkVersion inferior de 23.

Como padrão, o aplicativo recebe direitos e tudo vai funcionar corretamente sem pedidos. Depois de desabilitar os direitos nas configurações do aplicativo, a lista de contatos vai ficar vazia. Não recebemos nenhum erro mas contatos também. Assim, sem o nosso conhecimento aplicativo receberão informação irrelevante.

Conclusão

A nova versão do Android inclui configurações de permissões mais confiáveis e flexíveis para aplicativos. Podemos dizer que na nova versão nossos dados são protegidos de forma mais eficiente mas isso não significa que você pode agora concordar cegamente com todas as propostas provenientes das janelas pop-up. Seja atento!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *