Ведение закрытого ключа между https и http
Я работаю над новым сайтом, который использует сервис-ориентированную архитектуру с чистым JavaScript на внешнем интерфейсе, получая доступ к веб-сервисам для данных через вызовы RESTful AJAX.
Это не должно иметь особого значения, но мой стек:
- javascriptMVC
- JQuery
- Bootsrap
- ASP.NET Web API (C# на.NET 4.0)
- MS SQL
Из этой статьи я выяснил некоторые хорошие способы защиты вызовов веб-службы, если у меня есть личный ключ, совместно используемый клиентом (JavaScript) и сервером (службы REST через Web API). Однако я борюсь с тем, как установить закрытый ключ, который будет использоваться для шифрования.
Плохая идея № 1
Первоначально, однако, было установить его при входе в систему через HTTPS, а затем сохранить его на клиенте в файле cookie для повторного использования. Проблема в том, что наш SSL -сертификат предназначен для https://secure.example.com/, а наш сайт - на http://www.example.com/ поэтому я не смогу получить доступ к cookie-файлу secure.example.com. с www.example.com.
Плохая идея № 2
Моя следующая мысль состояла в том, чтобы передать его в зашифрованном виде и подписать с помощью параметра URL от входа HTTPS на страницу HTTP post-login следующим образом:
http://www.example.com/processLogin?key=[encryptedKey]&sig=[encryptedSig]&user=[userid]
Как encryptedKey, так и encryptedSig будут зашифрованы другим закрытым ключом, который существует только для этой транзакции. Он будет создан при входе в систему и назначен этому пользователю в базе данных. На стороне HTTP все это передается на сервер, который расшифровывает его, проверяет подпись, удаляет этот закрытый ключ (для защиты от атак воспроизведения - по сути, одноразовый номер) и возвращает расшифрованный закрытый ключ ([encryptedKey]
расшифрованы).
С этого момента расшифрованное значение [encryptedKey]
будет использоваться для всех будущих транзакций. Проблема в том, что дешифрованный закрытый ключ должен был быть отправлен по линии через HTTP, что отстой.
Плохая идея № 3
Мне также кратко пришло в голову иметь жестко закодированный ключ в JavaScript, который используется для расшифровки этого значения, но независимо от того, как я пытаюсь его запутать, он может быть найден и использован хакером.
Плохая идея № 4
Я также рассмотрел какой-то обмен ключами с использованием криптографии с открытым ключом при первоначальном рукопожатии, но, как уже отмечалось в другом месте, на стороне клиента нельзя быть уверенным в том, что во время этого первоначального рукопожатия не будет подделок, пока он не закончится. SSL - вернуть меня на круги своя.
Большой вопрос
Итак, как вы, ребята, справляетесь с такими вещами, когда все не идет по HTTPS? Должен ли я иметь одно и то же доменное имя для моих HTTP и HTTPS, чтобы я мог сохранить этот закрытый ключ в cookie?
Обратите внимание, что части сайта, не относящиеся к SSL, не будут обмениваться информацией о кредитной карте, имени входа и т. П. Я просто не хочу оставлять эту присоску широко открытой.
3 ответа
Вы можете посмотреть, как работать с поддоменами и cookie-файлами, проверив этот ответ: Создание файла cookie javascript в домене и его чтение по поддоменам.
Вы не можете иметь безопасную и зашифрованную связь между клиентом javascript и сервером без использования SSL. Это невозможно. Если вы действительно хотите не зашифровать трафик, а просто убедиться, что клиент, с которым вы разговариваете, авторизован на выполнение запроса, и что клиент не является имитатором, то OAuth может быть достаточно. См. http://www.dotnetopenauth.net/ для стандартной реализации OAuth .net.
Если OAuth - это не то, в чем вы хотите участвовать, и вы просто хотите использовать то, что уже собрали, вы должны распространить токен, открытый и закрытый ключи для клиента javascript. Открытый ключ и токен - это то, что отправляется взад и вперед для каждого запроса, в то время как закрытый ключ никогда не пересылается взад и вперед и вместо этого используется для генерации хеша подписи определенного типа. Каждый запрос должен иметь эту подпись и одноразовый номер для предотвращения повторов. Вы также должны истечь токен очень часто и требовать, чтобы клиент запросил "обновить" токен со своим sig и своим открытым ключом. По сути, я описал OAuth 1.0a, и если вы хотите пойти по этому пути, я бы обратился к DotNet OpenAuth вместо того, чтобы пытаться свернуть его самостоятельно.
Однако, повторюсь, без SSL вы все равно будете уязвимы для других типов атак. Кроме того, если вы не зашифруете SSL при первоначальном запросе токена, хакер всегда может прослушать начальную доставку пары токен / открытый / закрытый ключ, следовательно, устраняя всю вашу тяжелую работу, чтобы обеспечить безопасность в первую очередь.
Альтернативой вышесказанному является размещение прокси-сервера между вашим клиентом и REST API. Запросы к API могут проходить только через прокси-сервер. Клиент входит в систему и получает файл cookie с https://secure.example.com/ с использованием базовой аутентификации. Затем клиент продолжает отправлять запросы на secure.example.com, а secure.example.com затем отправляет запросы вашему API и возвращает данные обратно клиенту.
Во всяком случае, надеюсь, достаточно информации, чтобы дать вам пищу для размышлений.
Относительно плохой идеи № 3:
Я давно знаю, что могу использовать http://jsbeautifier.org/ для деобфускации всего, что скрыто с помощью http://dean.edwards.name/packer/ с помощью флажка "Shrink variable" и / или "Base62 encode". флажок. Таким образом, JavaScript абсолютно небезопасен, и на него не следует полагаться при сохранении любого вида шифрования SSL, ни пользовательских токенов, ни редактируемой статистики аккаунта в браузере. В противном случае кто-то просто попытается отредактировать свой игровой аккаунт и подарить себе +10 миллионов игровых монет.
Когда все идет по SSL, оно защищает только от атак "человек посередине". Это действительно атака "сервер-бот-в-середине". Это не мешает конечному пользователю быть хакером.
На этой следующей иллюстрации SSL будет препятствовать тому, чтобы серверы a-e могли видеть любые данные, которые передаются от клиента к конечному серверу, но без SSL-сервера C мог бы украсть данные. Вот как работает серверный прыжок без шифрования, когда клиент + все серверы могут читать данные:
client > a > b > server c's bot sniffs http traffic > d > e > terminus server
Бот сервера c регистрирует номер кредитной карты, который является зашифрованным номером банковского счета. (Большинство людей не осознают, что номер кредитной карты является зашифрованным и преобразованным номером банковского счета. Если номер кредитной карты скомпрометирован, банку легко переиздать новый зашифрованный номер CC# с номера банковского счета и отправить новую карточку по почте. Им не нужно ни менять номер исходного банковского счета, ни печатать новые чеки, на которых номер банковского счета напечатан внизу.)
Серверные прыжки с шифрованием TLS/SSL/https будут работать следующим образом, когда только клиент и сервер могут читать все:
client > all servers from a-e are blind & pass the data through > terminus server
Бот сервера c видит нежелательные сообщения: as65a89as7df08 вместо 1234-5678-9012-..., если они вообще могут что-либо читать с использованием SSL.
Что хорошо в iOS, так это то, что она усложняет чтение кода JS, когда он используется с HTML 5 и CSS. Пользователь не может щелкнуть правой кнопкой мыши, чтобы проверить на своем iPhone, как они могут в браузере на рабочем столе. Легко спрятать пароль на конечном сервере, используя внутренний язык.
В настоящее время невозможно предотвратить взлом JavaScript конечным пользователем (клиентом). Каждый конечный пользователь может быть хакером. Если я пойму что-то еще, я могу опубликовать это здесь для будущих разработчиков, чтобы прочитать.