Broadcast receivers non sécurisés

Catégorie OWASP : MASVS-PLATFORM : interaction avec la plate-forme

Présentation

Les broadcast receivers mal implémentés peuvent permettre à un pirate informatique d'envoyer un intent malveillant pour que l'application vulnérable effectue des actions qui ne sont pas destinées aux appelants externes.

La faille fait généralement référence aux cas où le broadcast receiver est exporté par inadvertance, soit en définissant android:exported="true" dans AndroidManifest, soit en créant un broadcast receiver par programmation, ce qui le rend public par défaut. Si le récepteur ne contient aucun filtre d'intent, la valeur par défaut est "false", mais si le récepteur contient au moins un filtre d'intent, la valeur par défaut d'android:exported est "true".

Les broadcast receivers exportés intentionnellement sans contrôle d'accès approprié peuvent être utilisés de manière abusive si le développeur n'a pas l'intention qu'ils soient appelés par toutes les applications.

Impact

Un pirate informatique peut abuser des broadcast receivers implémentés de manière non sécurisée pour obtenir un accès non autorisé à l'exécution d'un comportement dans l'application que le développeur n'avait pas l'intention d'exposer à des tiers.

Stratégies d'atténuation

Éviter complètement le problème

Pour résoudre complètement le dilemme, définissez exported sur false:

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

Utiliser des appels et des rappels

Si vous avez utilisé des broadcast receivers à des fins internes à l'application (par exemple, une notification de fin d'événement), vous pouvez restructurer votre code pour transmettre un rappel qui se déclenchera à la fin de l'événement.

Écouteur de fin d'événement

Kotlin

interface EventCompletionListener {
    fun onEventComplete(data: String)
}

Java

public interface EventCompletionListener {
    public void onEventComplete(String data);
}
Tâche sécurisée

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");
        }
    }
}
Activité principale

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
        // ...
    }
}

Sécuriser les broadcast receivers avec des autorisations

N'enregistrez des récepteurs dynamiques que pour les diffusions protégées (diffusions que seules les applications de niveau système peuvent envoyer) ou avec des autorisations de niveau signature autodéclarées.

Ressources