Перейти к содержанию

Ошибка в приложении при работе через 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()
}

Ссылки

  1. Экспортируемость компонентов

  2. Статьи о IPC

  3. O Intent

К началу