Не так давно шумели новости о активации in-app покупок бесплатно и даже без джейлбрейка. Идея проста, в систему устанавливаются ssl сертификаты и прописывается кастомный dns сервер, который запросы к серверам apple будет пересылать на сервер взломщиков. Сервер взломщиков будет подтверждать покупку и она успешно активируется на устройстве. После выхода этой новости паники было много и Apple даже пришлось что-то делать и рассказывать разработчикам, как защитить их приложение. На самом деле проблема была не нова, на джейлбрейкнутых устройствах уже давно можно было активировать in-app покупки бесплатно. Решение проблемы так же не ново, оно описано в документации Apple, но практической реализацией никто себя не утруждал. О моей версии такой защиты и пойдет речь ниже.
Как работают in-app покупки.
Есть два возможных сценария. Простой:
Устройство активирует покупку через сервера apple без дополнительной валидации и участия сервера разработчика.
Сложный:
Сервер разработчика может участвовать в процессе покупки следующим образом:
отправляет список возможных покупок (шаг 2),
валидирует чек покуки (шаги 10-11),
предоставляет доступ к какому-то дополнительному контенту (шаги 13-14).
Нас интересуют шаги 10-11, т.к. именно на них мы можем помочь устройству определить был чек выписан сервером apple или это подделка.
Тут надо добавить что исходники из статьи Apple могут помочь с валидацией чека прямо из приложения, но эта защита не отличается надежностью, т.к. никто не мешает перенаправить запросы к валидирующему серверу, на адрес сервера взломщиков, который будет возвращать ожидаемый ответ.
Валидация
Валидировать чек покупки мы можем только на сервере Apple. Для этого надо отправить JSON с чеком закодированным в base64, внутри HTTP POST запроса:
{
"receipt-data" : "(receipt bytes here)"
}
В ответ сервер вернет статус валидации, и если валидация успешна, декодированные поля чека.
{
"status" : 0,
"receipt" : { (receipt here) }
}
От теории к практике
Понимая описанную выше механику не составило труда написать приложение-прокси на ruby, которое пересылает запросы на валидацию на один из серверов Apple. Я выложил готовый к использованию код приложения на GitHub. Буду рад улучшениям и pull-запросам. Также его можно потрогать на heroku: https://receiptValidator.heroku.com/validate, используя тестовый чек из репозитория. С галочкой sandbox — можно посмотреть корректый ответ, а без неё — на код ошибки.
В приложении мы анализируем ответ нашего сервера и решаем стоит активировать встроенные функции или это подозрительный чек и его можно игнорировать. Если интересно в следующей статье я напишу о защите внутри приложения.
Сухой итог
Валидация покупок через свой сервер делает приложение «особенным» и универсальные ломалки, перестают работать.
Взломать приложение всё еще возможно, но для этого надо ломать именно наше приложение.
Если кто-то потратит время и взломает покупки — можно добавить дополнительное шифрование в общении с нашим сервером.
Бесплатно на heroku мы получаем удобный ruby хостинг и шифрование https.
P.S. немного бессовестного самопиара: эта защита была написана специально для Galileo Offline Maps и была успешно опробована в версии 2.2, которая появилась в AppStore вчера утром.