Filter Provider
Filter Provider — это важнейшее приложение для камер планшетов и смартфонов Samsung. По сути, оно снабжает приложение камеры фильтрами для фотографий, которые вы делаете. Если вы удалите или удалите это приложение по ошибке, то у вас, вероятно, возникнут проблемы с использованием камеры вашего смартфона.
По этой причине важно дважды подумать, прежде чем удалять системные приложения со смартфона Android. В прошлом было важно удалять множество встроенных приложений, но сейчас в этом нет необходимости по разным причинам.
Во-первых, в смартфонах Android становится все больше оперативной памяти, поэтому нет ничего страшного в том, что системные приложения занимают немного памяти. Во-вторых, операционные системы Google теперь ограничивают активность приложений, открытых в фоновом режиме. Тогда как всего несколько лет назад отключение этих системных приложений было необходимо, если вы хотели увеличить время автономной работы.
К счастью, после того, как Google перестал называть новые версии операционной системы Android, они также ввели оптимизацию для приложений, открытых в фоновом режиме. По этим причинам больше нет необходимости удалять системные приложения типа Filter Provider.
Проверено Alberto García Переведено Uptodown Localization Team
Требования (последняя версия)
- Требуется Android 9 или более новая версия
Уязвимости Android приложений. Часть 2

Эта статья является логическим продолжением ранее опубликованной статьи. Для понимания того, что здесь вообще происходит рекомендую прочитать первую часть и иметь хотя-бы базовое представление о написании программ под платформу Android.
Уязвимости компонентов Android
Intent
Я напомню, что Intent — это инструмент запроса действия от одного компонента другим. Например, вызов второго Activity по нажатию кнопки(т.е компонент Button запрашивает через Intent действие в виде переключения Activity). Intent связывает разные компоненты и позволяет им общаться между собой (компонентом может быть что угодно: ImageView, Button, Activity, WebView и т.д)
Проблема Intent заключается в том, что стороннее приложение может перехватить и подменить этот самый Intent для совершения вредоносных действий.
Intent делятся на два типа:
С ними все более или менее понятно, берется один компонент, и напрямую связывается с другим(с фильтром или без)
Пример кода:
Вызов Activity:
Intent intent = new Intent(this, SecondActivity.class);
StartActivity(intent)
Неявные Intent представляют собой передачу данных между компонентом А, и явно не заданным компонентом В. То бишь Intent компонента А может обработать любое приложение, используя Intent Filter. Самый понятный пример, это когда вы открываете какую-то ссылку, и система Android предлагает вам открыть ее браузером на выбор во всплывающем нижнем окне. Кстати, здесь хорошо видна суть Intent фильтров.
Может получиться так, что у вас установлено 5 браузеров, но открыть ссылку может только 4 браузера. Именно это и означает, что у одного из браузеров нет фильтров для открытия этой ссылки.
Т.е ваше приложение ищет соответствие путем сканирования всех Manifest файлов всех приложений, и если ваш Intent фильтр на открытие Activity в другом приложении будет совпадать по значениям с Intent фильтром другого Activity в другом приложении, то это Activity и будет вызвано
Пример кода:
Intent intent = new Intent();
intent.addAction(«CustomAction»);
intent.addCategory(«CustomCategory»);
startActivity(intent);
Тут же стоит сделать небольшое пояснение насчет строк:
intent.addAction(«CustomAction»);
intent.addCategory(«CustomCategory»);
Action — это то действие, которое Intent должен совершить(открыть ссылку, открыть Activity или передать данные)
Так же для дальнейшего понимания:
Data — это данные в формате URI, которыми будет оперировать Intent. Как выглядит блок данных, будет показано позже.
Category — это строка, которая содержит информацию о типе компонента, который обрабатывает Intent.
Extras – пара «ключ-значение», дающая Intentу дополнительную информацию.
Если сразу непонятны некоторые моменты, не волнуйтесь, все это мы еще несколько раз рассмотрим на практике, но самое важное из всего выше, что в общих чертах Intent выглядит как:
Intent = Data + Action + Category
После всего этого возникает главный вопрос:
Что если вредоносное приложение будет использовать точно такой же Intent фильтр с такими же параметрами, как в целевом приложении?
Ответ прост: подмена и перехват данных
Давайте для наглядности создадим два приложения. Первое будет создавать неявный Intent со своим Intent фильтром, а второе приложение этот Intent будет перехватывать.
Первое приложение:

После нажатия кнопки нас перекидывает на второе активити(intentTest) с таким текстом:

Код в MainActivity, которое неявным Intent’ом через action вызывает IntentTest activity
Так же при помощи Extra мы передаем чувствительные данные вместе с Intentом:

Содержимое файла Manifest, где четко видно, что поиск нужного action прописан при помощи строчки в intent-filter:

Примечание: если обратить внимание, то android:name в IntentTest был записан в иной форме(в виде пакета приложения), которая пригодится нам далее
Второе приложение:
Точно так же имеет два активити, одно из них и будет перехватывать данные с первого приложения, путем сопостановки Intent фильтров.
Код EvilAct
Тут идет самая банальная запись данных с Extra внутри Intent на экран телефона:

Код в MainActivity:

Файл манифеста:
И теперь когда я жму на кнопку в первом приложении, выходит вот такой экран из-за сходства фильтров:


Конечно же откроем мы нашим EvilApk:
Тут нас и встречают наши конфиденциальные данные, которые передавались по неявному Intent.

Но возникает еще один резонный вопрос. Видно ли в том же Jadx фильтры Intent?
Ответ: отчетливо.
Т.е если злоумышленник нашел необходимые фильтры, он может написать вредоносную программу, которая будет перехватывать и отсылать конфиденциальные данные
WebView
Для начала давайте разберемся, что из себя в целом представляет WebView.
Наверняка вы часто сталкивались с открытием внутреннего браузера для просмотра веб страничек в приложении. Примером может служить Telegram, который при открытии любой ссылки открывает WebView(встроенный браузер), а не Chrome или Firefox.
Для дальнейшего разбора уязвимостей этого компонента, давайте сначала рассмотрим его работу на примере простого для понимания кода:


Код достаточно прост и не требует пояснений кроме одной важной строчки, где мы включили поддержку js. После такого шага у подкованных в веб уязвимостях читателей возникают интересные мысли насчет xss атак, которые, конечно же, будут.
Вообще, помимо прямых ссылок из интернета в WebView можно также передавать свои страницы, хранимые в памяти устройства. Во время разработки они должны располагаться в папке assets. К ним доступ будет происходить через URI конструкцию, например так: file://android_res/custom_page.html.
Понятное дело, что под словом веб страничка может быть вообще что угодно: картинка, простенькая форма или сложный динамичный сайт с js под капотом.
В чем же заключаются проблемы с WebView?
Вообще, главная проблема WebView — это сама связь с веб приложениями как таковыми, т.к помимо проблем с Intent(в контексте WebView еще поговорим ниже), есть и проблемы, присущие сайтам: веб уязвимости по типу XSS, отсутствие у загружаемого ресурса ssl соединения, mitm атаки и т.д.
Давайте по порядку:
1) Неявные Intent
Вполне логично, что некоторые приложения получает ссылку на открытие внутри приложения через неявный Intent(это присуще приложениям, которые при открытии ссылки со своих крупных сайтов перекидывают вас внутрь приложения)
Тут и вытекают проблемы, на примерах выше мы смогли через одинаковый Intent фильтр перехватить данные, но что если их перезаписать?
Правильно, мы сможем вызвать банальную XSS атаку, если вредоносное приложение имеет тот же Intent фильтр и если мы сможем перезаписать данные ссылки
2) Проблемы с внутренними файлами
Выше было сказано, что webview может рисовать локальные файлы. Но что если вместо локального файла мы сможем подать на вход какой-то другой, конфиденциальный путь?
Допустим, в коде есть такая строка:
webView.loadUrl(‘’file://android_res/profile.html’’ + name);
А теперь давайте подумаем, что если вместо name = John мы напишем:
name = «/../../../../../sdcard/Downloads/Photos/1.jpg»
Верно, наши строки сконкатенируются и мы получим изображение 1.jpg.
Но как это должно делать вредоносное приложение, если у него нет прямого доступа на изменение кода легитимной программы?
Тут на помощь приходят неявные Intent. В первой половине статьи мы перехватили конфиденциальные данные, которыми могут оказаться и те данные, которые впоследствии и будут отрисовываться при помощи WebView. Опять же, все зависит от конкретного приложения, но если есть данные, которые вредоносное приложение может явно контролировать, стоит обратить внимание на WebView и его параметры.
3) Deep Links
Давайте представим, что у нас есть специальное приложение для работы с нашим крупным веб-ресурсом(например, соц сеть) и мы делаем приложение, которое позволяет пользователю анализировать активность на своей странице
Опустим моменты с подробной реализацией и задумаемся глобально. Наверняка url адрес нашего профиля будет примерно такой:
https://my-social/profiles?user=codebyschool
И давайте представим, что наше приложение посредством WebView рисует красивую аналитику профиля, но проблема заключается в том, что ссылки для разных пользователей разные, и писать колоссальное количество строк кода со всеми ссылками, чтобы юзер имел возможность открыть ссылку именно через наше приложение — это довольно глупо.
Т.е нам нужно решить две проблемы:
- Открытие подобного шаблона ссылки из любого приложения нашим приложением
- Оптимизировать это под каждого пользователя
Тут нам на помощь приходят deep links, которые андроид приложение будет разбивать на части, вытаскивать нужную информацию и манипулировать с данными
Логично, что для открытия подобных ссылок из других приложений нашей программой, мы должны написать неявный Intent, который будет запускаться, когда клик по ссылке будет осуществлен.
А теперь давайте подумаем. У нас есть приложение, которое открывает шаблонизированные ссылки, вытаскивая и обрабатывая оттуда какие-то данные.
Например, у нас есть приложение, которое работает со ссылками вида:
http://my-site.com/rename-user?user=John
И изменяет при работе с данными в параметре user введенное в приложении имя пользователя, после отображая новый профиль с новым именем в WebView.
А теперь давайте подумаем, что если мы вытащили путем обратного инжиниринга этот url адрес, и теперь просто создадим веб страницу со ссылкой выше, по которой кликнет пользователь?
Естественно, что Intent фильтр сразу заметит этот диплинк и обработает его при запуске приложения. Значит, мы удаленно поменяем имя пользователя всего лишь по одной простой ссылке, которую мы вытащили из кода.
Конечно, ситуации отличаются, но если вы будете тестировать приложение, ни в коем случае не упускайте мелькающие в коде диплинки, ведь они могут стать очередным вектором для атак.
Broadcast receivers
Часто приложению нужно получать информацию от системы или от других приложений. Например, если у вас приложение, которое анализирует использование батареи, т.е вам постоянно нужно получать заряд батареи. Если же у вас приложение, которое при регистрации запрашивает код с смс, вам нужно каким-то образом получить уведомление о приходе смс на указанный номер.
Согласитесь, постоянно обращаться к андроиду и спрашивать у операционной системы заряд батареи — это достаточно странно.
Именно поэтому и придумали Broadcast receiver(широковещательный приемник)
Этот компонент постоянно «слушает» устройство и выдает вам то, что вы ждете от системы или других приложений.
Т.е у вашего приложения есть специальный приемник, который ловит запросы от системы или приложений. Или же у вас есть специальный формат широковещательных обращений, которые будут идти на вход к чужим приемникам.
Есть два вида broadcast receiver:
- Явный. В нем мы явно указываем названия приложений, которые будут получать наши широковещательные сообщения.
- Неявный. При таком объявлении уведомления будут получать все приложения. Чтобы принимать такие сообщения нужно прописать в Intent фильтр необходимые настройки.
Какие проблемы есть у приемников?
Представьте, что широковещательное сообщение по всему устройству рассылает вредоносное приложение, у которого стоят те же фильтры, что и у целевого приложения.
Да, т.к и этот компонент работает через Intent, мы можем менять и вставлять данные на лету, как и в первом пункте про Intent.
Notification Service
Наверняка вы часто сталкивались с push уведомлениями от различных приложений. Они и реализуются при помощи Notification Service.
Наше приложение по нажатию кнопки будет выводить уведомление, при клике на которое нас перебросит на неявно вызванное Activity с надписью success. Неявно вызванное Activity в связке с Notification может использоваться, если у нас будет два приложения, которые смогут открывать одинаковые уведомления. Например, неофициальные клиенты каких-либо мессенджеров или соц.сетей




Если вчитаться в код, то никакого Notification сервиса здесь нет, но давайте подумаем, что если мы создадим второе приложение, которое будет иметь разрешение на прочтение всех уведомлений с устройства?
Да, такие приложения бывают, и даже легитимные приложения зачастую читают уведомления в смс, чтобы, например, автоматически вставить код, подтверждающий при регистрации номер телефона.
Делается такой перехват при помощи сервиса Notification Listener Service, и в интернете очень много его реализаций. Например, такой сервис, примеры кода которого очень легко найти, может подменять уведомления от того же WhatsApp, даже была ситуация, когда любое приложение, имеющее доступ к чтению всех уведомлений, могло перехватить текст сообщения, отправленного через Gmail, а как мы с вами знаем, некоторые сервисы могут отправлять пароли при регистрации на почту.
Content provider
Представьте, что ваше приложение хранит какие-то данные(банально, базу данных) и вы хотите делиться ими, полностью не давая доступ к тем или иным данным в общем объеме, тут и приходит на помощь content provider, который помогает организовать передачу данных от одного приложения к другим.
В content provider все данные извлекаются и записываются при помощи специально настроенных URI строк(они похожи на строки, которые мы рассмотрели в пункте про WebView)
Например, мы хотим получить через Content Provider список пользователей в базе данных SQLite, строка примет такой вид:
content://com.android.contentapp.userprovider/users
Т.е по сути мы обращаемся к базе данных и извлекаем строки, но этот запрос, записанный в форме content provider будет записан в такой простой форме.
А теперь давайте представим, что наш провайдер может работать с абсолютно любым приложением на устройстве(как, например, системные приложения с контактами).
Если это так, то мы можем самостоятельно вписывать и извлекать значения из той же базы данных. Ничего не напоминает?
Правильно, небезопасная работа провайдера с абсолютно любым приложением может привести к Sql инъекции, которая может извлекать данные о пользователях, которые работали в приложении или иную информацию, которая была записана в таблице или файлах, к которым был прикреплен контент провайдер.
Зачастую разработчики хардкодят(пишут открытым текстом) URI схему контент провайдера. Вкупе с анализом файла манифеста, где может быть установлен легко читаемый Intent фильтр или exported: «true» значение, такой небезопасный код может привести к тому, что вредоносное приложение сможет записывать свои данные в таблицу другого приложения, просто имея нужные данные для провайдера. Более того, давно есть инструмент drozer, который всего одной строкой может извлечь или записать данные в выбранный контент провайдер
Заключение
Андроид приложения, как и любые другие приложения под различные системы имеют уязвимости. И если стоит цель найти эти самые уязвимости, стоит досконально изучить код и работу архитектуры андроид. Андроид приложения в целом являются очень громоздкими, поэтому разработчик банально для быстроты написания кода может ставить exported:«true» и забывать закрывать доступ к компонентам приложения, даже не осознавая, к чему это может привести.
Android Manifest
Каждый Android-проект содержит файл AndroidManifest.xml.
Android manifest — файл, в котором содержится вся самая важная информация о нашем приложении, которую вы же и описываете.
Манифест нужен чтобы:
- Задавать имя пакета Java для приложения. Это имя пакета служит уникальным идентификатором приложения.
- Описать компоненты приложения — activity, service, broadcast receiver и provider, из которых состоит приложение. Он содержит имена классов, которые реализуют каждый компонент, и публикует их возможности (указывает, например, какие сообщения Intent они могут принимать).
- Определить, в каких процессах будут размещаться компоненты приложения.
- Объявить, какие разрешения должны быть выданы приложению, чтобы оно могло получить доступ к защищенным частям API-интерфейса и взаимодействовать с другими приложениями.
- Объявить разрешения, требуемые для взаимодействия с компонентами данного приложения.
- Объявить минимальный уровень API-интерфейса Android, который требуется приложению.
- Содержать список библиотек, с которыми должно быть связано приложение.
Обязательными являются только элементы и . Они должны присутствовать в файле манифеста, при этом указать их можно только один раз. Большинство других элементов необязательны, а также их можно указывать по нескольку раз. При этом элементы, находящиеся на одном уровне могут располагаться в любом порядке. Также элементы могут содержать в себе другие элементы или атрибуты. Формально все атрибуты являются необязательными. Однако некоторые их них указывать необходимо, чтобы файл мог выполнять свое предназначение. Имена всех атрибутов должны начинаться с префикса android:
Структура манифеста:
Рассмотрим подробно каждый из этих элементов.
Элемент
Позволяет запрашивать у системы разрешения, которые нужны приложению для доступа к различным функциям. Это делается с помощью единственного атрибута android:name, в параметры которого нужно передать имя разрешения.
Элемент
Объявляет разрешение, которое может использоваться для ограничения доступа к определенным компонентам или функциям этого или других приложений.
Элемент
Этот элемент объявляет базовое имя дерева разрешений. Приложение получает права собственности на все разрешения в дереве. Оно может динамически добавлять новые разрешения для дерева, вызывая PackageManager.addPermission().
Элемент
Объявляет имя группы для набора разрешений. Отдельные разрешения присоединяются к группе через атрибут android:permissionGroup элемента .
Элемент
Объявляет класс Instrumentation, который позволяет отслеживать взаимодействие приложения с системой.
Элемент
Позволяет указать совместимость с одной или несколькими версиями Android через указание уровня API.
Элемент
Указывает, какие аппаратные и программные функции требуются приложению.
Элемент
Объявляет определённый функционал, используемый приложением. Цель объявления этого элемента — информировать любой внешний объект о наборе аппаратных и программных функций, от которых зависит приложение. Элемент предлагает атрибут android:required, который указывает, требуется ли приложению функционал, без которого он не сможет работать.
Элемент
Позволяет указать размеры экрана, поддерживаемые вашим приложением, и включить режим совместимости с экраном, большим, чем приложение поддерживает.
Элемент
Указывает конфигурацию экрана, с которой приложение совместимо.
Элемент
Объявляет одну GL текстуру сжатия, поддерживаемую приложением.
Элемент
Объявляется Activity, которая реализует часть визуального пользовательского интерфейса приложения.
Элемент
Указывает типы интентов, на которые может реагировать активность, сервис и тд. Фильтр интентов объявляет возможности своего родительского компонента, а также открывает интентам нужного типа доступ к компоненту и отфильтровывает те, которые не нужны.
Элемент
Добавляет действие в фильтр намерений. Элемент должен содержать как минимум один элемент . Если он не содержит никаких действий, интенты не пройдут через фильтр.
Элемент
Добавляет название категории в фильтр намерений.
Элемент
Добавляет спецификацию данных в фильтр намерений. Спецификация может быть только android:mimeType, URI или оба вместе.
Элемент
Это псевдоним для активности, указанной в атрибуте android:targetActivity. Активность должна быть в том же приложении, что и псевдоним, и должна быть объявлена в манифесте перед псевдонимом.
Элемент
Объявляет сервис (подкласс Service) как один из компонентов приложения. В отличие от активности, сервис не имеет визуального пользовательского интерфейса. Сервисы используются для реализации длительных фоновых операций или крупного API, который может быть вызван другими приложениями.
Элемент
Объявляет BroadcastReceiver как один из компонентов приложения.Они позволяют приложению получать интенты, которые посылаются системой или другими приложениями, даже если другие компоненты приложения не работают.
Элемент
Объявляет компонент ContentProvider. Он обеспечивает структурированный доступ к данным, управляемым приложением.
Элемент
Указывает, для кого могут быть предоставлены разрешения на подмножество данных ContentProvider.
Элемент
Определяет путь и необходимые разрешения для определенного подмножества данных внутри ContentProvider. Этот элемент может быть указан несколько раз для передачи нескольких путей.
Элемент
Задает общедоступную библиотеку, с которой приложение должно быть связано. Этот элемент указывает системе включить код библиотеки в загрузчик классов для пакета.
Защищаемся от трекеров на мобильных платформах
Многие пользователи сталкиваются с отслеживанием в интернете повседневно. Одним из самых явных и крупных следствий является таргетированная реклама. Любой, кто хоть раз имел дело с такими гигантами как, например, Google AdWords, знает насколько обширны настройки целевой аудитории, доступные рекламодателю.

Особенные опасения вызывает мобильный таргетинг, который к обыкновенным сведениям прикрепляет геолокацию и время пользователя. Вопрос о защите приватности в интернете на мобильных устройствах возникает у многих пользователей.
Как происходит отслеживание пользователей
Взаимодействие с трекер-сервисом обычно происходит отдельно от подгрузки контента приложения или веб-страницы. В зависимости от контекста идентификации, собирается отпечаток устройства на основе доступных параметров: серийные номера компонентов, особенности конфигурации, результаты бенчмарков и прочее. После идентификации на удаленный сервер посылается запрос, содержащий отпечаток и полезную информацию о пользователе.

Есть только один способ избежать идентификацию в целях таргетированной рекламы — перехватить обращение к стороннему сервису.
Идентификация трекеров
Для идентификации трекера можно использовать существующие списки доменов (disconnectme). При отправке пакетов с устройства проверять адрес назначения, и блокировать пакеты если они должны были попасть на трекер.
Есть сложные решения (Pi-hole и другие), но нам преимущественно интересны Android и iOS.
Фильтрация трафика на Android
Один из способов – конвертировать доменные имена трекеров в IP-адреса и блокировать их с помощью iptables. Принципиальная проблема такого подхода – необходимость root-прав для выполнения, так как Android не дает прав на модификацию параметров брандмауэра. Но есть способ обойти это ограничение без root.
Если выделить весь трафик в отдельный виртуальный слой позволяющий фильтрацию на уровне приложения. Такой способ существует. С помощью VpnService можно создать локальный VPN, посредством которого можно фильтровать трафик по необходимым параметрам. Для реализации мы можем создать три очереди: сеть-устройство, устройство-сеть-tcp, устройство-сеть-udp. Сырой входящий/исходящий трафик записывается в очереди. Посредством четырех объектов TcpIn, TcpOut, UdpIn, UdpOut обрабатывать пакеты, в том числе утилизируя не проходящие проверку. Пример реализации можно посмотреть на Github (LocalVPN).
Фильтрация трафика на iOS
Для фильтрации трафика будем использовать NetworkExtension.
Как и на Android, ОС не дает нам прямого доступа к настройке брандмауэра. Но при этом есть возможность задать фильтр для сетевого контента из коробки посредством NEFilterControlProvider и NEFilterDataProvider. Мы данный вариант рассматривать не будем, так как Content Filter Providers работают только в контролируемом (supervised) режиме, из-за чего публикация такого приложения в AppStore становится невозможной. Если же такой подход интересен можно рассмотреть пример рабочего приложения на Github (sift-ios, FilterControlProvider, FilterDataProvider).
Для нашего решения мы также будем использовать локальный VPN. В NetworkExtension есть три варианта работы с VPN.
Personal VPN. Использует только встроенные протоколы. Нам это не подходит, так как необходим пользовательский протокол.
App Proxy Provider. Используется для создания пользовательского потокоориентированного VPN протокола. Для нас важна фильтрация отдельных пакетов, что приводит нас к.
Packet Tunnel Provider. Используется для создания пользовательского пакетоориентированного VPN протокола. Мы будем использовать именно его.
Для реализации мы наследуемся от NEPacketTunnelProvider. При запуске тоннеля нам необходимо указать конечную точку – укажем в её качестве локальный прокси сервер, для этого можем использовать, например, GCDHTTPProxyServer, так как он используется в примере который я приведу позже. С помощью прокси сервера на выбор мы утилизируем не нужные нам пакеты. Рабочий пример приложения с использованием NEPacketTunnelProvider и GCDHTTPProxyServer на Github (lockdown-ios PacketTunnelProvider).
Проблема приватности, при использовании удаленного VPN
Во всех примерах выше опускался вариант простого подключения к удаленному VPN, на котором настроена фильтрация. Такой вариант имеет серьезные плюсы – простоту создания клиентов под любую систему (на которой есть возможность использовать VPN) и возможность скрыть фильтры. Но критическим минусом является необходимость проводить трафик через сторонний удаленный сервер. Это требует наличия сетевой инфраструктуры и вызывает недоверие пользователей (так как трафик проходит через сторонний сервер для фильтрации). Данный вариант хоть и имеет свое место и значимость, но не является целью данной статьи.
Несколько слов в заключение
Сегодня мы рассмотрели способы реализации фильтров трафика для ОС Android и iOS. Рассмотрели самый не ограничивающий способ – локальный VPN и основы его реализации с примерами готовых продуктов и примеров. Для этого мы воспользовались возможностью создания пользовательских протоколов VPN. С их помощью мы с прикладного уровня получили доступ к сетевому, что позволило нам применить фильтр к входящим/исходящим пакетам. Фильтр мы основываем на черных списках доменов трекеров, доступных в сети интернет.
Статья подготовлена для Telegram канала @paradiSEcurity.
- tracking protection
- android development
- ios development
- vpn