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

Как защитить веб-службу без входа в систему

У меня есть мобильное приложение (в настоящее время IOS и вскоре Android), который рассказывает о веб-сервисе. Нет входа и данные не являются частными. В основном приложение POST устанавливает маркер (lon, lat) и GET содержит ближайшие 25 маркеров для отображения на карте.

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

Я медленно делаю вывод, что это невозможно. Лучший ответ - "не делай этого". Не предоставляйте веб-службу без проверки подлинности. Не так много услуг открыты. API Google You Tube открыт, но большинство нет. К сожалению, у меня нет выбора. Поэтому после нескольких дней взгляда на это здесь мое мышление. Имейте в виду, что я очень далек от эксперта по безопасности, и я уверен, что мой подход может быть улучшен. Но это может указывать на вас в правильном направлении. Надеюсь, кто-то более опытный может перезвонить и исправить/улучшить это. Я нашел эту статью, и комментарии особенно полезны.

Безопасность уровня сообщений

Я буду защищать msgs с помощью хэш-шифрования. Клиенты и веб-сервис сохраняют копию общего секрета, который используется как соль для создания хеша из URL-адреса и всех аргументов POST. Хэш передается как дополнительный аргумент, а хэш перестраивается и сравнивается на другом конце (используя общий ключ в качестве соли). Это очень хорошо, пока вы не поймете, что любой мобильный клиентский код может быть запрограммирован в обратном порядке за считанные минуты. В этот момент эта линия обороны совершенно бесполезна.

Клиентские меры

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

Безопасность на стороне сервера

Таким образом, серверная сторона должна иметь как можно больше дополнительных мер безопасности, чтобы быть независимой, исходя из предположения, что ваш клиент (и общий секрет) скомпрометирован. Вот что я имею:

Один msg arg - это время UTC, которое используется для ограничения повторных атак. Это должно помешать злоумышленнику повторно запустить один и тот же msg на сервере.

Сервер выполняет ограничение скорости по IP. Да, IP-адреса легко подделываются, а переключение между прокси-серверами - игра для детей, но все помогает, когда у вас так мало.

Конечно, сервер строго проверяет все аргументы, использует параметризованные запросы и не возвращает исключения.

Безопасность транспортного уровня

К сожалению, я уверен, что выдача сертификатов отдельных клиентов SSL невозможна без регистрации. И поскольку я использую хэш-проверку msg (а мои данные не являются частными), я не совсем уверен, что SSL приносит в таблицу. Тем не менее, я, вероятно, буду использовать SSL (с одним сертификатом приложения), потому что он добавляет еще один уровень безопасности, который легко и дешево развертывается (хотя и за счет дополнительного времени соединения для каждого сообщения).

The Gaping Большая большая дыра в моем подходе

Я предупреждаю, что если приложение станет популярным, кто-то будет компрометировать общий секрет на клиенте. Просто потому, что они могут, и они, вероятно, опубликуют его в Интернете. Так что на самом деле все сводится к серверной стороне. К сожалению, у меня нет возможности идентифицировать и блокировать злоумышленника. Это я бы очень любил.

Заключительная просьба

После нескольких дней исследований это все, что у меня есть. Но я хочу большего. Я бы особенно признателен за любые идеи, направленные на усиление серверной части. Итак, я поставил все свои ТОЧНЫЕ ТОЧКИ как щедрость. Да, сэр, все 97 баллов!

4b9b3361

Ответ 1

Фактически в вашем конкретном случае, поскольку в настоящее время это приложение только для iOS, есть решение.

  • После того, как пользователь загружает и запускает приложение в первый раз, приложение попадает в API /access_token/create, который содержит GUID и передает его обратно в приложение через Apple Push Notifications.

  • App хранит этот access_token и использует его во всех последующих запросах. Ваш фактический API может оценивать лимит на основе access_token.

В принципе, вы позволяете Apple делать всю тяжелую работу по обеспечению того, чтобы исходный запрос поступал с реального устройства iOS.

Расширение этого для настольных клиентов возможно, но несколько разрушает UX. Просто измените шаг 1, чтобы позволить /access_token/create принимать произвольные запросы, а если запрос не принадлежит устройству iOS, заставьте пользователя проверить их адрес электронной почты/решить captcha и т.д., Прежде чем выдать им access_token.

Устройства Android (не очень знакомые с ними) могут иметь аналогичный механизм Push Notification, и в этом случае вы можете использовать это или не иметь механизм Push Notification, и в этом случае вы можете подвергнуть пользователей Android неудобствам, перечисленным выше.

Ответ 2

Я слышал об этой идее один раз, когда говорил о поиске глобального решения проблемы СПАМ: заставил вашего клиента выполнить некоторые вычисления времени.

Чтобы быть точным: найдите некоторый вычислительный алгоритм, который может вычислить некоторый z для пары x и y в мгновение ока, но для вычисления z требуется довольно много времени, дается только x. Я не могу предоставить фактический алгоритм, но я уверен, что их много, что бы это значило.

Теперь вся процедура должна выглядеть следующим образом:

  • При первом запросе клиента генерируется некоторая session_id и для этой session_id пара x и y.
  • Предоставьте клиенту session_id и x.
  • Клиент может запускать вычисления, как только он получает данные (в некотором фоновом потоке, не связанном с пользовательскими взаимодействиями).
  • Чтобы запросить маркеры, клиент должен предоставить session_id и рассчитанный z.
  • Вы можете быстро проверить, подходит ли клиент z, поскольку у вас уже есть x и y, которые позволяют вам легко это сделать.
  • (вариант 1) Для каждого session_id храните, сколько/часто оно запрашивается. В тот момент, когда вы подозреваете, что он подвергается насилию - принудительно регенерируйте x и y.
  • (опция 2) Настройте новые x и y на каждый последовательный запрос для session_id.

Выбор между 6 и 7 на самом деле настраивается, что зависит от сложности алгоритма и ожидаемого "справедливого" использования базы данных маркеров. Если ваши оценки хороши - злой клиент никогда не должен получать слишком много данных или перегружать ваш сервер.

Надеюсь, что это поможет.

Ответ 3

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

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

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

Подписанный подход Kuba Wyrostek может работать - заставить клиента выполнить некоторые трудоемкие вычисления, которые вы можете быстро проверить, прежде чем разрешить обработку запроса. Но это не может занять слишком много времени, или ваши пользователи будут жаловаться на сокращение времени автономной работы. Также злоумышленник, вероятно, будет использовать более мощное настольное оборудование вместо другого iPhone.

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

Ответ 4

Я действительно искал причину для реализации некоторых из этих идей. Большой вопрос и ответы до сих пор.

Я согласен с @Kuba Wyrostek относительно его рассмотрения, поскольку проблема с спамом является частью решения. Особенно, если ваше приложение будет иметь текстовые сообщения (добавление магазина, службы или сообщения), вы можете обнаружить, что обычной причиной спама вашего приложения было бы рекламировать что-то. Это приведет к моей первой рекомендации:

1) Рассматривайте каждую достоверность сообщения в процентах от 0% до 100% действительных. Разработайте процесс на стороне сервера с помощью эвристики, чтобы отметить сообщение более или менее достоверным. Это позволит вам настроить таргетинг на некоторые дополнительные методы (например, заставить клиента рассчитать сложное значение) только для тех запросов, где это необходимо. Вы также можете легко зарегистрировать и просмотреть возможное злоупотребление (и более легко очистить это злоупотребление после его таргетинга).

У ваших приложений действительно есть преимущество перед серверами электронной почты в спам-войне, однако - вы контролируете обе стороны разговора. Эта ситуация на самом деле напоминает мне о двух других ситуациях, которые могут вам пригодиться: спутники Pay-TV "войны" и Instant Messenger клонируют "войны". (Ссылка Jeff Atwoods на Black Sunday hack, например). Вот несколько идей из тех противостояний, которые могут помочь вам немного опередить игру в кошки-мышки:

2) Требовать от клиента отправки дополнительных данных - столько же данных о запросе имеет смысл. На iOS отправьте показатели точности для местоположения. На Android вы можете получить необработанные данные GPS, такие как информация о эфемеридах. Затем вы можете (возможно, не сразу, но позже), начните проверять эти данные на достоверность. Это заставляет кого-то переделать запросы на работу намного сложнее. Например, если они отправляют спутники GPS, вы можете проверить это на основе общеизвестных данных для подтверждения.

3) Принудите своего противника на мобильное устройство.. Как отмечает @Sven, ваш злоумышленник может использовать настольный ПК, что означает, что запрос "вычислительно дорого" может стать тривиальным. Не позволяйте им делать это (или, по крайней мере, заставить их работать усерднее). Например, вы можете вычислить некоторую математическую функцию (отправленную сервером) и посмотреть, на основе модели телефона, если она вернет правильное количество миллисекунд. Или выполните небольшую задачу 3D-рендеринга с данными с сервера, которые полагаются на поведение отсечения оборудования. Хеш результат и отправьте его обратно. Все они будут в пределах диапазона - это многозадачная ОС. Но это очень поможет.

4) Переходите к ним динамически. Отправьте бит алгоритма, который нужно вычислить в контексте клиента. Apple получает немного смешно в отношении удаленного кода для интерпретации, но что-то вроде отправки немного javascript, который не отображается пользователю, может работать. Этот код может задавать всевозможные уникальные вопросы (разрешение экрана, версия браузера, причуды WebKit), которые было бы трудно предвидеть впереди. По мере того, как они догонят вас, вы можете стать более креативными с ними.

5) CAPTCHA. Если ваша эвристика начнет видеть подозрительные данные, заставьте их пройти аутентификацию. Если у вас многоязычное приложение, это может быть так же просто, как сопоставление изображения или символа юникода с другим. Измените его таким образом, чтобы его можно было обновить позже.

Во всяком случае - несколько дополнительных идей. Удачи!

Ответ 5

Самый простой способ реализовать ограничение скорости на стороне сервера - просто использовать плагин/модуль веб-сервера. Например, если ваша служба работает на apache, установите и настройте mod_evasive. Это позволит вам оценить лимит на основе IP-адреса, сервиса/URL-адреса и т.д. Mod Evasive будет более эффективным, чем то, что вы можете реализовать самостоятельно.

Если вы используете ключи, у вас должен быть какой-то способ, основанный на методе "captcha", чтобы клиент мог получить ключи при регистрации. Вы могли бы отменить учетные записи для пользователей с нарушениями. Правильно, конечно, одним из параметров будет метка времени, которая будет проверена как последняя, ​​так и в прошлом на стороне сервера. Ключ будет шифровать всю полезную нагрузку вместе с временной меткой и быть добавлен в качестве дополнительного параметра. Хранение частоты запросов по принципу "за ключ" заканчивается тем, что требуется какая-то сводная база данных, если только вы не проверяете повторение последнего запроса.

Никакой предел скорости на стороне клиента не будет иметь никакого значения. Кто-то может обнаружить ваш API в Интернете, даже не увидев своего клиента. Я сомневаюсь, что общий секрет будет эффективен долго.

Вы найдете множество веб-сервисов, которые не требуют пароля и просто ограничены по скорости... например, API twitter предлагает множество услуг API без аутентификации с ограничением скорости.

Ответ 6

Вот еще одно "решение":

  • Не тратьте время на эту проблему.

потому что:

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

если есть подозрительная производительность или шипы запросов для наименее трудоемкого решения:

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

это в 99,99% решит ваши проблемы, и вы сможете работать прямо сейчас и писать потрясающие новые функции.

Ответ 7

Это сложно, вы не ожидаете, что кто-нибудь изменит данные... так что ваша забота не о целостности. И поскольку вы не поддерживаете список клиентов... не может быть никакой озабоченности по поводу подлинности?

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

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

Если вы посмотрите на подходы, которые вы оцениваете:

Защищенный ключ. Насколько я понимаю, сервер и приложение будут использовать один и тот же ключ, и если я прав, все приложения на всех устройствах будут использовать один и тот же ключ. И когда приложение выталкивает данные, он хэширует "Фактический фид" и отправляет через "Фактический канал + хешированный канал". На стороне сервера вы будете использовать ключ и хеш фактический фид и проверить, совпадает ли он с хешированным фидом. И, на мой взгляд, это решение в основном касается аспекта целостности данных, который не является для вас серьезной проблемой. RGT! (И да, вероятно, будет легко перепроектировать.)

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

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

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

Ответ 8

Вы можете использовать ограничение скорости + клиентскую "мягкую" регистрацию.

В принципе, вы должны сгенерировать идентификатор устройства, который вы могли бы сохранить в настройках пользователя по первому запросу. Для каждого запроса вы отслеживаете, сколько запросов было отправлено на сервер и ограничено его серверной стороной. Это можно сделать очень быстро.

У вас также может быть какой-то общий секрет, используемый для подписи вашего запроса сгенерированным идентификатором устройства + post/get parameters