Критическая уязвимость типа zero-click в Android SDK платформы Zendesk была обнаружена исследователями в рамках приватной программы bug bounty. Уязвимость позволяла злоумышленникам получать полный контроль над учетными записями поддержки и просматривать все тикеты без какого-либо взаимодействия с пользователем.
Проблема была связана с ненадежными механизмами генерации и хранения токенов в мобильном приложении Zendesk. Как выяснилось, клиентская часть для Android формировала токены аутентификации на основе трех предсказуемых элементов: идентификатора учетной записи, статического секретного ключа, вшитого в код, и хеша SHA-1 от их конкатенации. Конкретно, приложение создавало строку в формате COMPANY-<AccountID>-<Secret>, применяло к ней алгоритм SHA-1 и добавляло в начало идентификатор аккаунта, формируя токен в стиле JWT.
Поскольку идентификаторы учетных записей являются последовательными, а секретный ключ оставался неизменным и был встроен непосредственно в бинарный файл, злоумышленник мог подобрать действительные токены для любого пользователя методом перебора. После генерации такой токен отправлялся через POST-запрос на эндпоинт /access/sdk/jwt, который возвращал токен доступа, предоставляющий неограниченный доступ к API.
Исследователь использовал комбинацию статического и динамического анализа для изучения уязвимости. С помощью инструмента JADX был проведен реверс-инжиниринг SDK, в ходе которого были идентифицированы ключевые методы: ZendeskHelper.g(), отвечающий за создание и хранение токена, а также связанные API в классах ZendeskIdentityStorage и ZendeskIdentityManager. Динамическая проверка с использованием Frida подтвердила, что секретный ключ не менялся и не был привязан к устройству, а идентификационные данные сохранялись между сеансами до принудительной очистки кэша приложения.
Сетевая активность перехватывалась через Burp Suite после обхода SSL-пининга с помощью скрипта Frida. Перехваченный POST-запрос содержал только токен пользователя и возвращал многократно используемый токен доступа. Отсутствие ограничений на частоту запросов или одноразовых проверок позволяло злоумышленникам обновлять токены неограниченное количество раз.
Эксплуатация уязвимости была автоматизирована с помощью Python-скрипта, который генерировал токены, получал токены доступа и перечислял тикеты. Простой перебор идентификаторов учетных записей позволял массово компрометировать сотни тысяч аккаунтов. Для успешной атаки не требовалось действий со стороны пользователя - не нужны были фишинг или социальная инженерия, что делало уязвимость truly zero-click.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import hashlib, requests def gen_sha1(full_string): return hashlib.sha1(full_string.encode()).hexdigest() def get_access_token(user_token): url = "https://COMPANY.zendesk.com/access/sdk/jwt" resp = requests.post(url, json={"user":{"token": user_token}}) return resp.json()['authentication']['access_token'] user_id = "131070497" secret = "987sdasdlkjlakdjf" full = f"COMPANY-{user_id}-{secret}" token = f"{user_id}_{gen_sha1(full)}" access = get_access_token(token) print("Access Token:", access) |
Успешная эксплуатация предоставляла права на чтение и запись всех тикетов поддержки для целевого пользователя. Злоумышленники могли эксфильтрировать конфиденциальные данные клиентов, добавлять мошеннические тикеты или повышать привилегии в рамках экосистемы поддержки Zendesk.
После ответственного раскрытия информации компания Zendesk оперативно признала проблему и выпустила патч. Обновление включало замену статического секретного ключа на рандомизированные ключи для каждого устройства и пользователя, введение строгого ограничения на частоту запросов к эндпоинтам обмена JWT, а также усиление защиты хранилища токенов с использованием безопасного хранилища ключей Android.
Данная уязвимость нулевого клика подчеркивает критическую важность надежной генерации и управления токенами в мобильных SDK. Даже широко признанные платформы, такие как Zendesk, могут содержать высокорисковые ошибки, когда используются предсказуемые значения и статические секреты. Командам безопасности необходимо тщательно аудировать сторонние библиотеки и применять лучшие практики - включая ротацию секретов, использование аппаратно-защищенного хранилища и ограничение частоты запросов для потоков аутентификации - чтобы защититься от незаметных, но разрушительных захватов учетных записей.