Broadcast receivers não seguros

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

Visão geral

Broadcast receivers implementados de forma inadequada 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 instâncias em que o broadcast receiver é exportado sem intenção, seja definindo android:exported="true" no AndroidManifest ou criando um broadcast receiver de forma programática, o que torna o receptor público por padrão. Se o receptor não tiver filtros de intent, o valor padrão será "false". Se ele tiver pelo menos um filtro de intent, o valor padrão de android:exported será "true".

Os broadcast receivers exportados intencionalmente sem controle de acesso adequado podem ser usados indevidamente se o desenvolvedor não tiver a intenção de que ele seja chamado por todos os aplicativos.

Impacto

Os broadcast receivers implementados de forma insegura podem ser usados indevidamente por um invasor para ganhar acesso não autorizado e executar comportamentos no aplicativo que o desenvolvedor não pretendia expor a terceiros.

Mitigações

Evitar o problema

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

Se você usou broadcast receivers para fins internos do app (por exemplo, notificação de conclusão de evento), reestruture o código para transmitir um callback que seja 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

Registre apenas 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