Плагін ATAK — це не споживчий застосунок. Він працює на пристрої, що береться в оспорену місцевість, використовується операторами під вогнем і потенційно може бути захоплений противниками, які точно знають, як виглядає програмне забезпечення TAK і чому зворотна розробка його є цінною. Захисна позиція тактичного Android-плагіна повинна бути спроектована навколо цієї реальності — а не навколо моделі загроз роздрібного банківського застосунку.
Ця стаття охоплює повний стек захисту для розробки плагінів ATAK: від моделі загроз через обфускацію, захист від підробки, безпечне сховище, прив'язування сертифікатів, мережеву безпеку, безпечне видалення та цілісність конвеєра збірки. Кожен розділ пояснює, від чого захищає контроль, від чого не захищає та специфіку реалізації, що має значення в екосистемі TAK.
Модель загроз: від чого ви захищаєтеся
Чотири сценарії загроз мають визначати кожне рішення щодо безпеки для TAK-плагіна.
Захоплений пристрій. Захищений Android-пристрій — Samsung XCover Pro, Kyocera DuraForce або подібний — потрапляє до противника після того, як оператора поранено, вбито або він вимушений покинути обладнання. Противник має необмежений фізичний час із пристроєм. Він може витягти APK через ADB, проаналізувати його офлайн за допомогою jadx або apktool, спробувати зчитати зашифроване сховище та клонувати пристрій у лабораторне середовище. Архітектура безпеки повинна гарантувати, що захоплений пристрій не надасть жодних оперативно корисних даних — ні серверних адрес, ні облікових даних автентифікації, ні кешованих оперативних даних.
Зловмисний інсайдер. Користувач із законним доступом до пристрою та встановленого плагіна навмисно відкачує дані, змінює поведінку плагіна або передає облікові дані противнику. Внутрішні загрози технічно складніше нейтралізувати, ніж зовнішні атаки — інсайдер знає PIN-код пристрою, автентифікований у серверних системах та може робити знімки екрана карт. Основні технічні засоби контролю — мінімізація локально збережених даних (мінімізація даних) і журналювання доступу до чутливих операцій через журнали аудиту MDM.
Мережева атака. Противник, що працює в тій самій радіомережі або стільниковій мережі, що й пристрій, намагається перехопити або впровадити дані у трафік TAK-плагіна — MITM-атаки на TLS-з'єднання з використанням підробленої точки доступу та шахрайськи отриманого сертифіката, або впровадження підроблених подій CoT для пошкодження спільної оперативної картини. Прив'язування сертифікатів і конфігурація TLS безпосередньо вирішують цю загрозу.
Компрометація ланцюжка постачання. Зловмисник вводить бекдор у плагін через скомпрометовану залежність, підроблений SDK або середовище збірки, що модифікує скомпільований вихід. Атаки на ланцюжок постачання дедалі частіше спрямовані проти програмного забезпечення, суміжного з оборонною галуззю. Безпека конвеєра збірки — відтворювані збірки, прив'язування залежностей, генерація SBOM та підписання бінарних файлів — вирішує цю загрозу.
Обфускація коду: конфігурація ProGuard/R8
Компілятор R8 Android (який замінив ProGuard у AGP 3.4+) виконує три операції: мінімізацію (видалення невикористовуваних класів, методів і полів), обфускацію (перейменування ідентифікаторів у короткі беззмістовні назви) та оптимізацію (вбудовування методів, видалення мертвих гілок коду). Усі три слід вмикати для реліз-збірок будь-якого TAK-плагіна.
Критичні правила ProGuard для контексту плагіна ATAK: зберігати видимість підкласу AbstractPlugin та його методів життєвого циклу (ATAK завантажує плагіни через рефлексію і не зможе ініціалізувати повністю обфускований вхід), зберігати будь-які класи, що використовуються у макетах XML або посиланнях на ресурси, та зберігати реалізації Parcelable/Serializable, що перетинають межі процесів через рівень IPC ATAK. Окрім цих обов'язкових правил збереження, все інше слід обфускувати.
Шифрування рядків. Обфускація R8 не шифрує рядкові літерали — ім'я хоста сервера, жорстко закодоване як "tak.yourbackend.mil", залишається після обфускації у незміненому вигляді та тривіально витягується за допомогою strings. Рядкові літерали, що представляють адреси серверів, шляхи API або будь-які оперативно чутливі константи, повинні бути зашифровані в APK та розшифровані під час виконання. Бібліотеки, такі як StringFog або власні процесори анотацій, можуть автоматизувати шифрування рядків у збірці Gradle. Сам ключ дешифрування не повинен бути жорстко закодованим літералом — він повинен виводитися з матеріалу, прив'язаного до пристрою, збереженого в Android Keystore.
Від чого обфускація не захищає. Обфускація підвищує вартість зворотної розробки, але не запобігає їй. Противник із jadx, кількома годинами та знанням API плагіна ATAK може відновити логічну структуру обфускованого плагіна. Обфускацію слід розглядати як механізм затримки, що дає час для закінчення оперативної цінності даних — а не як межу безпеки. Межами безпеки є управління ключами, зашифроване сховище та прив'язування сертифікатів.
Захист від підробки: перевірка підпису, виявлення root, виявлення емулятора
Перевірка підпису APK під час виконання. При ініціалізації плагін повинен зчитати свій власний сертифікат підпису за допомогою PackageManager.getPackageInfo(packageName, GET_SIGNATURES), хешувати його за допомогою SHA-256 та порівняти зі значенням, скомпільованим (та обфускованим) у плагін. Якщо хеші відрізняються, APK був перепакований та повторно підписаний — плагін повинен видалити будь-які локально кешовані чутливі дані та відмовитися від запуску. Це нейтралізує атаку декомпіляції, виправлення та перерозподілу модифікованого APK.
Важлива деталь: на Android 9+ правильним API є GET_SIGNING_CERTIFICATES (а не застарілий GET_SIGNATURES), який повертає повний ланцюжок сертифікатів підпису та обробляє ротацію ключів схеми підпису APK v3. Логіка порівняння повинна обробляти як поточний, так і будь-який попередній сертифікат підпису, якщо використовувалася ротація ключів.
Виявлення root. Пристрій із root означає, що припущення безпеки пісочниці додатків Android — ізоляція процесів, примусове виконання дозволів файлів, апаратне прив'язування Keystore — послаблені або порушені. Виявлення root перевіряє кілька сигналів: наявність бінарного файлу su у загальних місцях (/system/bin/su, /system/xbin/su, /sbin/su), наявність відомих пакетів управління root (Magisk, SuperSU, KingRoot), можливість запису у /system (що вдається лише на пристроях з root) та висновок Play Integrity API.
Play Integrity API (що замінив SafetyNet Attestation у 2023 році) повертає три рівні висновку: MEETS_BASIC_INTEGRITY, MEETS_DEVICE_INTEGRITY та MEETS_STRONG_INTEGRITY. Для TAK-плагіна, що обробляє чутливі оперативні дані, прийнятним є лише MEETS_STRONG_INTEGRITY — що вимагає апаратної атестації від немодифікованого пристрою. Зверніть увагу, що деякі захищені Android-пристрої, що використовуються в оборонних цілях, можуть не проходити перевірку STRONG, якщо вони поставляються із власними збірками ОС; перевірте на цільовому обладнанні перед тим, як зробити це жорстким обмеженням.
Виявлення емулятора. Аналіз APK часто проводиться в емуляторах Android, де противник може інструментувати середовище виконання, перехоплювати виклики методів та спостерігати розшифровані дані в пам'яті. Виявлення емулятора перевіряє властивості збірки (Build.FINGERPRINT, Build.MODEL, Build.HARDWARE) на відомі рядки емуляторів, перевіряє, що апаратні датчики повертають ненульові значення, та перевіряє відсутність стану телефонії, характерного для фізичних пристроїв. Виявлення емулятора легко обходиться досвідченими противниками, але додає складності для автоматизованих конвеєрів аналізу.
Безпечне сховище: Android Keystore, EncryptedSharedPreferences, SQLCipher
Будь-які чутливі дані, що повинні зберігатися між сеансами — токени автентифікації, кешовані облікові дані, локально збережені оперативні треки, параметри конфігурації — повинні бути зашифровані у стані спокою. Android надає багаторівневий стек безпечного сховища.
Android Keystore. Система Keystore генерує та зберігає криптографічний ключовий матеріал у апаратно захищеному безпечному анклаві на пристроях із Trusted Execution Environment (TEE). Ключовий матеріал ніколи не покидає безпечний анклав — операції шифрування та дешифрування виконуються всередині TEE, а необроблені байти ключа ніколи не відкриваються процесу застосунку. Ключі слід створювати з KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT, setUserAuthenticationRequired(true) там, де це оперативно доцільно, та setInvalidatedByBiometricEnrollment(true) для виявлення класу атак, коли противник додає власну біометрію для розблокування ключа.
EncryptedSharedPreferences. Бібліотека Jetpack Security надає EncryptedSharedPreferences, що обгортає стандартний API SharedPreferences та шифрує як ключі, так і значення за допомогою головного ключа з Android Keystore. Значення конфігурації, токени та невеликі елементи даних слід зберігати в EncryptedSharedPreferences, а не у звичайних SharedPreferences. API є заміною без змін — міграція з незашифрованих SharedPreferences є однорядковою зміною на місці виклику.
SQLCipher для локальних баз даних. TAK-плагіни, що кешують оперативні дані локально, зазвичай використовують SQLite. Стандартна база даних Android SQLite зберігається у незашифрованому вигляді в файловій системі — доступна з пристрою з root або через ADB у відлагоджувальній збірці. SQLCipher забезпечує прозоре шифрування AES-256 файлів баз даних SQLite. Це заміна без змін для API Android SQLite: змініть імпорт з android.database.sqlite на net.sqlcipher.database та надайте пароль під час відкриття бази даних. Пароль повинен бути ключем, підкріпленим Keystore, а не жорстко закодованим рядком.
Ключовий висновок: Апаратне прив'язування Android Keystore є настільки сильним, наскільки сильним є TEE пристрою. Споживчі Android-пристрої значно відрізняються за якістю реалізації TEE. Для розгортань, де безпека сховища є жорсткою вимогою, вкажіть обладнання, що постачається із сертифікованим TEE — Keystore з підтримкою StrongBox (доступний на Pixel 3+ та окремих пристроях Samsung) надає найвищу гарантію.
Прив'язування сертифікатів: реалізація OkHttp/TrustKit та ротація pin
Прив'язування сертифікатів запобігає MITM-атакам, прив'язуючи плагін до конкретного сертифіката або матеріалу відкритого ключа для його серверних кінцевих точок, незалежно від системного сховища сертифікатів. Підроблений центр сертифікації — чи то державний суб'єкт, чи скомпрометований корпоративний CA у польовій мережі — не може видати сертифікат, що проходить перевірку прив'язування.
OkHttp CertificatePinner. Стандартна реалізація для плагінів ATAK, що використовують OkHttp, додає CertificatePinner до конструктора клієнта:
CertificatePinner pinner = new CertificatePinner.Builder()
.add("tak.yourbackend.mil",
"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", // primary
"sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=") // backup
.build();
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(pinner)
.build();
Прив'язуйте хеш відкритого ключа (префікс sha256/ в OkHttp), а не хеш сертифіката. Хеші відкритого ключа виживають після оновлення сертифіката, якщо та сама пара ключів повторно використовується — прив'язування хешу сертифіката вимагає оновлення плагіна кожного разу, коли сертифікат оновлюється.
TrustKit для Android. TrustKit надає реалізацію прив'язування на основі конфігурації, яка також повідомляє про збої перевірки pin на кінцеву точку звітування — корисно для виявлення активних MITM-атак проти розгорнутих пристроїв. TrustKit зчитує конфігурацію pin з файлу XML конфігурації мережевої безпеки, який можна оновлювати без повторної збірки APK, якщо він доставляється через політику MDM.
Стратегія ротації pin. Кожне прив'язане розгортання потребує плану ротації. Резервний pin повинен бути хешем попередньо згенерованої пари ключів, що зберігається в резерві — ще не встановленої як живий сертифікат. Коли основний сертифікат наближається до закінчення терміну дії (або скомпрометований), встановіть резервний ключ як новий сертифікат, потім видайте оновлення плагіна, що просуває резервний pin до основного та додає новий резервний. Дозвольте 30-денне вікно перекриття, де обидва pin дійсні, щоб усі розгорнуті клієнти оновилися до закінчення терміну дії старого pin.
Мережева безпека: TLS 1.3, прозорість сертифікатів, заголовки HPKP
Застосування TLS 1.3. Налаштуйте OkHttp ConnectionSpec для дозволу лише TLS 1.3, з TLS 1.2 як резервним варіантом лише для застарілих розгортань TAK Server, що не були оновлені. TLS 1.0 та 1.1 повинні бути явно виключені зі списку дозволених протоколів — стандартний SSLSocketFactory Android може узгодити їх, якщо сервер їх пропонує. У network_security_config.xml плагіна встановіть cleartextTrafficPermitted="false", щоб запобігти будь-якому випадковому з'єднанню у відкритому тексті.
Прозорість сертифікатів. Прозорість сертифікатів (CT) — це публічний журнал усіх TLS-сертифікатів, виданих центрами сертифікації. Увімкнення перевірки CT означає, що плагін відхилятиме TLS-з'єднання до серверів, чиї сертифікати не записані у публічних журналах CT — сильний індикатор шахрайськи виданого сертифіката, використаного у MITM-атаці. OkHttp підтримує перевірку CT через розширення certificateTransparency з бібліотеки прозорості сертифікатів Appmattus.
Заголовки HPKP. HTTP Public Key Pinning (HPKP) — це серверний механізм, де сервер доставляє значення pin у заголовку відповіді (Public-Key-Pins), який клієнт кешує та застосовує у наступних з'єднаннях. Для TAK-плагінів HPKP є рівнем захисту в глибині, що доповнює внутрішнє прив'язування — скомпрометований бінарний файл плагіна, з якого видалено жорстко закодовані pin, все одно застосовуватиме pin, доставлені сервером. HPKP застарів у браузерах, але залишається дійсним механізмом для не-браузерних клієнтів, таких як застосунки Android.
Мінімізація даних та безпечне видалення
Мінімізуйте те, що зберігається. Найефективніший спосіб захисту даних на захопленому пристрої — не зберігати їх. TAK-плагіни повинні зберігати локально лише дані, необхідні для роботи у відключеному стані протягом очікуваного періоду ізоляції. Оперативні треки, старіші за тактичне вікно, більше не потрібні токени автентифікації та проміжні артефакти обробки повинні видалятися, як тільки вони більше не потрібні — а не зберігатися нескінченно, оскільки видалення ніколи не розглядалося.
Обнулення в пам'яті. Чутливі дані в пам'яті — розшифровані ключі, декодовані токени автентифікації, розшифрований вміст повідомлень — повинні бути перезаписані нулями, як тільки обробка завершена. Збирач сміття Java не гарантує, коли пам'ять буде звільнена, тобто чутливі дані можуть зберігатися в купі пам'яті довго після того, як посилання звільнено. Використовуйте байтові масиви (а не String, який є незмінним і не може бути обнулений) для чутливого матеріалу та явно перезаписуйте перед звільненням посилання.
Безпечне видалення файлів. Стандартний File.delete() Android позначає inode як вільний, але не перезаписує сектори даних — вміст можна відновити за допомогою криміналістичних інструментів із флеш-пам'яті захопленого пристрою. Перед видаленням чутливого файлу відкрийте його для запису та перезапишіть вміст нулями, потім видаліть. Для баз даних SQLCipher, що очищаються, викличте SQLiteDatabase.rawQuery("PRAGMA wal_checkpoint(TRUNCATE)") перед перезаписом, щоб забезпечити включення сторінок журналу запереджувального запису до очищення.
Віддалене очищення через MDM. Пристрої, розгорнуті оперативно, повинні бути зареєстровані в профілі MDM (Microsoft Intune, VMware Workspace ONE або спеціалізований MDM для оборонної галузі). Профіль MDM дає змогу оперативній групі видати команду дистанційного очищення, якщо пристрій зазначено як загублений або захоплений. Дистанційне очищення MDM повинно перевірятися під час введення пристрою в експлуатацію — а не виявляти неправильну конфігурацію при фактичній втраті пристрою.
Безпека конвеєра збірки: відтворювані збірки, SBOM, підписання бінарних файлів, атестація
Відтворювані збірки. Відтворювана збірка виробляє побітово ідентичний APK з одних і тих самих вхідних даних джерела незалежно від того, коли або де виконується збірка. Це означає блокування всіх версій залежностей у gradle.lockfile (або використання перевірки залежностей із контрольними сумами), видалення часових міток та шляхів збірних машин зі скомпільованих артефактів та використання фіксованої версії інструментального ланцюжка Java/Kotlin, вказаної в конфігурації Gradle wrapper. При відтворюваних збірках будь-яка сторона з доступом до джерела може самостійно перевірити, що розповсюджений APK відповідає конкретному коміту — надаючи технічну основу для аудиту ланцюжка постачання.
Генерація SBOM. Software Bill of Materials — це машинозчитуваний інвентар кожної бібліотеки та залежності у збудованому артефакті. Інтегруйте CycloneDX для Gradle або SPDX Gradle Plugin у збірку для генерації SBOM разом з APK при кожній CI-збірці. SBOM дає змогу швидко сортувати, коли публікується нова CVE: запитайте SBOM для назви та версії відповідної бібліотеки, щоб негайно дізнатися, які релізи плагіна є ураженими, без ручної перевірки дерев залежностей Gradle.
Підписання бінарних файлів ключами з підтримкою HSM. Ключ підпису релізу для APK плагіна повинен зберігатися в апаратному модулі безпеки (HSM) — а не у файлі keystore на робочій станції розробника. Конвеєр CI/CD повинен викликати API підписання HSM (наприклад, Google Cloud HSM, AWS CloudHSM або локальний HSM) безпосередньо, щоб необроблений ключовий матеріал ніколи не існував у середовищі збірки. Використовуйте схему підпису APK v3 (Android 9+), яка підтримує ротацію ключів із ланцюжком доказів ротації, дозволяючи ротацію ключа підпису без порушення шляху оновлення для існуючих установок.
Атестація та провенанс. Окрім підписання APK, публікуйте підписаний документ атестації разом із кожним релізом — твердження, що пов'язує хеш SHA-256 APK з конкретним комітом джерела, середовищем збірки та SBOM. Сама атестація повинна бути підписана тим самим ключем з підтримкою HSM, що й APK. Союзні організації, що отримують плагін, можуть перевірити атестацію перед установкою, підтверджуючи, що артефакт відповідає відомій збірці конкретної версії джерела.