Кодирование на стороне клиента: как предотвратить злонамеренное использование?

60

За последние несколько лет тенденция для клиентских (браузерных) приложений действительно взлетела.

Для моего последнего проекта я решил попробовать идти в ногу со временем и написать приложение на стороне клиента.

Часть этого приложения включает отправку электронных писем о транзакциях пользователям (например, подтверждение регистрации, электронные письма для сброса пароля и т. Д.). Я использую сторонний API для отправки электронных писем.

Обычно я запускаю приложение на сервере. Я бы вызвал сторонний API из кода на моем сервере.

Запуск клиентского приложения означает, что теперь это должно происходить в браузере пользователя. Сторонний API предоставляет необходимые файлы JavaScript для достижения этой цели.

Первая явная проблема, которую я вижу, - мне нужно использовать ключ API. Обычно это безопасно хранится на моем сервере, но теперь, вероятно, мне нужно будет предоставить этот ключ клиентскому браузеру.

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

Я предполагаю, что мой общий вопрос - как мы можем предотвратить злонамеренное использование клиентского приложения?

Gaz_Edge
источник
24
По какой-либо причине у вас нет этого приложения для связи с вашим собственным сервером, а затем ваш сервер перенаправляет эти запросы любой внешней службе, которую вам нужно использовать? (Многие такие службы в любом случае запрещают использовать их таким образом)
thorsten müller
11
Вот почему ключи API в конечном итоге бессмысленны. Сервер не должен доверять приложению, которое отправляет ему команды; это должно только доверять пользователю.
Кевин Панко
42
Я не видел ни одного здравомыслящего человека, который когда-либо определял бы «клиентское приложение» как «ни при каких обстоятельствах не общающийся с сервером» - это больше похоже на соломенного человека, чем на разумный аргумент. Ясно, что есть некоторые вещи, которые вы должны выполнить на стороне сервера, но подавляющее большинство действий может быть выполнено локально без проблем, что, в свою очередь, значительно улучшит
Voo
4
Где вы видите толчок к «Приложения только для браузера?» Я никогда не видел ничего подобного тому, что вы описываете, храня секреты в клиентском коде в безумно плохой идее, даже самые упорные ребята из тех, кого я знаю, никогда бы этого не сделали.
Уилс
2
Любая попытка защитить защищенные ресурсы на стороне клиента обречена, поскольку она нарушает некоторые из неизменных законов безопасности. # 2/3 - если ваше программное обеспечение работает на вашем компьютере противника, то это не ваш компьютер по определению, и вы уже проиграли. # 7 Попытка защитить ресурс с помощью шифрования обречена, так как вы также должны предоставить клиенту ключ дешифрования. # 10 ни одна технология не может исправить вышеперечисленное. blogs.technet.com/b/rhalbheer/archive/2011/06/16/…
Дэн Нили

Ответы:

200

Вы не можете, и чем больше люди понимают это, и чем глубже они понимают, тем лучше для мира.

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

Запутывание очень мало помогает; тот тип оппонента, которого вы привлечете, как только будет задействовано что-то удаленное финансовое, читает язык ассемблера, например, объявления. Шифрование не может вам помочь, потому что устройство, которое будет защищать ключ, является тем же устройством, которое, как вы полагаете, взломано. Есть много других, казалось бы, очевидных контрмер, которые не работают по тем же причинам.

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

Тем не менее, конечно, есть такая вещь, как глубокоэшелонированная защита. Запутывание вашего JavaScript не отпугивает решительного злоумышленника, но может отпугнуть некоторых менее решительных злоумышленников. Если ваши активы имеют достаточную ценность для защиты, но не любой ценой, любая из этих мер может повысить ценность вашей системы для бизнеса; это просто не может быть идеальным. Пока вы полностью осведомлены о компромиссе, который делаете, это может быть разумной стратегией.

Килиан Фот
источник
6
Но если взглянуть на это в перспективе: это верно для КАЖДОГО программного обеспечения, будь то операционная система или иск для транзакций. В конце концов, есть несколько очень хороших обфускаторов кода, и вы можете поднять планку достаточно высоко, если нет немедленного финансового стимула для взлома вашего программного обеспечения!
Falco
5
В наши дни компании начали угрожать судебным иском против людей, которые взламывают контент, полученный от них перед обработкой (например, с помощью блокировщиков рекламы). Это только показывает, насколько невозможны технические действия.
Килиан Фот
62
Если я остановлюсь на первых двух предложениях, тонкости, которые люди часто упускают из виду, заключаются в том, что задача браузерных приложений на стороне клиента состоит в том, чтобы перенести тяжелую работу. Ваш сервер по-прежнему отвечает за доверенные операции, такие как отправка электронных писем или доступ к данным. Однако, если клиент отобразит график на основе этих данных, это сэкономит вам время ЦП (и деньги) без изменения модели безопасности.
ssube
11
@Gaz_Edge Важно отметить, что проблема здесь не в том, что клиентские приложения по своей природе небезопасны. Проблема состоит в том, чтобы писать эти клиентские приложения так, чтобы клиенту доверяли информацию, которую вы не хотите публиковать. Вполне возможно написать приложение, насыщенное клиентом, которое так же безопасно, как и приложение, в котором большая часть обработки происходит на сервере. (Подробнее об этом см . Ответ
jhocking
7
@ Ajedi32 стороны клиента приложений являются небезопасными. Невозможно разработать безопасное приложение, если какая-либо логика, выполненная на стороне клиента, не проверена на стороне сервера. В этот момент логика на стороне клиента становится хитроумным пользовательским интерфейсом или способом разгрузить базовые проверки, но все должно всегда проверяться на сервере !! ,
69

Правило здесь:

Делайте все на стороне клиента, чтобы это ни на кого не влияло, если пользователь вмешивается в это. В частности, это означает графические эффекты.

Делайте все на стороне сервера, которое должно быть защищено, и просто отправляйте события пользовательского интерфейса от клиента (например, тогда клиент просто говорит «пользователь нажал кнопку« Купить », пока сервер фактически выполняет транзакцию)». В частности, это означает финансовые операции.

jhocking
источник
28

Это именно тот случай , когда делает его полностью на стороне клиент приложения не соответствующие.

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

Ян Худек
источник
11
Примечание. Несмотря на то, что проверять формы на стороне клиента замечательно, никогда не забывайте проверять их и на стороне сервера! Когда вы отправляете свой код клиента в браузер, он перестает быть вашим кодом! Вы должны проверить каждый бит, который он отправляет снова!
Йозеф
17

Ваш средний параграф - суть проблемы:

Запуск клиентского приложения означает, что теперь это должно происходить в браузере пользователя. Сторонний API предоставляет необходимые js-файлы для достижения этой цели.

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

Что касается .jsфайла, который вы получили, вы уверены, что он предназначен для браузера? Может ли это быть библиотека node.js?

Brandon
источник
4
+1 за действительно хорошее предположение, что файл JS предназначен для сервера NodeJS
Machinarius
11

Давайте отступим от этого и посмотрим на более высокий уровень. Должны ли мы. Eudora или outlook (клиентское приложение, даже не нуждающееся в браузере) когда-либо приводили к финансовым потерям для какой-либо компании? Нет. Любой может написать в POP / SMTP API и стать клиентом. Но без потерь для сервера. Сервер не ограничивал действия клиента, вычисления, хранилище, температуру, размер диска, размер оперативной памяти, DPI монитора, GPU, FPU и другие параметры клиента, но точно указывал, на что он будет отвечать, и не более. Вы когда-нибудь слышали о том, чтобы Quicken или MS-Money использовались для взлома банка?

Ваше браузерное (т.е. клиентское) приложение может использовать ту же архитектуру.

  1. Вы строите свой сервер с помощью API (который, кстати, всегда сводится к производным от GET POST HEAD и т. Д.).
  2. На сервере убедитесь, что API взаимодействует только с аутентифицированным и проверенным идентификатором клиентом для каждого вызова.
  3. Тогда вам все равно, кто клиент.
  4. И тогда вам все равно, браузер ли это, взломанное устройство, Google Glass, DOS 3.1 или новый Nexus в руках технофоба, пра-пра-пра-прадеда, который путешествовал по времени в 2014 году и пропустил все технология, которая наводнила нашу жизнь за последние 15 десятилетий.
  5. Теперь вы можете начать разгрузку всего остального на стороне клиента.

SoapBoxBegin

@KilianFoth поднимает важный пункт осведомленности для наивных и безрассудных, в основном тех, кто все время читает заголовки, но никогда не думает, что это случится с их приложением, их кодом, их работодателем, их клиентом, их собственным банковским счетом. Еще более безрассудными являются их работодатели (особенно технический директор), которые позволяют приложениям выходить, которые подвергают любые системы неуправляемому / неконтролируемому воздействию. Однако я всегда озадачен тем, как кажется, что «мы никогда не учимся».

SoapBoxEnd

Итак, подведем итог. Создайте надежный и жесткий API на стороне сервера. Перенесите все остальное клиенту на основе того, что клиент может обработать.

LMSingh
источник
6

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

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

Я бы всегда рассматривал опыт работы на стороне клиента JS как дополнение к коду сервера. Проверка на клиенте обеспечивает приятный пользовательский опыт, но если вы не проверяете данные POST и на принимающем сервере, вы открываете себя для атаки. Все, что от клиента, следует считать подозрительным.

Мэтт Клинкер
источник
4

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

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

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

Следует признать, что реализация - это проблема, но важна ментальная позиция, предположение о том, что «клиент», с которым вы, по вашему мнению, общаетесь, не клиент, а активный злоумышленник.

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

gnasher729
источник
0

Клиентское приложение, на мой взгляд, в основном касается пользовательского интерфейса. Например, вся ваша система пользовательского интерфейса будет отправлена ​​клиенту один раз, а затем клиент будет делать с ней все, что захочет.

Обычно я запускаю приложение на сервере. Я бы вызвал сторонний API из кода на моем сервере.

Запуск клиентского приложения означает, что теперь это должно происходить в браузере пользователя. Сторонний API предоставляет необходимые файлы JavaScript для достижения этой цели.

Если у вас есть API-ключ, он не предназначен для работы на стороне клиента. Если вы дадите API-ключ на стороне клиента, тогда любой может получить к нему доступ, а затем сможет использовать его в своих целях. Сохраните его и используйте его на стороне сервера, когда клиенту это нужно, затем отправьте результат с помощью Ajax / WebSockets.

Это как если бы ваш банк говорил: «Ну, я собираюсь поставить пароль на стороне клиента основной базы данных, чтобы клиент мог запросить его сам, и он больше не будет беспокоить наши серверы».

Depado
источник