Как защитить трекинг атрибуции от спуфинга SDK? Для защиты от спуфинга SDK необходимо внедрить проверку подписей запросов HMAC-SHA256 между серверами (S2S), защиту от атак повторного воспроизведения (replay) с помощью динамических нонсов, а также использовать аппаратные средства подтверждения целостности платформы.
Спуфинг SDK — это продвинутый вид мобильного мошенничества, при котором злоумышленники реверс-инжинирят протоколы мобильной телеметрии и отправляют синтетические данные об установках или событиях напрямую на эндпоинты атрибуции, не запуская приложение на физическом устройстве. В мобильной атрибуции для снижения рисков спуфинга SDK требуется двухуровневая архитектура безопасности, сочетающая криптографические подписи HMAC-SHA256 между серверами и динамические нонсы с аппаратной аттестацией целостности платформы.
| Термин | Определение | Связанная сущность | Роль в поиске |
|---|---|---|---|
| Трекинг атрибуции | Систематическая запись и проверка маркетинговых касаний и конверсий. | Партнер по мобильным измерениям | Информационный / Коммерческий |
| Спуфинг SDK | Симуляция трафика SDK на стороне сервера с использованием реверс-инжиниринга API-запросов. | Рекламное мошенничество | Технический / Информационный |
| Подпись HMAC | Аутентификационный тег HMAC, подтверждающий подлинность запроса и целостность данных. | Трекинг конверсий | Технический / Информационный |
Почему спуфинг SDK угрожает трекингу атрибуции и доходам
Проблема «призрачных установок»: расход бюджета без реальных или виртуальных устройств
При обычном рекламном мошенничестве злоумышленники используют фермы устройств или эмуляторы операционных систем для симуляции действий пользователей. Эти атаки требуют физической или вычислительной инфраструктуры для загрузки, установки и запуска приложения.
Спуфинг SDK полностью устраняет необходимость в устройствах. Мошенники анализируют сетевой протокол общения между SDK атрибуции и сервером сбора данных. Используя скрипты для генерации и отправки HTTP POST-запросов напрямую на эндпоинты атрибуции, они создают миллионы «призрачных» установок без скачивания ни одного байта кода приложения на реальное устройство.
Поскольку «призрачные» установки расходуют маркетинговый бюджет на полностью синтетические события, кампании работают неэффективно. Рекламодатели платят за установки (CPI) или действия (CPA) мошенническим источникам, истощая бюджеты, не привлекая при этом ни одного реального пользователя.
Фабрикация ценных конверсий: внутриигровые покупки, регистрации и достижение уровней
Ранние методы спуфинга фокусировались на установках. Однако современные ботнеты имитируют полноценный жизненный цикл пользователя, отправляя телеметрию в течение нескольких дней.
Реверс-инжиниринг эндпоинтов событий позволяет мошенникам отправлять синтетические постбеки о важных конверсиях:
- Регистрации аккаунтов: Создание фальшивых профилей для получения бонусов за регистрацию (CPA).
- Прохождение уровней: Симуляция завершения обучения или достижения игровых этапов для выполнения условий по удержанию пользователей.
- Синтетические покупки: Отправка поддельных чеков о транзакциях, чтобы обмануть платформы аналитики и завысить показатель возврата инвестиций (ROAS), заставляя алгоритмы направлять еще больше средств на мошеннические площадки.
Разрушение доверия: как синтетическая телеметрия вредит маркетинговому ROI
Когда в систему атрибуции попадает поддельная телеметрия, отчеты искажаются. Команды аналитиков обучают модели LTV и алгоритмы автоматического биддинга на ложных сигналах, в результате чего система оптимизируется под источники, которые не приносят реальной ценности.
Криптографическая аутентификация позволяет шлюзу сбора данных отклонять подозрительные запросы еще до их обработки. Хотя валидный тег HMAC подтверждает источник данных и их целостность, он не доказывает, что конверсия произошла в реальности. Сочетание криптографической проверки и поведенческого аудита обеспечивает необходимый эшелонированный уровень защиты для чистоты данных атрибуции.
Разработчики, которым нужны легкие SDK для сбора телеметрии и атрибуции, могут ознакомиться с доступными пакетами по ссылке mobile analytics SDK package.
Как спуфинг SDK имитирует конверсии без физических устройств
Механика реверс-инжиниринга протоколов: прокси-перехват, декомпиляция и маппинг API
Для осуществления спуфинга злоумышленники разбирают клиент приложения и библиотеки аналитики с помощью следующих этапов:
- Статическая декомпиляция: Использование декомпиляторов (например, JADX для Android или Ghidra для iOS) для анализа пакетов приложений (APK или IPA), поиска эндпоинтов API, схем параметров и захардкоженных токенов аутентификации.
- Перехват через прокси (MitM): Направление трафика реального устройства через локальные прокси-инструменты (например, Charles Proxy или mitmproxy) с установленными корневыми сертификатами для расшифровки TLS-трафика и анализа JSON-данных.
- Динамическая подмена (Runtime Hooking): Применение фреймворков для инструментации (например, Frida или Xposed) для обхода SSL-пиннинга, анализа оперативной памяти и извлечения криптографических ключей.
После понимания структуры протокола злоумышленник кодирует ее в автоматизированные скрипты, генерируя запросы, которые имитируют легитимный трафик на незащищенных эндпоинтах.
[Сервер ботов] ──► [Сгенерированный payload] ──► [Поддельный HTTPS POST] ──► [Эндпоинт атрибуции]
│ │
├─► Имитация идентификаторов (GAID / IDFA) ▼
├─► Повтор захваченных сетевых параметров [Атрибуция записана]
└─► Отправка симуляции покупок (Выплата за конверсию)
Анатомия поддельного запроса: синтез аппаратных хэшей, таймстемпов и рекламных идентификаторов
Поддельный пакет телеметрии содержит сгенерированные или повторно отправленные метаданные, имитирующие работу мобильного устройства:
- Рекламные идентификаторы: Ротация идентификаторов (например, синтетических GAID или IDFA) для имитации разных пользователей.
- Метаданные устройства: Программная подмена моделей устройств, архитектуры процессора, разрешений экрана и версий ОС для создания иллюзии естественного разнообразия устройств.
- Сетевые параметры: Маршрутизация запросов через коммерческие прокси или VPN для соответствия географии рекламной кампании.
- Временные метки (Timestamps): Фальсификация последовательных меток времени для имитации естественных задержек между установкой и конверсией.
Поскольку незащищенные шлюзы проверяют только структуру JSON и наличие параметров, они не могут определить, поступил ли запрос от реальной мобильной ОС или от скрипта в дата-центре.
Ошибка встраивания секретов в клиент: почему хранение API-ключей внутри приложения ненадежно
Типичная архитектурная ошибка в мобильной безопасности — использование статических секретных ключей, зашитых непосредственно в код клиента (например, хардкод строки в классе Application на Android или бандле iOS).
Мобильные приложения работают в недоверенных средах, контролируемых пользователем. Любой ключ в APK или IPA может быть извлечен путем статической декомпиляции, дампов памяти или динамической инструментации. После получения доступа к секрету злоумышленники могут подписывать синтетические запросы, что делает статические подписи на стороне клиента бесполезными.
Защита трекинга атрибуции требует отделения уязвимых клиентских секретов от защищенных границ сервер-сервер и использования аппаратной аттестации платформ.

Криптографическая архитектура подписи запросов HMAC между серверами
Отделение секретов клиентского приложения от границ доверия S2S
Корпоративная архитектура защиты от спуфинга устанавливает строгое разделение между клиентской телеметрией и серверными постбеками:
- Уровень интеграции S2S: Прямые API-интеграции между рекламными сетями, DSP и эндпоинтами атрибуции работают в доверенной серверной среде. Секретные ключи хранятся исключительно в системах управления ключами (KMS) или аппаратных модулях безопасности (HSM) и никогда не передаются в клиентские бинарные файлы.
- Уровень клиентской телеметрии: Мобильные клиенты полагаются на криптографические подтверждения уровня платформы (такие как Google Play Integrity или Apple App Attest), а не на статические секреты, для предоставления доказательств подлинности исполнения кода.
Конструирование канонической строки: структура данных для предотвращения подмены параметров
Чтобы исключить подмену данных и обеспечить детерминированную проверку подписи, отправляющий сервер и принимающий шлюз должны собрать идентичную каноническую строку перед вычислением криптографического тега.
Протокол определяет четкое представление цели запроса:
- Версия протокола: Заголовок идентификатора протокола (
X-Signature-Version: v1). - HTTP-метод: Стандартизированная строка в верхнем регистре (например,
POST). - Путь URI запроса: Абсолютный нормализованный путь к эндпоинту, без параметров запроса (например,
/api/v1/attribution/event). - Таймстемп: Unix-время в секундах (
X-Timestamp). - Нонс: Уникальная криптографическая случайная строка с энтропией не менее 128 бит (
X-Nonce), состоящая только из буквенно-цифровых символов. - Идентификатор ключа: Версия ключа (
X-Key-Id), соответствующая активному или льготному периоду действия ключа. - Хэш сырого тела запроса: Hex-кодированный хэш SHA-256, вычисленный непосредственно по байтам HTTP-тела (
SHA256(RawBodyBytes)).
Каноническая строка собирается с использованием разделителя (|) и кодируется в UTF-8:
Математическое описание подписи HMAC-SHA256
Аутентификационный тег HMAC вычисляется с использованием алгоритма HMAC-SHA256 в соответствии с IETF RFC 2104, применяя секретный ключ к канонической строке:

Приведенная ниже реализация на Python демонстрирует промежуточное ПО (middleware) для верификации HMAC-SHA256 с поддержкой жизненного цикла ключей (активные, льготный период, отозванные), асимметричными окнами таймстемпов и атомарным управлением состоянием нонсов:
```python
# [CODE_BLOCK_01] Middleware на Python для проверки S2S HMAC-SHA256 подписи
import hmac
import hashlib
import time
import redis
from enum import Enum
from typing import Dict, Tuple, Optional, Set
class KeyStatus(Enum):
ACTIVE = "active" # Допустимо для подписи и проверки
GRACE_PERIOD = "grace_period" # Допустимо для проверки при ротации; не рекомендуется для подписи
REVOKED = "revoked" # Скомпрометировано или отозвано; все проверки отклоняются
EXPIRED = "expired" # Срок действия истек; проверка отклоняется
class KeyRecord:
def __init__(self, key_id: str, secret: str, status: KeyStatus):
self.key_id = key_id
self.secret = secret
self.status = status
class KeyProvider:
"""
Абстрактный интерфейс для разрешения ключей и их статусов из KMS/HSM.
"""
def get_key_record(self, partner_id: str, key_id: str) -> Optional[KeyRecord]:
raise NotImplementedError
class MemoryKeyProvider(KeyProvider):
"""
Пример поставщика ключей в памяти. В продакшене используйте KMS или HSM.
"""
def __init__(self, key_registry: Dict[str, Dict[str, KeyRecord]]):
self.key_registry = key_registry
def get_key_record(self, partner_id: str, key_id: str) -> Optional[KeyRecord]:
return self.key_registry.get(partner_id, {}).get(key_id)
class AttributionSecurityMiddleware:
def __init__(
self,
key_provider: KeyProvider,
redis_client: redis.Redis,
max_past_age_seconds: int = 300,
max_future_skew_seconds: int = 30
):
"""
Инициализация middleware для S2S верификации и защиты от атак повтора.
:param key_provider: Провайдер ключей
:param redis_client: Хранилище (Redis) для отслеживания уникальности нонсов
:param max_past_age_seconds: Максимальное время «прошлости» запроса
:param max_future_skew_seconds: Допуск на рассинхронизацию часов
"""
self.key_provider = key_provider
self.redis = redis_client
self.max_past_age_seconds = max_past_age_seconds
self.max_future_skew_seconds = max_future_skew_seconds
self.nonce_ttl_seconds = max_past_age_seconds + max_future_skew_seconds + 30
def verify_request(
self,
partner_id: str,
http_method: str,
uri_path: str,
headers: Dict[str, str],
raw_body: bytes
) -> Tuple[bool, Optional[str]]:
"""
Выполняет криптографическую проверку и предотвращение атак повтора.
:return: (is_valid, error_code)
"""
signature = headers.get("X-Signature")
timestamp_str = headers.get("X-Timestamp")
nonce = headers.get("X-Nonce")
key_id = headers.get("X-Key-Id")
sig_version = headers.get("X-Signature-Version", "v1")
if not signature or not timestamp_str or not nonce or not key_id:
return False, "MISSING_SECURITY_HEADERS"
if sig_version != "v1":
return False, "UNSUPPORTED_SIGNATURE_VERSION"
if not (16 <= len(nonce) <= 64 and nonce.isalnum()):
return False, "INVALID_NONCE_FORMAT"
try:
request_timestamp = int(timestamp_str)
except ValueError:
return False, "INVALID_TIMESTAMP_FORMAT"
current_time = int(time.time())
age_seconds = current_time - request_timestamp
future_skew_seconds = request_timestamp - current_time
if age_seconds > self.max_past_age_seconds or future_skew_seconds > self.max_future_skew_seconds:
return False, "TIMESTAMP_OUT_OF_BOUNDS"
key_record = self.key_provider.get_key_record(partner_id, key_id)
if not key_record:
return False, "UNKNOWN_KEY_ID"
if key_record.status == KeyStatus.REVOKED:
return False, "REVOKED_KEY_ID"
elif key_record.status == KeyStatus.EXPIRED:
return False, "EXPIRED_KEY_ID"
body_sha256 = hashlib.sha256(raw_body).hexdigest()
canonical_string = f"v1|{http_method.upper().strip()}|{uri_path.strip()}|{request_timestamp}|{nonce}|{key_id}|{body_sha256}"
expected_signature = hmac.new(
key=key_record.secret.encode("utf-8"),
msg=canonical_string.encode("utf-8"),
digestmod=hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature.lower(), expected_signature.lower()):
return False, "INVALID_SIGNATURE"
nonce_key = f"s2s_nonce:{partner_id}:{nonce}"
is_nonce_unique = self.redis.set(
name=nonce_key,
value="1",
ex=self.nonce_ttl_seconds,
nx=True
)
if not is_nonce_unique:
return False, "REPLAY_ATTACK_DETECTED"
return True, None
Рабочие процессы проверки подписей и стандартизация ответов
Шлюз атрибуции выполняет последовательную проверку входящих запросов:
- Извлечение заголовков: Чтение параметров безопасности.
- Проверка свежести таймстемпа: Сверка с внутренним временем (допуск 300с назад, 30с вперед). При ошибке возвращается
HTTP 401 Unauthorized. - Разрешение ключа: Проверка статуса ключа (активен, отозван, истек).
- Верификация тега: Пересчет HMAC-SHA256 и сравнение с переданным значением.
- Атомарное потребление нонса: Запись нонса в Redis. Если нонс уже существует, запрос отклоняется как
REPLAY_ATTACK_DETECTED.
Проверка подписи HMAC до проверки нонса защищает кэш от отравления и DoS-атак.
Защита от атак повтора: кэширование нонсов и временные окна
Механика атак повтора
Даже при криптографической аутентификации злоумышленники могут перехватить валидный подписанный запрос и отправлять его тысячи раз. Без защиты от повторов сервер примет каждый запрос как легитимный.
Применение асимметричных окон таймстемпа
Таймстемп в запросе позволяет серверу вычислять разницу Δt:
- Максимальное время «прошлости»: ≤ 300 секунд (старые запросы отклоняются).
- Максимальный допуск вперед: ≤ 30 секунд (корректировка на рассинхрон часов).
Распределенное хранение нонсов в Redis
Каждый запрос должен содержать уникальный нонс (случайная строка, минимум 128 бит). Сервер проверяет нонс в Redis: если он уже существует, запрос отклоняется.
Redis-команда: SET key "1" EX 360 NX. Если результат nil — нонс повторный, доступ запрещен.
[Входящий запрос]
│
▼
[1: Проверка заголовков] ──► [Отказ 401]
│
▼
[2: Проверка таймстемпа] ──► [Отказ 401]
│
▼
[3: Проверка ключа] ──► [Отказ 401]
│
▼
[4: Валидация HMAC] ──► [Отказ 401]
│
▼
[5: Атомарная проверка нонса (Redis SET NX)] ──► [Отказ 401]
│
▼
[6: Событие атрибуции принято]

Сравнительная оценка механизмов защиты
| Уровень | Механизм | Уязвимость | Ограничения |
|---|---|---|---|
| Обфускация клиента | Шифрование строк, ProGuard | Затрудняет декомпиляцию | Неэффективно против Frida/Xposed |
| Секреты клиента | Вшитые симметричные ключи | Базовая проверка | Ключи извлекаются из памяти |
| S2S подпись | HMAC-SHA256 | Безопасность вебхуков | Требует общих секретов |
| Защита от повторов | Нонсы в Redis | Блокирует переотправку | Требует Redis |
| Аттестация платформы | Play Integrity / App Attest | Доказательство подлинности | Зависимость от вендора |
Как аппаратная аттестация подтверждает подлинность клиента
Поскольку статические ключи в мобильных приложениях уязвимы, современные ОС предоставляют аппаратные сервисы аттестации. Сервер проверяет эти аппаратные подтверждения, доказывая, что запрос исходит из немодифицированного приложения на физическом устройстве.
Android: Google Play Integrity API
Интеграция API позволяет оценивать целостность устройства и приложения через токены. Backend проверяет токены, анализируя вердикты: appRecognitionVerdict (подлинность бинарного файла) и deviceRecognitionVerdict (уровень безопасности устройства).
iOS: App Attest и DeviceCheck
Apple App Attest использует Secure Enclave для создания неэкспортируемого ключа. Сервер проверяет аттестацию ключа, а затем подтверждает подлинность событий через подписи, генерируемые этим ключом. DeviceCheck дополняет это возможностью хранения состояния устройства на стороне Apple.
Интеграция в пайплайн атрибуции
Токены аттестации объединяются с параметрами атрибуции. Сочетание S2S HMAC с аппаратной аттестацией создает end-to-end защиту, значительно повышая стоимость атак для злоумышленников.

Когда необходима продвинутая защита от спуфинга
- Высокие CPA-выплаты: Программы с большими бонусами за целевые действия (финансы, подписки, депозиты).
- Объемные партнерские сети: Где низка прозрачность паблишеров.
- Расхождения в данных: Когда статистика атрибуции сильно завышена по сравнению с доходами в базе данных.
Распространенные заблуждения
- Миф 1: HTTPS достаточно: HTTPS защищает данные при передаче, но не проверяет личность отправителя. Скрипт может успешно установить HTTPS-сессию.
- Миф 2: Обфускация кода предотвращает спуфинг: Это лишь усложняет анализ, но не защищает от динамического анализа (Frida) и анализа трафика.
Часто задаваемые вопросы (FAQ)
Чем спуфинг SDK отличается от мошенничества с эмуляторами?
Почему хранение ключа внутри мобильного приложения небезопасно?
Как динамические нонсы предотвращают атаки повтора?
Итоги и рекомендации
Защита трекинга атрибуции от спуфинга требует отказа от статических ключей в пользу двухуровневой архитектуры безопасности. Спуфинг SDK позволяет фабриковать конверсии без реальных устройств, размывая бюджет и искажая эффективность кампаний.
Надежный контур защиты строится на базе подписей HMAC-SHA256, кэширования нонсов для защиты от атак повтора и аппаратной аттестации (Play Integrity, App Attest). Платформы уровня OpoInstall предоставляют инфраструктуру для проверки подлинности запросов и защиты от синтетического мошенничества.
Чтобы понять, как криптографическая безопасность может защитить ваши маркетинговые кампании, изучите руководство по реализации атрибуции или настройте интеграцию в консоли разработчика OpoInstall.
Материалы по теме
-
Концепции: Рекламное мошенничество, Спуфинг SDK, Атрибуция, Криптографическая подпись, Защита от атак повтора, Управление нонсами
-
Технологии: HMAC-SHA256, Google Play Integrity API, Apple App Attest, Redis, Вебхуки S2S
-
API и интерфейсы: Google Play Integrity API, Apple DeviceCheck / App Attest, Интерфейсы настройки безопасности OpoInstall S2S
-
Документация:
Share this article



