Мой вопрос касается безопасности JavaScript.
Представьте себе систему аутентификации, в которой вы используете среду JavaScript, такую как Backbone или AngularJS , и вам нужны защищенные конечные точки. Это не проблема, поскольку сервер всегда имеет последнее слово и проверит, авторизованы ли вы делать то, что вы хотите.
Но что, если вам нужно немного безопасности без участия сервера? Это возможно?
Например, скажем, у вас есть система маршрутизации на стороне клиента, и вы хотите, чтобы конкретный маршрут был защищен для вошедших в систему пользователей. Таким образом, вы пингуете сервер, спрашивая, разрешено ли вам посещать защищенные маршруты, и вы продолжаете. Проблема заключается в том, что когда вы отправляете эхо-запрос на сервер, вы сохраняете ответ в переменной, поэтому при следующем входе на частный маршрут он проверит, если вы уже вошли в систему (нет связи с сервером), и в зависимости от на ответ пойдет или нет.
Насколько легко пользователю изменить эту переменную и получить доступ?
Мои знания по безопасности (и JavaScript) не велики. Но если переменная не находится в глобальной области видимости и находится в закрытой части шаблона модуля, который имеет только геттеры, но не сеттеры, даже в этом случае, вы можете разобраться с этим?
источник
manipulate any part of the sight without long lines
сайт против зренияОтветы:
Пожалуйста, прочитайте ответ Иоахима, прежде чем читать этот. Он описывает общие причины уязвимости на стороне клиента. Теперь для предположения, как вы могли бы обойти эту проблему ...
Безопасная схема для связи клиент-сервер без необходимости аутентификации на сервере вручную при каждом запросе:
Вы по- прежнему позволяете серверу сказать последнее слово, а серверу все еще нужно проверить все, что говорит клиент, но это происходит прозрачно.
Предположим, что протокол HTTPS предотвращает атаки «человек посередине» (MITMA).
Клиент впервые связывается с сервером, и сервер генерирует открытый ключ для клиента и сохраняет личный ключ, используя асимметричную схему шифрования. Клиент хранит «открытый» ключ сервера в локальном хранилище, зашифрованный безопасным паролем, который вы нигде не сохраняете.
Клиент сейчас не в сети. Клиент хочет выполнить доверенные действия. Клиент вводит свой пароль и получает открытый ключ сервера.
Клиент теперь выполняет действия, основываясь на своих знаниях об этих данных, и клиент шифрует каждое действие, которое он выполняет, с помощью открытого ключа сервера для этого клиента .
Когда клиент находится в сети, клиент отправляет свой идентификатор клиента, и все действия, которые выполнял клиент, отправляются на сервер в зашифрованном виде с открытым ключом сервера.
Сервер расшифровывает действия, и если они имеют правильный формат, он доверяет тому, что они возникли на клиенте.
Заметка:
Вы не можете хранить пароль клиента где-либо, иначе злоумышленник сможет получить ключ и подписать действия как свои собственные. Безопасность этой схемы зависит исключительно от целостности ключа, который сервер генерирует для клиента. При запросе этого ключа клиенту все равно нужно будет проходить проверку подлинности на сервере.
Вы по-прежнему полагаетесь на сервер для обеспечения безопасности, а не на клиента. Каждое действие, которое выполняет клиент, вы должны проверить на сервере.
Возможно запускать внешние скрипты в веб-работниках . Имейте в виду, что каждый ваш запрос JSONP является гораздо более серьезной проблемой безопасности. Вам необходимо защитить ключ любой ценой. Как только вы его потеряете, злоумышленник может выдать себя за пользователя.
Это соответствует вашему требованию о том, что «ping to the server» не выполняется. Злоумышленник не может просто имитировать HTTP-запрос с поддельными данными, если он не знает ключ.
Иоахим все еще прав . На самом деле вы все еще выполняете всю аутентификацию на сервере . Единственное, что вы сохранили здесь - это необходимость каждый раз проверять пароль на сервере. Теперь вам нужно только подключить сервер, когда вы хотите зафиксировать, или получить обновленные данные. Все, что мы здесь сделали, - это сохранили доверенный ключ на стороне клиента и попросили клиента повторно его проверить.
Это довольно распространенная схема для одностраничных приложений (например, с AngularJS).
Я называю открытый ключ сервера «открытым» из-за того, что это означает в схемах, подобных RSA , но на самом деле это конфиденциальная информация в схеме, и ее следует защищать.
Я бы нигде не хранил пароль в памяти. Я бы заставлял пользователя отправлять свой «автономный» пароль каждый раз, когда он / она запускает автономный код.
Не катите свою собственную криптографию - используйте для аутентификации известную библиотеку, такую как Stanford.
Прими этот совет как есть . Перед тем, как приступить к такой аутентификации в реальном критически важном приложении, проконсультируйтесь с экспертом по безопасности . Это серьезная проблема, которая и болезненная, и легко ошибиться.
Крайне важно, чтобы никакие другие сценарии не имели доступа к странице. Это означает, что вы разрешаете только внешние сценарии для веб-работников. Вы не можете доверять никаким другим внешним скриптам, которые могут перехватить ваш пароль, когда пользователь вводит его.
Используйте поле
prompt
а не встроенный пароль, если вы не совсем уверены и не откладываете его выполнение (то есть оно не должно дойти до точки, где события имеют к нему доступ, а только в коде синхронизации). И на самом деле не храните пароль в переменной - опять же, это работает, только если вы уверены, что компьютер пользователя не скомпрометирован (хотя это также верно для проверки на сервере).Я хотел бы еще раз добавить, что мы все еще не доверяем клиенту . Вы не можете доверять клиенту в одиночку, и я думаю, что ответ Иоахима прибивает его. Мы получили только удобство: не нужно пинговать сервер перед началом работы.
Материалы по теме:
источник
window.prompt
метод, чтобы перехватить фразу-пароль, или запустить собственное приглашение (возможно, в пределах iframe!). Поле пароля имеет одно дополнительное преимущество: символы не отображаются.Все просто: любой механизм безопасности, который полагается на то, что клиент делает только то, что вы ему говорите, может быть скомпрометирован, когда злоумышленник контролирует клиента.
У вас могут быть проверки безопасности на клиенте, но только для того, чтобы эффективно действовать как «кеш» (чтобы избежать дорогостоящих обратных вызовов на сервер, если клиент уже знает, что ответом будет «нет»).
Если вы хотите сохранить информацию от группы пользователей, убедитесь, что клиент этих пользователей никогда не получит эту информацию. Если вы отправите эти «секретные данные» вместе с инструкциями «но, пожалуйста, не отображайте их», отключение кода, проверяющего этот запрос, станет тривиальным.
Как видите, в этом ответе не упоминаются какие-либо особенности JavaScript / браузера. Это потому, что эта концепция одинакова, независимо от того, кто ваш клиент. На самом деле не имеет значения, что это толстый клиент (традиционное клиент-серверное приложение), веб-приложение старой школы или одностраничное приложение с обширным клиентским JavaScript.
Как только ваши данные покидают сервер, вы должны предположить, что злоумышленник имеет к ним полный доступ.
источник
В игровом сообществе есть поговорка: « Клиент в руках врага". Любой код, работающий вне защищенной области, такой как сервер, уязвим. В самом простом сценарии уязвим для того, чтобы не запускаться в первую очередь. Это решение клиента фактически запустить ваш" код безопасности ", и пользователь может просто "отказаться". Хотя с нативным кодом у вас есть, по крайней мере, автоматическое запутывание в сборке и дополнительный уровень защиты, потому что злоумышленник должен быть хорошим программистом, чтобы манипулировать этим, JS, как правило, безоблачный и в виде простого текста. Все, что вам нужно для проведения атаки, - это примитивные инструменты, такие как прокси-сервер и текстовый редактор.Заключителю по-прежнему потребуется определенный уровень знаний в области программирования, но модифицировать скрипт с помощью любого текстового редактора гораздо проще, чем вводить код в исполняемый файл.
источник
Это не вопрос взлома JavaScript. Если бы я хотел атаковать ваше приложение, я бы использовал частный прокси, который позволял бы мне захватывать, изменять и воспроизводить трафик. Ваша предложенная схема безопасности, похоже, не имеет никакой защиты от этого.
источник
Говоря конкретно об Angular:
Защита клиентской стороны маршрута просто не существует. Даже если вы «спрячете» кнопку для этого маршрута, пользователь всегда сможет набрать ее, Angular будет жаловаться, но клиент может кодировать это.
В какой-то момент ваш контроллер должен будет запросить у вашего сервера данные, необходимые для визуализации представления, если пользователь не авторизован для доступа к этим данным, они не получат его, поскольку вы защитили эти данные на стороне сервера. и ваше угловое приложение должно обрабатывать 401 соответственно.
Если вы пытаетесь защитить необработанные данные, вы не можете на стороне клиента, если вы хотите, чтобы конкретный пользователь мог только просматривать общие данные определенным образом, создавайте «представления» данных на сервере, а не отправляйте их. Необработанные данные для клиента и их реорганизация (вы все равно должны делать это по соображениям производительности).
Примечание: никогда не должно быть ничего чувствительного, встроенного в шаблоны представлений, которые запрашивает Angular, просто не делайте этого. Если по какой-то безумной причине это происходит, вам нужно защитить эти шаблоны представлений на стороне сервера, как если бы вы выполняли рендеринг на стороне сервера.
источник