Ошибка в приложении при работе через IPC
![]() |
Критичность: СРЕДНИЙ |
| Способ обнаружения: IAST |
Описание
Операционная система Android имеет богатое межпроцессное взаимодействие (IPC), построенное на базе Intent. Приложение может получать данные от других приложений или операционной системы через экспортированные компоненты. Экспортированность компонента в современных версиях Android определяется наличием атрибута exported="true" в теге объявленного компонента в файле AndroidManifest.xml.
<manifest
<application
<activity
android:name=".DashboardActivity"
android:exported="true">
</activity>
</application>
</manifest>
Если компонент экспортирован, он может принимать Intent'ы извне (от других приложений). Помимо запуска такого компонента сторонним приложением, в объекте Intent могу передаваться дополнительные данные в виде пар ключ-значение и/или URI. В качестве значений могут передаваться примитивы, строки, массивы, а также целые объекты в Parcelable. Переданные данные извлекаются на стороне целевого приложения и зачастую не валидируются и не санитизируются на наличие некорректных или вредоносных значений. В результате возможны как непосредственные атаки на пользователя/приложение, так и просто ошибки в работе приложения вплоть до его аварийного завершения.
Пример создания Intent для последующего запуска DashboardActivity:
class DashboardActivity :
AppCompatActivity(R.layout.activity_dashboard) {
companion object {
private const val KEY_INFO_1 = "KEY_INFO_1"
private const val KEY_INFO_2 = "KEY_INFO_2"
fun newIntent(
context: Context,
firstInfo: FirstInfo,
secondInfo: SecondInfo,
) = Intent(context, DashboardActivity::class.java)
.putExtra(KEY_INFO_1, firstInfo)
.putExtra(KEY_INFO_2, secondInfo)
}
startActivity(
DashboardActivity.newIntent(
context = context,
firstInfo = firstInfo,
secondInfo = secondInfo,
)
)
Пример получения данных из Intent:
private val firstInfo by requireExtra<FirstInfo>(KEY_INFO_1)
private val secondInfo by requireExtra<SecondInfo>(KEY_INFO_2)
inline fun <reified T> AppCompatActivity.requireExtra(key: String): Lazy<T> {
return lazy { intent?.extras?.get(key) as T }
}
Проблема
В случае, если приложение аварийно завершается от пришедшего Intent'а, сторонее приложение может периодически посылать такие Intent'ы, сделав невозможным использование целевого приложения. Кроме того, ошибка в приложении при парсинге или прямом использовании данных из Intent'а говорит о наличии потенциальной уязвимости в нем. Злоумышленник может подобрать такой формат данных, чтобы обойти существующие проверки (если они вобще есть), и тогда просто ошибка в приложении превратится в серьезную эксплуатируемую уязвимость, позволяющую совершить атаку на данные пользователя/приложения.
Рекомендации
Следует рассматривать любые приходящие извне данные как вредоносные и соответствующим образом их обрабатывать. Обработку данных, если это возможно, лучше строить на «белых списках» в остальных случаях предусмотреть проверку семантики, синтаксиса и авторизации при использовании пришедших из внешних источников данных.
Пример обработки входящих данных из Intent:
private val deeplinkEvent by requireExtra<DeeplinkEvent?>(KEY_DEEPLINK_EVENT)
if (deeplinkEvent != null && deeplinkEvent is DeeplinkEvent.OpenMyScreenEvent) {
showMyScreen()
}
