Блокуйте відкритий текст у застосунках Android, не покладаючись на VPN
Відкритий текст у навантаженні й відкритий текст у шляху — різні проблеми. Першу розв'яжіть у застосунку, а другу — тунелем або політикою пристрою.
Дві цілком різні речі називають блокуванням відкритого тексту в Android. Одна — це політика всередині застосунку, яка наказує власному мережевому стеку відмовитися від звичайного HTTP. Інша — це впорядкування на рівні пристрою, яке намагається захистити все на телефоні одразу, зазвичай пропускаючи трафік через VPN. Вони розв'язують різні проблеми, і друга не може виправити першу: тунель захищає ділянку між телефоном і виходом, а застосунок, що говорить HTTP, і далі говорить HTTP з усім, що лежить за цим виходом.
Дві проблеми під однією назвою
Перша проблема — навантаження: застосунок записує облікові дані або токени в запит, який не шифрується від початку до кінця, тож кожен перехід, що його бачить, може його прочитати. Друга — шлях: застосунок може бути бездоганним, а ви все одно хочете, щоб місцевий оператор Wi-Fi не дізнався нічого про те, куди він підключається. VPN працює з другою і лише з другою.
Ця відмінність визначає, кому належить виправлення. Навантаження належить тому, хто постачає застосунок, бо лише цей код вирішує, який URL викликається і чи перевіряється сертифікат. Шлях належить пристрою або мережі, бо йдеться про те, куди мандрують пакети, а не про те, що вони містять.
Шлях перший: застосунок, який ви контролюєте
Якщо ви постачаєте застосунок, виправлення — це рішення про транспорт плюс політика, що його забезпечує. Спрямуйте кожну кінцеву точку на HTTPS, залиште ввімкненою перевірку імені хоста й сертифіката і видаліть запасний шлях звичайним HTTP, а не залишайте його на відстані одного прапорця конфігурації. Перенаправлення тут не допомагає: HTTP-запит, що отримує 301, уже надіслав заголовки й тіло відкрито, тож облікові дані ніколи не повинні йти в припущенні, що перенаправлення їх захистить.
Починаючи з Android 7.0, політику виражає Network Security Configuration. Файл нижче — найменша корисна версія: він відмовляє у відкритому тексті всюди, якщо тільки виняток для конкретного домену не каже інакше.
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
</network-security-config>Посилайтеся на цей ресурс із маніфесту, а потім прочитайте вже наявні винятки перед постачанням. Старий домен для налагодження або запис SDK платіжного провайдера можуть тихо знову дозволити відкритий текст для хоста, який ви намагалися захистити.
Дві подробиці про версії варто знати. Застосунки, націлені на API 28 або новіше, уже за замовчуванням відмовляють у відкритому тексті, тож застосунок, який досі говорить звичайним HTTP, або цілить на старіший рівень API, або десь має виняток. А коли присутня конфігурація мережевої безпеки, старіший атрибут маніфесту android:usesCleartextTraffic більше не вирішує це питання, і саме тому зміна того прапорця іноді виглядає так, ніби нічого не робить.
Шлях другий: застосунок, який ви не контролюєте
Для встановленого стороннього застосунку ви не можете переписати його конфігурацію безпеки користувацьким налаштуванням. Реалістичні варіанти — власні засоби безпечного з'єднання продукту, підтримувана альтернатива, що вже використовує TLS, або політика керованого пристрою, яка обмежує те, що пристрою дозволено запускати. Це різні зобов'язання, і лише третє масштабується на парк пристроїв.
Мережеві правила — слабша заміна, ніж здається. Дозвіл лише порту 443 не забезпечує автентифікований TLS, бо багато протоколів відкритого тексту можна перенести на цей порт, а блокування порту 80 не покриває відкритий текст на інших портах. Режим лише-HTTPS у браузері теж обмежений цим браузером, а не окремим застосунком пошти чи чату на тому самому телефоні.
Встановлення перехоплювального сертифіката, щоб трафік виглядав зашифрованим, — це зміна довіри, а не виправлення. Воно замінює автентифікацію сервера застосунку вашою, і застосунок, який від самого початку не перевіряв сертифікати, цим не виправляється; ви лише перемістили те, хто може читати потік.
Де VPN допомагає, а де ні
Тунель — правильний інструмент, коли вимога полягає в тому, щоб локальна мережа нічого не дізналася про з'єднання, або щоб застосунок дістався приватної служби, до якої інакше не дістатися. Це неправильний інструмент, щоб змусити HTTP-клієнт говорити HTTPS, бо запит залишає тунель точно таким, яким увійшов.
Android додає практичне обмеження: платформа запускає лише одну службу VPN одночасно. Локальний застосунок фільтрації, що займає це місце, конкурує з віддаленим тунелем, який вам справді потрібен, а перемикання між ними — операція рівня пристрою, а не застосунку. Це єдине місце — добра причина тримати політику навантаження в застосунку, а тунель лишити для шляху.
Єдиний випадок, коли ці двоє перетинаються, — приватний сервер, яким ви теж керуєте. Там тунель може зробити шлях приватним, навіть якщо протокол усе ще відкритий текст, що зменшує експозицію, але не змінює того, чим є навантаження. Ставтеся до цього як до зниження ризику, а не як до шифрування даних.
Що перевірити, перш ніж називати це заблокованим
Почніть із типового налаштування, яке дивує людей: застосунок, націлений на API 28 або новіше, мав би вже відмовляти у відкритому тексті, тож перевірте цільовий рівень, перш ніж додавати конфігурацію, що дублює типове значення. Потім навмисно перевірте випадок збою: запит до звичайного HTTP-хоста має зазнавати невдачі, а не тихо вдаватися через запасний шлях.
adb shell dumpsys package com.example.app | grep -E 'targetSdk|versionName'
adb logcat | grep -i cleartextДля випадку успіху переконайтеся, що виклик HTTPS перевіряє справжній ланцюжок сертифікатів і що проксі з недовіреним сертифікатом відхиляється, а не толерується. Рукостискання, яке вдається з будь-яким сертифікатом, нічого не довело про безпеку транспорту.
Для стороннього застосунку запишіть межу, яку ви справді можете забезпечити, будь то політика керованого пристрою, мережеве правило чи нічого, і скажіть це в критеріях приймання. Посібник із конфігурації безпеки Android перелічує типові значення платформи й те, які компоненти дотримуються політики, і саме ця частина вирішує, чи ваша конфігурація взагалі щось робить.