mobilegame-qasecurityeconomyqa

Как тестировать экономику мобильной игры и ловить читеров

В F2P-игре экономика — это и есть бизнес: монеты, кристаллы, энергия, лутбоксы, IAP. Поэтому она же — главная мишень. Один дюп-баг с валютой или чит на «бесконечные монеты» — и внутриигровой магазин, на котором держится выручка, теряет смысл: зачем платить, если можно нафармить читом. Тестировать экономику надо не как «работает ли кнопка купить», а как защиту от злоупотреблений. Ниже — атаки, которые QA обязан прогнать сам.

Золотое правило: клиент врёт

Любое значение, пришедшее с устройства, — потенциально подделано. Баланс, «я купил», «я прошёл уровень», «мне начислить награду» — всё это должно проверяться и считаться на сервере, а клиент лишь отображает. Главный тест: перехватываешь запрос (Proxyman/Charles/mitmproxy) и меняешь — шлёшь coins += 1000, level = 99, reward = legendary. Сервер должен отбить (403/ошибка валидации), а не радостно начислить. Если начисляет — экономика дырявая, и никакие клиентские проверки её не спасут.

Дюп-баги и идемпотентность

Классика — задвоение награды/валюты на стыке «действие → сеть → подтверждение»:

  • Двойной тап по «Купить» / «Забрать награду» — два запроса. Должна отработать ровно одна операция (идемпотентность по ключу транзакции), а не списать деньги дважды или выдать награду дважды.
  • Обрыв сети mid-transaction: заплатил → соединение упало до ответа → ретрай. Не должно ни задвоить покупку, ни «съесть» её без выдачи.
  • Откат/восстановление: убил приложение в момент начисления, перезашёл — состояние должно сойтись, без дублей и без потерь.

Тест: гоняешь покупку/награду с искусственными обрывами и дабл-кликами (тротлинг сети, kill приложения) — итог всегда «ровно один раз».

Перевод часов устройства

Всё, что завязано на время, — таймеры «ждать 8ч или заплатить», ежедневные награды, энергия, кулдауны, ограниченные по времени офферы — атакуется переводом системных часов. Тест: крутишь время устройства вперёд (таймер «прошёл», награда «доступна») и назад (повторно забрать дейлик). Правильно — сервер считает время сам; устройство — не источник истины. Проверь и стык: перевёл часы, забрал награду локально, ушёл в оффлайн, вернулся — сервер должен отклонить.

Редактирование сейва

Локальный прогресс в PlayerPrefs, SharedPreferences, plist или файле сейва редактируется за минуту (rooted/jailbroken, или просто редактор). Тест: находишь, где хранится валюта/прогресс, меняешь на «999999» — что произойдёт? Чувствительные значения должны жить на сервере или быть подписаны/зашифрованы так, чтобы правка ломала подпись и откатывалась. Если игра честно поверила локальному файлу — это чит в один клик.

Отрицательный баланс, переполнение, гонки

  • Потратить больше, чем есть: купить за 100 монет, имея 50 — должно отбиться, а не уйти в минус.
  • Переполнение: зафармить/наградами загнать валюту за 2^31 (или сколько там тип) — не должно переполниться в отрицательное.
  • Race condition: два параллельных списания с одного баланса (два девайса, быстрые тапы) — сумма не должна «раздвоиться». Классика: потратить одни и те же монеты дважды одновременно.

Фейковый IAP-чек

Покупка за реальные деньги проверяется валидацией чека на сервере через App Store Server API / Google Play. Без этого фейковый или переигранный чек = бесплатная покупка. Тест: подсунуть невалидный/чужой/повторный receipt — не должно выдать товар. (Подробнее про IAP — в отдельном разборе покупок.)

Тулы читеров

Игроки используют GameGuardian, редакторы памяти, Lucky Patcher, модифицированные клиенты. Полностью на клиенте это не остановить — поэтому и нужен сервер-авторитет. Что проверить: критичное состояние (валюта, прогресс, результаты матчей) сервер пересчитывает/валидирует; аномалии (нереальный прирост, невозможный счёт) детектятся; клиентские анти-чит и обфускация — это замедление, а не защита.

Чек-лист атак на экономику

  • Подмена запроса «+валюта / +уровень / +награда» → сервер отбивает.
  • Двойной тап по покупке/награде → ровно одна операция.
  • Обрыв сети во время транзакции → без дублей и без потерь.
  • Kill приложения в момент начисления → состояние сходится.
  • Перевод часов вперёд/назад → таймеры и дейлики считает сервер.
  • Правка локального сейва (валюта/прогресс) → откат/не применяется.
  • Покупка дороже баланса → отказ, без ухода в минус.
  • Переполнение валюты → не уходит в отрицательное.
  • Параллельные списания (2 девайса/быстрые тапы) → без раздвоения.
  • Невалидный/повторный IAP-чек → товар не выдаётся.
  • Критичное состояние валидируется на сервере, не на клиенте.

Коротко — что забрать с собой

  • Экономика = деньги, поэтому тестируется как защита от злоупотреблений, а не как «кнопка купить».
  • Клиенту не верить — считать и валидировать на сервере; главный тест — подмена запроса.
  • Дюп-баги ловятся идемпотентностью: обрывы, дабл-тапы, kill → «ровно один раз».
  • Перевод часов и правка сейва — обязательные атаки; время и ценности держит сервер.
  • Отрицательный баланс, переполнение, гонки — проверять на границах.
  • IAP — только с серверной валидацией чека.

Почитать: OWASP MASVS — Mobile App Security · Apple — App Store Server API (валидация покупок) · Google Play — Billing security