защита API REST, доступная с Android

Мы создаем игру для Android, которая нуждается в доступе к веб-сервисам – поэтому мы написали RESTful API в PHP, который работает на нашем собственном сервере. Что предлагает API: создание пользователя, вход в систему, загрузка игр, получение списка игр, отправка баллов … и т. Д. Теперь я думаю, что если какой-нибудь опытный пользователь получит URL-адрес API-интерфейса, он сможет для утилизации системы различными способами:

  • Создайте сценарий и запустите его для создания автоматических пользователей. Думаю, я могу предотвратить его с помощью CAPTCHA или сопутствующего подобного. Но опять же, captcha будет раздражать игроков игры.
  • Вредоносный пользователь регистрируется в своем браузере, загружает игру и затем отправляет счет по своему усмотрению – все через вызов API, просто набрав его из своего браузера. Я предполагаю, что вредоносный пользователь каким-то образом знает URL-адреса API для вызова – путем обнюхивания, когда приложение выполняло HTTP-запросы.
  • Мне нужно, чтобы запросы выполнялись только с Android-устройства, которое установило игру. (Игра будет бесплатной)

Теперь Как предотвратить такие злоупотребления?

Solutions Collecting From Web of "защита API REST, доступная с Android"

Я думаю, что вы никогда не сможете скрыть URL-адреса, вызываемые приложением (если я запускаю анонимный телефон с правами root, я должен следить за всем сетевым трафиком)

Но ваша настоящая проблема заключается в том, что вам необходимо аутентифицировать ваш api.

Одним из способов было бы реализовать OAUTH, но, возможно, это было бы излишним.

Если вам нужен простой механизм, как насчет этого;

  1. создать секретный ключ
  2. создайте запрос api (например, https://my.example.com/users/23?fields=name,email )
  3. хэш этот путь запроса + плюс ваш секретный ключ (например, md5 (url + secret_key) == "a3c2fe167")
  4. добавьте этот хэш в свой запрос (теперь это https: // …..? fields = name, email & hash = a3c2fe167 )
  5. на конце api, выполните одно и то же преобразование (удалите хэш-параметр)
  6. проверьте md5 URL-адреса и секретный ключ

Пока секрет остается в секрете, никто не может подделать ваши просьбы.

Пример (в псевдокоде):

Сторона Android:

SECRET_KEY = "abc123" def call_api_with_secret(url, params) # create the hash to sign the request hash = MD5.hash(SECRET_KEY, url, params) # call the api with the added hash call_api(url+"&hash=#{hash}", params) end 

Серверная сторона:

 SECRET_KEY = "abc123" def receive_from_api(url, params) # retrieve the hash url_without_hash, received_hash = retrieve_and_remove_hash(url) # check the hash expected_hash = MD5.hash(SECRET_KEY, url_without_hash, params) if (expected_hash != received_hash) raise our exception! end # now do the usual stuff end 

Решения, которые другие представили здесь, называются безопасностью через неясность . В основном они пытаются скрыть протокол и скрыть реализацию. Это может работать до тех пор, пока кто-то не сможет достаточно разобрать приложение и переконвертировать протокол. Хакеры очень способны на это.

Вопрос в том, что ваше приложение стоит взломать? Очевидно, что такие схемы, как iTunes, DVD или Sony PS3, стоят того. Подход безвестности может сработать, если никто не сможет взломать заботы. Только не обманывайте себя, что это не обидно.

Поскольку вы не можете доверять устройству или вашему приложению, вы должны доверять пользователю. Чтобы доверять пользователю, вам нужна система идентификации и авторизации пользователей. В основном вход в ваше приложение. Вместо того, чтобы каталогизировать свою систему индексирования (логин с электронными письмами с подтверждением и т. Д.), Используйте стороннюю систему: OpenID (учетные записи google) или OAuth (facebook, twitter). В случае использования facebook используйте серверную схему auth.

Что я буду делать:

  1. Позвольте пользователям свободно играть в игру, пока они не захотят «сохранить» результаты на сервере.
  2. Прежде чем сохранять свои результаты, вы можете войти в систему через вышеупомянутый метод.
  3. Используйте HTTPS для отправки данных на ваш сервер. Покупайте сертификат ssl из доверенного центра сертификации, поэтому вам не нужно иметь дело с самозаверяющими сертификатами.

Вы упомянули пользователей, которые подделывают высокие баллы. Это может произойти, если ваши пользователи прошли аутентификацию. Когда игра загружает высокие баллы, вы можете захотеть, чтобы она также загрузила доказательство оценки. Например, Score 20100 из 103 ошибок хлынул, пролетел 1200 миль, уровень 3 достиг, и 2 вишни были съедены. Это отнюдь не идеально, но будет покрывать низко висящие плоды.

Первое, что вы должны сделать, это аутентифицировать пользователей. Токен пользователя / пароль / сеанс и т. Д., Посмотрите, можете ли вы найти некоторые уже существующие фреймворки. После аутентификации пользователей убедитесь, что вы можете сделать это с помощью TLS или аналогичного.

Насколько я знаю, ваш сервер не может быть уверен в том, что запрос поступает из вашего приложения (все это всего лишь биты в пакетах), но вы можете по крайней мере затруднить кому-то вредоносность.

  • Постройте секрет в своем приложении (как предложено другими ответами, ключом, солью хешей и т. Д.),
  • Создайте уникальный идентификатор при первом выполнении приложения после установки и отслеживания, который вместе с зарегистрированным пользователем. Подробности об этом и уникальном ID устройства (почему бы не использовать его) можно найти в блоге Android
  • Некоторые идеи обсуждались в этом сообщении. Как обеспечить / определить, что сообщение поступает из определенного приложения, работающего на iPhone / iTouch?
  • Проверить агент пользователя

Если вы действительно хотите защитить соединение, вам придется использовать криптографию с открытым ключом, например RSA. Устройство будет шифровать информацию журнала с помощью открытого ключа, а в конце сервера вам придется расшифровывать, используя закрытый ключ. После входа в систему сервер отправит ключ маркера / шифрования (ответ будет зашифрованным JSON или что-то еще), и устройство сохранит это. С тех пор, пока сеанс не истек, устройство отправит всю информацию, зашифрованную с использованием этого токена. По этим запросам вы не должны использовать RSA, для чего потребуется больше времени. Вы можете использовать AES256 (популярное шифрование с закрытым ключом) с помощью этого ключа шифрования, полученного от сервера, для шифрования ваших запросов.

Для простоты вы можете вообще отказаться от RSA (если вы не отправляете платежную информацию) и делать все с помощью AES256 с помощью закрытого ключа. Шаги должны быть –

  • Шифруйте каждый исходящий запрос с помощью закрытого ключа.
  • Преобразуйте зашифрованную строку в базовую 64 строку.
  • URL кодирует базовую кодированную строку.
  • Отправьте это.

На сервере

  • Делают декодирование базы 64
  • Расшифруйте с помощью закрытого ключа.

В вашем запросе должна быть подпись (например, ключ шифрования, добавленный в виде соли), чтобы стало возможным идентифицировать ее после дешифрования. Если подпись отсутствует, просто отбросьте запрос.

Для отправки ответов делайте то же самое.

Android SDK должен иметь методы шифрования с кодировкой AES256 и Base 64.

Следуйте этим рекомендациям от команды Android, чтобы обеспечить защиту вашего бэкэнда, используя токены Oauth, предоставляемые через API Google.