Ще трохи про телефони Xiaomi і боротьбу з ними

image
Чесно зізнатися, у мене не було планів писати і публікувати цю статтю, але, після того, як за два місяці побачив у близькому колі колег 5 штук новоотриманих телефонів від Xiaomi, і недавню статті на Geektimes, рекламує управління розумним будинком від Xiaomi, до мене прийшла совість і, сцуко, зажадала поділитися знаннями з іншими.

Для початку невелика вступна частина для тих хто не в темі. Є така компанія Xiaomi, яка робить непогані по начинці телефони і заливає в них кастомизированный Android. Бізнес-модель, як нещодавно офіційно було заявлено — «По суті ми роздаємо наші смартфони, не заробляючи на цьому гроші. Нас більше турбують довгострокові джерела доходу. Ми могли б продати 10 мільярдів смартфонів і не заробити на них жодного цента». Джерело раз і два.

Заглянувши в вересневу статті Security lab і ще ось у цю скаргу, у мене особисто виникло відчуття, що телефон Xiaomi це щось типу повідця на якому власника водить Великий брат (утрирую, звичайно ж).

Це і стало основним мотивом проведення дослідження поведінки телефону Xiaomi redmi 3S
з прошивкою MIUI Global 8.1 Стабільна 8.1.1.0 (MALMIDI)

Дослідження піддослідного кролика і виявлення проблеми
Беру новенький телефон з коробки. Включаю його і проходжу через майстра настроювання, попередньо включивши запис трафіку на Wi-Fi роутера. Рівно через дві секунди після того, як телефон підключився до точки доступу, почалося завантаження файлу розміром близько 8Мбайт з одного з серверів Xiaomi. Це був звичайний zip архів, всередині якого лежала купа всього і в тому числі, файл AnalyticsCore.апк, згаданий у статті на SecurityLab.

Далі — більше. В цілому, за весь час спостереження, я нарахував трохи менше восьми десятків імен серверів в різних доменах. Відразу обмовлюся, що в цьому числі немає серверів Google і Facebook, програми яких також встановлені. Просто тому що я їх вважав окремо. З ними теж всі «весело».

Велика частина коннектов до серверів Xiaomi йшла через HTTPS, тому розібратися в деталях ЩО саме передається безпосередньо можливості не було. Відключення всіляких логінов, синхронізацій і т. п. до зникнення цього трафіку не призвело.

Додатково бентежило те, що здебільшого запити були невеликими (обсяг прийнятого переданого трафіку TCP сесій не перевищував 1-2Кб), але, оскільки наші стільникові оператори округляють обсяг трафіку вгору (Наприклад, Tele2 до 150Кб), то, при невдалому збігу, можна «накачати» таким чином суттєві обсяги трафіку, а в роумінгу несподівано потрапити на гроші.

Тих, кого цей факт не бентежить можуть далі не читати, т. к. далі буде опис конкретики ізоляції трафіку від додатків, ушитих в заводську прошивку.

Попередні умови
Перше, що необхідно — це рутовать телефон. Як це робиться у випадку Xiaomi я тут описувати не буду, відсилаю бажаючих пройти цей шлях до повної версії цієї статті (посилання в кінці).
Друге — це влити в телефон прошивку через кабель і стерти ВСІ дані користувача.
Третє — телефон НЕ ПОВИНЕН мати доступу в інтернет після затоки свіжої прошивки.

Disclamier. Всі подальші маніпуляції над телефоном Ви робите на свій страх і ризик.
Відповідальність за результат лежить на тому, хто саме робив описувані нижче дії.


Невелика технічна вступна частина
Сервери, до яких звертається телефон, здебільшого розташовані в хмарі Amazon, тому звернення до них відбувається по іменах, які ресолвятся через round-robin DNS в різні IP адреси з різних підмереж /16. Блокувати їх все по подсетям сенсу особливого немає — так можна половину інтернету відфільтрувати, що не є добре. Блокувати по іменах — добре, але не факт, що імена хостів з L3 доменів не генеруються динамічно. Ідеально було б прибити всі програми, які звертаються до серверів Xiaomi, але, як показала практика, глибина їх інтеграції в Android така, що після видалення деяких з них телефон може просто відмовитися завантажуватися.

Далі. До зовнішніх серверів звертається не один процес, а багато, при цьому завдання ускладнює наявність в Android UID sharing, коли під одним UID можуть генерувати трафік різні процеси (додатки). Більш того, один з корисних процесів (відповідальний за GPS) треба випускати у зовнішній світ, щоб завантажувати невеликі оновлення, але при цьому він сидів під тим же UID, що і вісім штук процесів, які рвуться до серверів Xiaomi.

Також треба згадати про обмеженість інструментарію, доступного для вирішення вищеописаних завдань, оскільки велика частина додатків мають в назві firewall доступних на Play Market працюють через т. зв. VPN, тобто від зливів інформації до запуску програми вони не захищають.

Велика частина того, що буде розказано далі для професійних розробників Android є банальна істина, але всім іншим це дозволить зрозуміти чому фільтрація побудована саме таким чином.

На відміну від звичайного Linux, де є файли конфігурації і стартові скрипти, що лежать в /etc, Android все зроблено дещо інакше. Загальне управління мережею здійснює Connection Manager, який смикає системний демон netd, який, у свою чергу, викликає iptables з певними параметрами командного рядка. Відповідно, викликати IPtables з скрипта початкового завантаження (init та інших) особливого сенсу немає — netd при старті все одно викличе iptables, очистить правила і заллє свої.

Єдиний вихід залишений Google — писати необхідні команди конфігурації iptables в скрипті /system/bin/oem-iptables-init.sh. Шлях до цього скрипту і його ім'я жорстко прописані всередині вихідного коду демона netd.

Для фільтрації статичних імен хостів можна редагувати файл /etc/hosts, але при цьому треба пам'ятати про їх кількість і можливість їх динамічної генерації.
Далі буде розповідь як це все робилося.

Видалення і заморожування (якщо немає впевненості) непотрібних програм
За допомогою безкоштовної версії Titanium Backup можна подивитися відповідність між ім'ям програми показується в системі (Play Market), її кодовим ім'ям (com.google.vending) і, при необхідності, видалити те, що явно не потрібно.

Недолік безкоштовної версії — не вміє робити заморожування програм, тому заморожування робимо через ADB shell за допомогою package manager. Приклад:

root@land:/ # pm disable com.miui.analytics
pm disable com.miui.analytics
Package com.miui.analytics new state: disabled
root@land:/ # pm disable com.miui.systemAdSolution
pm disable com.miui.systemAdSolution
Package com.miui.systemAdSolution new state: disabled
root@land:/ # reboot
reboot

Фільтрація мережевих запитів
Disclamier 2.У цій статті описано ЯК можна фільтрувати «ліву» мережеву активність телефону. Що конкретно фільтрувати кожен може вирішувати сам.

Робимо все по кроках:

1. найпростіше — заповнення файлу /etc/hosts записами імен серверів c IP адресою 127.0.0.1. Мій набір серверів лежить на Google Drive в папці Files.

2. пишемо команди фільтрація відправки пакетів на підмережі /16 /24 стандартними правилами Netfilter/IPtables в файл oem-iptables-init.sh. Тут їх не описую, бажаючі напишуть їх самі, або знайдуть у повній версії статті.

3. Фільтруємо DNS запити до непотрібних нам доменам. Це трохи складніше, тому опишу детальніше.

У складі IPtables, штатно йде в Android є модулі розширення функціоналу, якими ми далі і скористаємося. Пам'ятаючи, що DNS-запити відправляє система (UID 0) пишемо правило:

$IPTABLES -A oem_out --protocol udp --dport 53 -m --owner uid-owner 0 -m string --algo bm --hex-string '|<b>04</b>6d697569<b>03</b>636f6d|' -m comment --comment "Deny UID 0 DNS запити for miui.com domain" -j DROP
#
$IPTABLES -A oem_out --protocol udp --dport 53 -m --owner uid-owner 0 -j ACCEPT

Перша строчка відфільтрує всі UDP пакети, відправлені системою (UID 0) на 53 UDP порт будь-якого IP адреси і містять у собі байти 046d69756903636f6d (запити до DNS серверу містять в собі .miui.com). Код формується з назви домену, але з заміною коду точки-роздільника (2e) на шестнадцатиричную цифру кількості байт, наступних за даними роздільником до наступного роздільника.

Друга строчка пропустить всі інші DNS запити. Коментарі я вказав для зручності, щоб команда iptables -L -v показувала результати блокувань наочніше.

4. Для роботи Assited GPS необхідно дати можливість доступу до серверів QualComm процесу з UID 1000. Тут все складніше, оскільки пряма фільтрація як у випадку DNS серверів спрацює — пакети встановлення TCP з'єднання містять у собі ім'я хоста, яка обов'язково присутня в HTTP-запиті, а пакети йдуть після заголовка HTTP запиту вже можуть не містити в собі ім'я хоста. Тому малюємо ось такий милиця для фільтрації запитів сьомого рівня засобами 3-4 рівня:

# дозволяємо ініціювати встановлення TCP з'єднань на 80 порт всім процесам працюючим під UID 1000.
$IPTABLES -A oem_out -m --owner uid-owner 1000 --protocol tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
#перевіряємо наявність слова xtrapath у пакетах TCP з'єднань встановлених на 80 порт процесами з UID 1000 і позначаємо ці сполуки шестнадцатиричным числом 5555.
$IPTABLES -A oem_out -m --owner uid-owner 1000 --protocol tcp --dport 80 -m conntrack --ctstate ESTABLISHED -m string --algo bm --string 'xtrapath' -j CONNMARK --set-xmark 0x5555
# вбиваємо пакети всіх встановлених процесами з UID 1000 TCP з'єднань не мають нашої позначки число 5555
$IPTABLES -A oem_out -m --owner uid-owner 1000 --protocol tcp --dport 80 -m conntrack --ctstate ESTABLISHED -m connmark ! --mark 0x5555 -j DROP

5. Фільтруємо доступ в інтернет з додатками (у мене Google Chrome мав UID 10060). Дозволяємо вихід в інтернет Google Chrome і забороняємо всім іншим додаткам.

$IPTABLES -A oem_out -m --owner uid-owner 10060 -m comment --comment "Permit Google Chrome, internet access" -j ACCEPT
#
# Block all other processes
#
$IPTABLES -A oem_out -m --owner uid-owner 0-9999 -m comment --comment "Block all other system processes internet access" -j DROP
$IPTABLES -A oem_out -m --owner uid-owner 10000-99999 -m comment --comment "Block all other user processes internet access" -j DROP

Слабким місцем цього способу фільтрації є його опора на наявність позначки UID на кожному конкретному пакеті при проходженні його через Netfilter/IPtables. Виявилося це з незрозумілих TCP з'єднань із серверами Google, пакети яких не містили UID. Дослідження показало, що ці пакети ініційовані процесом Google Captive portal login. Я вирішив цю проблему обхідним шляхом — просто вимкнувши ці запити командами в ADB shell:

root@land:/ # settings put global captive_portal_detection_enabled 0
root@land:/ # reboot

Радує, що (судячи з накопиченої статистики за кілька діб перехоплення Wi-Fi трафіку), ніяких інших системних процесів посилають пакети без UID в исследовавшемся телефоні немає.

6. Для цілей моніторингу роботи правил Netfilter/IPtables можна додати ще ось таку строчку:

$IPTABLES -A oem_out --source 10.1.30.42 --protocol tcp --jump LOG --log-prefix "IPtables log:" --log-uid

Параметр IP-адреса відправника (--source 10.1.30.42) можна опустити, але в цьому випадку лог буде завалений записами мережевої активності процесів, загорнутих на адресу 127.0.0.1 файл hosts. Лог можна читати через команду dmesg (dmesg | grep IPtables) в ADB Shell.

Версію статті, яка писалася як повна інструкція щодо вирішення цієї проблеми з Xioami Redmi 3S я виклав на Google Drive. Сюди її викладати не ризикнув саме із-за об'єму.

p.s. Я не розробник Android-додатків, просто життя змусила два місяці порозбиратися з сабжевым телефоном. Тому, панове профі, якщо я десь помиляюся — поправляйте. Буду вдячний.

P. P. S. як засоби перехоплення використовувався Zyxel Keenetic Extra. У нього є можливість перехоплювати Wi-Fi трафік і зливати його на флешку для подальшого аналізу.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.