Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

  • создать секретный ключ
  • создайте запрос api (например https://my.example.com/users/23?fields=name,email)
  • hash этот путь запроса + плюс ваш секретный ключ (например, md5 (url + secret_key) == "a3c2fe167" )
  • добавьте этот хеш в ваш запрос (теперь это https://.....?fields=name,email&hash=a3c2fe167)
  • в конце api, выполните одно и то же преобразование (удалите хэш-параметр)
  • проверьте 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

Ответ 2

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

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

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

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

На сервере

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

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

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

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

Ответ 5

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