Возможность показа произвольного сообщения через Intent в BroadcastReceiver
![]() |
Критичность: СРЕДНИЙ |
| Способ обнаружения: IAST |
Описание
Дефект возникает, когда экспортируемый BroadcastReceiver принимает данные из входящего Intent и отображает их пользователю (например, через Toast, уведомление или диалог) без проверки источника и содержимого. Поскольку экспортируемый приёмник может быть вызван любым приложением на устройстве, злоумышленник получает возможность показывать пользователю произвольный текст от имени доверенного приложения.
Пример уязвимого кода:
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// текст полностью контролируется отправителем broadcast
String message = intent.getStringExtra("message");
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
}
<receiver android:name=".MessageReceiver" android:exported="true">
<intent-filter>
<action android:name="com.example.SHOW_MESSAGE"/>
</intent-filter>
</receiver>
Любое приложение может отправить:
Intent i = new Intent("com.example.SHOW_MESSAGE");
i.setPackage("com.example.victim");
i.putExtra("message", "Ваш аккаунт заблокирован. Перейдите по ссылке ...");
sendBroadcast(i);
Проблема
- Фишинг и социальная инженерия — злоумышленник показывает пользователю поддельные уведомления (о блокировке счёта, необходимости подтвердить операцию и т. п.) от имени доверенного приложения, склоняя к опасным действиям.
- Подмена доверия к интерфейсу — пользователь воспринимает сообщение как легитимное, поскольку оно отображается внутри известного приложения.
- Возможная инъекция форматирования/разметки — при использовании сообщения в более сложных UI-элементах непроверенный текст может приводить к дополнительным проблемам отображения.
Рекомендации
-
Не экспортируйте приёмник без необходимости: укажите
android:exported="false", если broadcast предназначен только для внутреннего использования. -
Защитите приёмник разрешением (
permissionс уровнемsignature), чтобы его могли вызывать только доверенные компоненты: -
Для внутренних сообщений используйте observable-механизмы (LiveData / Kotlin
Flow) или регистрируйте приёмник сContext.RECEIVER_NOT_EXPORTED(API 33+).LocalBroadcastManagerдля этого использовать не стоит — он deprecated с 2019 года. -
Проверяйте источник и валидируйте содержимое входящего
Intent: не отображайте пользователю текст, пришедший из недоверенного источника, без фильтрации. -
Не передавайте текст сообщения через extras внешнего Intent — используйте предопределённые на стороне приложения шаблоны/идентификаторы сообщений вместо произвольных строк.
