Broadcast receivers não seguros

Categoria do OWASP: MASVS-PLATFORM - Interação com plataformas

Visão geral

Broadcast receivers implementados incorretamente podem permitir que um invasor envie uma intent maliciosa para fazer com que o aplicativo vulnerável execute ações que não são destinadas a chamadores externos.

A vulnerabilidade geralmente se refere a casos em que o broadcast receiver é exportado acidentalmente, seja definindo android:exported="true" no AndroidManifest ou criando um broadcast receiver de forma programática, o que torna o receiver público por padrão. Se o receptor não tiver filtros de intent, o valor padrão será "false". No entanto, se o receptor tiver pelo menos um filtro de intent, o valor padrão de android:exported será "true".

Os broadcast receivers exportados intencionalmente sem o controle de acesso adequado podem ser abusados se o desenvolvedor não pretendia que eles fossem chamados por todos os apps.

Impacto

Os broadcast receivers implementados de forma não segura podem ser abusados por um invasor para ter acesso não autorizado para executar um comportamento no aplicativo que o desenvolvedor não pretendia expor a terceiros.

Mitigações

Evitar o problema completamente

Para resolver o dilema completamente, defina exported como false:

<receiver android:name=".MyReceiver" android:exported="false">
    <intent-filter>
        <action android:name="com.example.myapp.MY_ACTION" />
    </intent-filter>
</receiver>

Usar chamadas e callbacks

No caso de uso de broadcast receivers para fins internos do app (por exemplo, notificação de conclusão de evento), é possível reestruturar o código para transmitir um callback que seria acionado após a conclusão do evento.

Listener de conclusão de eventos

Kotlin

interface EventCompletionListener {
    fun onEventComplete(data: String)
}

Java

public interface EventCompletionListener {
    public void onEventComplete(String data);
}
Tarefa segura

Kotlin

class SecureTask(private val listener: EventCompletionListener?) {
    fun executeTask() {
        // Do some work...

        // Notify that the event is complete
        listener?.onEventComplete("Some secure data")
    }
}

Java

public class SecureTask {

    final private EventCompletionListener listener;

    public SecureTask(EventCompletionListener listener) {
        this.listener = listener;
    }

    public void executeTask() {
        // Do some work...

        // Notify that the event is complete
        if (listener != null) {
            listener.onEventComplete("Some secure data");
        }
    }
}
Atividade principal

Kotlin

class MainActivity : AppCompatActivity(), EventCompletionListener {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val secureTask = SecureTask(this)
        secureTask.executeTask()
    }

    override fun onEventComplete(data: String) {
        // Handle event completion securely
        // ...
    }
}

Java

public class MainActivity extends AppCompatActivity implements EventCompletionListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SecureTask secureTask = new SecureTask(this);
        secureTask.executeTask();
    }

    @Override
    public void onEventComplete(String data) {
        // Handle event completion securely
        // ...
    }
}

Proteger broadcast receivers com permissões

Só registre receptores dinâmicos para transmissões protegidas (transmissões que só aplicativos no nível do sistema podem enviar) ou com permissões de nível de assinatura autodeclaradas.

Recursos