
Спойлер: оба находятся в опасности, но по-разному. Эта разница имеет значение.
Каждый раз, когда я слышу фразу «с безопасностью все в порядке, мы не банк», у меня внутри что-то напрягается.
На практике эта фраза часто скрывает токены аутентификации в SharedPreferences, SQL-запросы без параметров, Firebase без правил доступа, слабые настройки сессий, открытые хранилища или бэкэнд, который доверяет всему, что отправляет клиент.
Меня зовут Илья Новиков, я технический директор компании «Исходный код». Мы разрабатываем веб- и мобильные продукты и сталкивались с одной и той же ошибкой с разных сторон: команды относятся к безопасности как к чему-то, что относится к банкам, финтех-компаниям или крупным корпоративным системам. А потом обычный продукт с обычными пользователями вдруг начинает обрабатывать персональные данные, платежи, внутренние документы, медицинские карты, заявки в службу поддержки или токены аутентификации.
В этой статье я пытаюсь честно сравнить два мира: веб-безопасность и мобильную безопасность. Я не пытаюсь определить, какая платформа в целом безопаснее. Этот вопрос слишком прост. Я хочу показать, где риски пересекаются, где они расходятся и почему один и тот же бэкэнд может стать слабым местом для обоих типов клиентов.
В качестве источников для этого сравнения использованы OWASP Top 10 Web 2025, OWASP Mobile Top 10 2024, статистика NVD и CVE, результаты реальных тестов на проникновение, а также отчет IBM Cost of a Data Breach 2024.
Масштаб проблемы: цифры, которые заставляют задуматься.
Общая картина за последние несколько лет кардинально не изменилась. Меняются детали. Меняются инструменты. Но в проде по-прежнему встречаются одни и те же виды ошибок.
Инъекции кода по-прежнему остаются одной из самых распространенных проблем в веб-безопасности. Эта проблема существует с 90-х годов. Она объясняется практически на каждом курсе по безопасности. Она документирована, протестирована и легко демонстрируется. Она по-прежнему ежедневно встречается в работающих приложениях.
Сбои аутентификации так же распространены: подбор учетных данных, фиксация сессии, отсутствие многофакторной аутентификации при критически важных действиях, короткий срок действия сессии, предсказуемые сценарии после входа в систему. Данные OWASP постоянно показывают, что проблемы с аутентификацией ежегодно затрагивают большое количество приложений.
Криптографические ошибки тоже кажутся скучными, пока не причинят ущерб: MD5 для паролей, ключи в исходном коде, слабые настройки TLS, незашифрованное локальное хранилище, самодельная криптография. Странно то, что правильные решения существуют уже много лет. Они хорошо задокументированы. Команды все еще откладывают их внедрение, потому что пока все работает.
Нарушение контроля доступа в веб-приложениях особенно проблематично. По данным OWASP, проблемы с контролем доступа встречаются более чем в 90 процентах протестированных приложений. Именно поэтому эта категория продолжает оставаться в числе 10 самых распространенных проблем веб-приложений.
Мобильная версия выглядит не лучше.
На основе руководства OWASP по тестированию безопасности мобильных устройств и типичных результатов аудита мобильных приложений мы видим ту же закономерность:
Большинство мобильных приложений содержат хотя бы одну уязвимость из списка «ТОП-10 мобильных приложений».
Небезопасное локальное хранилище - одна из наиболее распространенных проблем.
Токены аутентификации по-прежнему хранятся в незащищенном хранилище.
Локальные базы данных часто не зашифрованы.
В ходе статического анализа APK-файлов жестко закодированные ключи API обнаруживаются гораздо чаще, чем хотелось бы признать командам разработчиков.
Последствия не являются теоретическими. Утечки персональных данных, финансовые потери, штрафы со стороны регулирующих органов и ущерб репутации - это обычные последствия старых, заезженных ошибок в сфере безопасности.
В отчете IBM «Стоимость утечки данных в 2024 году» приводится полезный ориентир: средняя стоимость утечки данных составила 4,88 миллиона долларов, а среднее время на выявление и локализацию утечки - около 194 дней.
Последний показатель - это тот, на который я всегда обращаю внимание. Система может быть неисправна в течение нескольких месяцев, прежде чем команда поймет, что произошло.
OWASP Top 10: сравнение двух списков
Прежде чем вдаваться в детали, полезно сопоставить оба мира.

Разные платформы по-прежнему страдают от одних и тех же фундаментальных недостатков.
Слабые системы контроля доступа и сбои аутентификации позволяют злоумышленникам действовать от имени другого пользователя или получать доступ к данным, которые им не предназначены.
Плохая криптография делает конфиденциальные данные читаемыми. В веб-среде это может быть слабое хеширование, некорректный TLS или утечка ключей. В мобильных приложениях это часто означает незашифрованное локальное хранилище, токены, размещенные не в том месте, или секреты, передаваемые внутри исполняемого файла.
Небезопасная конфигурация создает дополнительные точки входа на обеих платформах.
Проблемы с цепочкой поставок приводят к тому, что код третьих лиц становится вектором атаки еще до того, как наш собственный код попадет в производство.
Проблемы с проверкой входных данных и внедрением кода остаются хроническими везде, где пользовательские данные попадают в интерпретатор без безопасной обработки. При этом не имеет значения, является ли интерпретатор SQL, HTML, JavaScript, командой оболочки, запросом NoSQL или мостом WebView.
Разница заключается в центре тяжести.
В веб-разработке уникальные угрозы сосредоточены вокруг серверной логики, инфраструктуры и мониторинга логов. Небезопасная архитектура означает, что уязвимость заложена в сам бизнес-процесс. Сбои в работе программного обеспечения и обеспечении целостности данных затрагивают конвейеры CI/CD, механизмы обновления и доставку артефактов. Слабое логирование и мониторинг делают атаки невидимыми. Неправильный обработчик исключений может раскрыть трассировки стека, внутренние пути, версии фреймворков и приблизительную схему инфраструктуры.
В мобильных приложениях риски смещаются в сторону самого устройства и экосистемы приложения. Небезопасная связь через межпроцессное взаимодействие, диплинки, и межпроцессные интенты создают векторы атак, которых нет в классических веб-приложениях. Слабая защита бинарных файлов позволяет злоумышленникам проводить реверс инжиниринг приложения, извлекать захардкоженные ключи или перепаковывать APK с вредоносным содержимым. Слабые средства контроля конфиденциальности отражают природу разрешений в мобильных приложениях: местоположение, камера, контакты, микрофон и сторонние SDK могут раскрывать больше информации, чем ожидает пользователь.
Вот почему веб-разработчик и мобильный разработчик могут говорить о безопасности, но при этом подразумевать разные вещи.
Архитектура определяет модель угроз.
Разница между OWASP Web и OWASP Mobile становится гораздо очевиднее, когда мы рассматриваем архитектуру.
Типичное веб-приложение выглядит примерно так:

Основное:
В веб-среде злоумышленник обычно атакует сервер через браузер.
В мобильных приложениях злоумышленник может атаковать само приложение.
Они могут загрузить его, декомпилировать, модифицировать, запустить на устройстве с root-доступом, подключиться к прокси-серверу, перехватывать методы среды выполнения и проверять локальные файлы.
В то же время, бэкэнд часто является общим. Мобильное и веб приложения могут работать с одним и тем же API. Уязвимость на стороне сервера опасна для обоих.
Вот почему мне не нравится вопрос о том, что безопаснее: веб или мобильное приложение. Лучше спросить, в чем мы можем доверять клиенту, и что произойдет, если это доверие окажется необоснованным.
Общие уязвимости: когда риски одинаковы.
1. Аутентификация и авторизация
Это самый большой блок проблем, и он одинаково важен для обеих платформ.
Типичная ошибка - проверка доступа только на стороне клиента.
Проверка роли на стороне клиента в JavaScript

Механизм имеет значение. Сервер извлекает пользователя из доверенного токена или сессии, проверяет роль и только после этого возвращает данные.
Та же проблема наблюдается и в мобильных API.
IDOR: изменение чужих данных через мобильный API

Здесь клиент больше не решает, чьи данные ему нужны. Решение принимает бэкэнд на основе подтвержденной личности.
Это выглядит менее гибким. Но это также безопаснее.
Безопасное управление сессиями в PHP

HttpOnly ограничивает кражу cookie-файлов через XSS. Secure предотвращает отправку cookie-файлов по обычному HTTP. SameSite добавляет уровень защиты от CSRF. Восстановление сессии после входа в систему снижает риск фиксации сессии. Timeout ограничивает срок действия украденной сессии.
Все это неинтересно. Именно поэтому команды это пропускают.
2. Инъекции
Внедрение кода происходит везде, где пользовательский ввод достигает интерпретатора.
В качестве интерпретатора могут использоваться SQL, NoSQL, HTML, JavaScript, команды оболочки, LDAP, XPath, шаблонизатор или мост WebView.
SQL-инъекция в Python

Аналогичные ошибки встречаются и при рендеринге HTML.
XSS в JavaScript / PHP

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

WebView обладает мощными возможностями, поскольку обеспечивает гибкость. Однако эта же гибкость расширяет поверхность атаки.
3. Небезопасные зависимости и цепочка поставок
Атаки на цепочки поставок неслучайно получили отдельную категорию в списках для веб- и мобильных приложений.
Взлом одного пакета программного обеспечения может предоставить злоумышленнику доступ к тысячам организаций одновременно.
Типичная атака на цепочку поставок выглядит следующим образом:

Реальные примеры уже вошли в отраслевую память:
В 2020 году произошла кибератака на компанию SolarWinds, которая разрабатывает для предприятий программное обеспечение для управления сетями, системами и инфраструктурой. Около 18 000 организаций получили скомпрометированное обновление легитимного программного обеспечения.
Log4Shell 2021 - критическая уязвимость в широко используемой библиотеке Java.
xz-utils 2024, где бэкдор чуть не проник в основные дистрибутивы Linux.
Урок не в том, что зависимости - это плохо. Это слишком примитивно.
Урок заключается в том, что зависимости - это внешний код, который выполняется внутри зоны нашего доверия.
Как мы проверяем зависимости: SCA
Практическое решение - анализ дерева пакетов.
Для проектов на JavaScript и Node.js выполните:
npm audit
Для Python:
pip-audit
Для PHP:
composer audit
или используйте такие инструменты, как local-php-security-checker.
Мы также добавляем в репозиторий Dependabot или аналогичный инструмент, а затем настраиваем CI/CD таким образом, чтобы High/Critical уязвимости приводили к сбою сборки.
Это не устраняет всех рисков в цепочке поставок. Но это обеспечивает нам контролируемый процесс, вместо того чтобы надеяться, что никто не заметит уязвимую упаковку.
Хороший процесс SCA скучен в самом лучшем смысле этого слова. Он превращает риски, связанные с зависимостями, в рутинное техническое обслуживание.
Уязвимости, специфичные для мобильных устройств
Локальное хранилище: иерархия безопасности
Наиболее распространенная ошибка в сфере мобильной безопасности - хранение конфиденциальных данных в местах, доступных любому пользователю рутованного телефона.

Первое ошибочное предположение обычно заключается в следующем: песочницы приложения достаточно.
Песочница помогает. Но она не защищает от рута, джейлбрейка, резервного копирования, логов, скриншотов, вредоносного ПО, отладочных сборок или неосторожного поведения SDK.
Правильное хранение токенов на Android с помощью EncryptedSharedPreferences

iOS Keychain на Swift

Механизм тот же: секреты хранятся в защищенном хранилище, предоставляемом платформой, а не в обычных файлах настроек.
Компромисс по-прежнему существует. Безопасное хранение данных не всегда удобно. Миграция, запросы биометрии, поведение при резервном копировании, восстановление устройства и логика обновления токенов становятся более сложными.
Такая сложность обходится дешевле, чем утечка учетных данных.
Привязка сертификатов: защита сетевого трафика
Без SSL pinning любой, кто имеет доступ к сети или устройству, может попытаться перехватить трафик через прокси-сервер.
В процессе разработки мы часто делаем это намеренно с помощью Burp Suite или Charles Proxy. Тот же метод становится опасным, когда злоумышленник контролирует устройство или может установить доверенный центр сертификации.

Настройка сетевой безопасности Android

Pinning сертификата помогает если у атакующего каким-то образом оказался валидный сертификат от доверенного CA. Обычный HTTPS в такой ситуации ничего не заметит, он же просто проверяет, подписан ли сертификат кем-то из доверенных центров. А если в приложении зашит конкретный сертификат сервера, то оно сверит и откажется работать с чужим, даже если тот формально валиден.
Обязательно ли это делать? Нет. HTTPS сам по себе закрывает почти все обычные атаки, и без pinning приложение вполне безопасно для большинства случаев. Заморачиваются с ним обычно там, где на кону реальные деньги или чувствительные данные: банки, платежные сервисы. Минус один, но неприятный: усложняется ротация сертификатов. Забыл заранее прописать backup пин и после планового обновления сертификата на проде приложение просто откажется работать, пока не выйдет новая версия в сторе.
Бинарная защита: проблема, характерная только для мобильных устройств.
В веб-разработке исходный код на стороне сервера не предоставляется пользователю.
На мобильных устройствах APK или IPA-файл можно загрузить из магазина и проанализировать.
Для Android отправная точка зачастую тривиальна:

Важное ограничение легко забыть: сокрытие - это не секретность.
Это затрудняет анализ. Это не гарантирует сохранность передаваемых секретов.
Все, что находится внутри клиентского приложения, следует рассматривать как потенциально видимое.
Веб-безопасность
Небезопасная конфигурация: ошибки инфраструктуры
По мере усложнения инфраструктуры небезопасная конфигурация стала одной из самых болезненных категорий веб-технологий. Kubernetes, облачные хранилища, микросервисы, reverse proxy, CDN, очереди, кэши и так далее - все это создает ситуации, когда небольшая ошибка может привести к публичной утечке информации.

Причин подобных проблем множество. Начиная от спешки и слепого копирования дефолтной документации и заканчивая отсутствием чек-листа проверки перед выкатом на прод.
Минимальное количество заголовков безопасности в Express.js

Это не универсальная конфигурация. Список заголовков зависит от предметной области приложения.
Принцип стабилен: защищенные заголовки - это не украшение. Они являются частью контракта приложения.
Небезопасный дизайн: что не исправит рефакторинг
Эта категория OWASP появилась в 2021 году и сохранилась не просто так.
Некоторые уязвимости возникают не из-за неудачной строки кода, а из-за неправильного решения в отношении продукта или архитектуры.
Простой пример: система принимает цену товара от клиента.
Никакая проверка входных данных не сможет это должным образом исправить. Дизайн неверен. Сервер должен рассчитывать цену, исходя из состояния доверенного продукта, статуса пользователя, скидок, налогов и правил.
Еще один пример: восстановление пароля с помощью секретных вопросов.
Реализация может быть и неплохой. Но сама идея пока слабая.
Хороший шаблон проектирования безопасности - это запрет по умолчанию.

Этот шаблон выглядит более строгим. В этом и суть.
В сфере безопасности неявное разрешение - это долгосрочный долг. Как правило, его стоимость возрастает по мере развития продукта.
Что дают нам платформы и чего они нам не дают.
И мобильные, и веб-платформы предоставляют полезные средства обеспечения безопасности. Но они не завершают начатое нами дело.

Платформа способна предотвратить целые категории ошибок. Это хорошо.
Платформа не может определять, что разрешено в продукте, где проходит граница доверия, что должна проверять серверная часть, какие события должны регистрироваться или что происходит, когда злоумышленник контролирует клиент.
Это по-прежнему остается инженерной работой.
Выводы
Проблема не в платформе. Проблема в подходе.
Большинство уязвимостей не являются чем-то экзотическим. Жестко закодированные ключи, отсутствие проверки подлинности, слабое хеширование, неработающие проверки доступа, открытые параметры отладки и небезопасное хранилище существуют не потому, что разработчики никогда не слышали о безопасности. Они существуют потому, что эта функция работает, а вопросы безопасности откладываются на потом.
События происходят позже.
Ответственность за бэкэнд полностью лежит на всей инфраструктуре.
Мобильное приложение и веб-интерфейс могут работать с одним и тем же API. Если API уязвим к IDOR, то уязвимы оба клиента. Если API доверяет идентификатору пользователя, полученному от клиента, то уязвимы оба клиента. Если сервер не обеспечивает контроль доступа, проверка пользовательского интерфейса не сохранит его.
Безопасность на стороне сервера важнее, чем защита конкретного клиента.
С точки зрения безопасности клиентских приложений, в мобильной версии ситуация сложнее.
Веб-разработчику обычно не нужно думать о декомпиляции серверного кода или краже локальных данных после физического доступа к устройству пользователя.
Это делает мобильный разработчик. Выбор хранилища, защита бинарных файлов, привязка сертификатов, детекция root и джейлбрейка, шифрование локальной базы данных, защита скриншотов и поведение SDK - все это становится частью работы.
Управление цепочками поставок – это новая норма.
В веб-разработке npm является частью системы. В мобильных приложениях частью системы являются CocoaPods, Maven, плагины Gradle, SDK и транзитивные зависимости.
SCA и SBOM - это уже не просто модные дополнения, а способ узнать, что мы отправляем.
О ведении журналов и мониторинге легко забыть.
OWASP выделяет эту категорию не просто так.
Система без мониторинга безопасности может быть уже скомпрометирована и при этом выглядеть работоспособной. Среднее время обнаружения и локализации нарушений снова и снова подтверждает одно и то же: команды часто обнаруживают инциденты слишком поздно.
Приложение, не обеспечивающее должный мониторинг, не работает бесшумно. Оно слепо.
Практический контрольный список
Бэкенд
Используйте параметризованные запросы или ORM везде, где пользовательский ввод доходит до этапа обработки запроса.
Проверяйте авторизацию на сервере, а не на клиенте.
Идентификатор пользователя следует брать из токена или сессии, а не из полей тела запроса.
Добавьте ограничение скорости запросов к конечным точкам API для входа в систему, регистрации, восстановления паролей и доступа к конфиденциальным данным.
Регистрируйте события безопасности и связывайте их с оповещениями.
Регулярно проверяйте зависимости с помощью npm audit, pip-audit, composer audit, Dependabot или аналогичных инструментов.
Рассматривайте как веб-, так и мобильные клиенты как ненадежных потребителей API.
Веб
По возможности используйте CSP без параметра unsafe-inline для скриптов.
Для файлов cookie аутентификации используйте SameSite=Strict или соответствующий режим SameSite.
Установите флаги HttpOnly и Secure для файлов cookie.
Используйте токены CSRF для изменения состояния форм и запросов там, где это необходимо.
Включите HSTS с помощью includeSubDomains, когда домен будет готов.
Не используйте innerHTML с данными, контролируемыми пользователем.
Мобилка
Сохраняйте токены только в Keystore или Keychain, а не SharedPreferences или UserDefaults.
Используйте привязку сертификатов с резервной привязкой и реальным календарем ротации сроков действия.
Включите R8 или ProGuard для релизных сборок.
Используйте флаг FLAG_SECURE на экранах с конфиденциальными данными, когда необходима защита от создания скриншотов.
Не следует скрывать секреты в коде, даже в зашифрованном виде.
Используйте обнаружение рута и джейлбрейка в качестве дополнительного сигнала, а не как основную защиту.
Размещайте критически важную бизнес-логику на сервере.
Что почитать и изучить дальше
Руководство по тестированию веб-безопасности OWASP (WSTG).
OWASP Mobile Application Security (MAS) , включая MASVS, MASTG и MAS Checklist.
OWASP MobSF - автоматизированный статический и динамический анализ мобильных приложений.
Список самых опасных классов уязвимостей CWE/SANS Top 25 на различных платформах.
Apple Platform Security - официальная документация по механизмам безопасности iOS и платформ Apple.
Руководство по безопасности Android - официальные рекомендации для разработчиков Android.
Академия веб-безопасности PortSwigger : бесплатные практические занятия по выявлению веб-уязвимостей.
Итоговый вывод
Для меня главный вывод таков: безопасность веб-сайтов и мобильных устройств не следует сравнивать как две изолированные сферы.
Бэкенд обычно общий. Граница доверия обычно размыта. Клиент всегда не заслуживает доверия, но на мобильных устройствах злоумышленник может также взломать клиентскую часть.
Создание безопасной системы начинается с того момента, когда мы перестаем спрашивать, что безопаснее - веб или мобильное приложение, и начинаем спрашивать, где мы доверяем клиенту, почему мы ему доверяем и что ломается, когда это доверие оказывается необоснованным.
Самые интересные открытия в области безопасности обычно скрываются за пределами аккуратных таблиц OWASP. Если вы сталкивались с необычным случаем во время тестирования на проникновение или аудита, мне было бы очень интересно об этом услышать.
Автор
Илья Новиков, технический директор.
Соавторы
- Данил Мануйлов, Максим Быков, Линар Огай, Максим Савченко, тимлиды.
- Тимофей Ищенко, техлид Frontend-разработки (направление web) @Is_Tim.
- Даниил Николаев, Frontend-разработчик (направление web).
