Может ли локальное хранилище считаться безопасным?
Мне необходимо разработать веб-приложение, которое будет работать в автономном режиме в течение длительного времени. Для того, чтобы это было жизнеспособным, я не могу избежать сохранения конфиденциальных данных (личных данных, но не тех данных, которые вы бы хранили только в хэше) в локальном хранилище.
Я принимаю, что это не рекомендуемая практика, но из-за небольшого выбора я делаю следующее для защиты данных:
- шифрование всего, что происходит в локальном хранилище, с использованием крипто-библиотеки stanford javascript и AES-256
- пароль пользователя является ключом шифрования и не хранится на устройстве
- обслуживание всего контента (при подключении к сети) с одного доверенного сервера через ssl
- проверка всех данных, поступающих в и из локального хранилища на сервере, с помощью проекта owasp antiisamy
- в разделе сети appcache, не используя *, и вместо этого перечисляя только URI, необходимые для соединения с доверенным сервером
- в общем, пытаясь применить рекомендации, предложенные в шпаргалке OWASP XSS
Я ценю, что дьявол часто в деталях, и знаю, что есть много скептицизма по поводу локального хранилища и безопасности на основе JavaScript в целом. Кто-нибудь может прокомментировать, есть ли:
- фундаментальные недостатки в вышеупомянутом подходе?
- какие-либо возможные решения для таких недостатков?
- Есть ли лучший способ защитить локальное хранилище, когда приложение HTML 5 должно работать автономно в течение длительного времени?
Спасибо за любую помощь.
6 ответов
WebCrypto
Проблемы с криптографией в клиентском (браузерном) javascript подробно описаны ниже. Все эти проблемы, кроме одной, не относятся к API-интерфейсу WebCrypto, который в настоящее время достаточно хорошо поддерживается.
Для автономного приложения вы все равно должны разработать и внедрить безопасное хранилище ключей.
В сторону: если вы используете Node.js, используйте встроенный криптографический API.
Нативная Javascript криптография (до WebCrypto)
Я предполагаю, что основная проблема - это кто-то с физическим доступом к компьютеру, который читает localStorage
для вашего сайта, и вы хотите, чтобы криптография помогла предотвратить такой доступ.
Если у кого-то есть физический доступ, вы также открыты для других атак и хуже, чем чтение. К ним относятся (но не ограничиваются ими): клавиатурные шпионы, автономная модификация скриптов, локальная инъекция скриптов, отравление кэша браузера и перенаправления DNS. Эти атаки работают только в том случае, если пользователь использует компьютер после его взлома. Тем не менее, физический доступ в таком сценарии означает, что у вас есть большие проблемы.
Так что имейте в виду, что ограниченный сценарий, в котором локальная криптография будет полезна, будет в случае кражи машины.
Есть библиотеки, которые реализуют желаемую функциональность, например Stanford Javascript Crypto Library. Хотя есть и слабые места (как указано в ссылке из ответа @ircmaxell):
- Отсутствие энтропии / генерации случайных чисел;
- Отсутствие безопасного хранилища ключей, то есть закрытый ключ должен быть защищен паролем, если он хранится локально или хранится на сервере (что запрещает автономный доступ);
- Отсутствие безопасного стирания;
- Отсутствие временных характеристик.
Каждый из этих недостатков соответствует категории криптографического компромисса. Другими словами, хотя у вас может быть "crypto" по имени, оно будет намного ниже строгости, к которой вы стремитесь на практике.
С учетом всего сказанного, актуарная оценка не так тривиальна, как "криптография Javascript слабая, не используйте ее". Это не одобрение, а строгое предостережение, и оно требует от вас полного понимания подверженности вышеперечисленным недостаткам, частоты и стоимости векторов, с которыми вы сталкиваетесь, и вашей способности к смягчению или страхованию на случай неудачи: Javascript crypto, in несмотря на свои слабые стороны, может снизить вашу подверженность, но только против воров с ограниченными техническими возможностями. Однако вы должны предположить, что криптография Javascript не имеет никакого значения для решительного и способного злоумышленника, который нацеливается на эту информацию. Некоторые сочли бы неправильным называть данные "зашифрованными", когда известно, что так много недостатков присуще реализации. Другими словами, вы можете незначительно уменьшить свою техническую подверженность, но вы увеличиваете свою финансовую подверженность раскрытию. Конечно, каждая ситуация индивидуальна - и анализ снижения технической подверженности финансовому риску нетривиален. Вот иллюстративная аналогия: некоторые банки требуют слабых паролей, несмотря на свойственный риск, потому что их подверженность потерям из-за слабых паролей меньше, чем затраты конечных пользователей на поддержку надежных паролей.
Если вы прочитали последний абзац и подумали: "Какой-то парень в Интернете по имени Брайан говорит, что я могу использовать криптографию Javascript", не используйте криптографию Javascript.
В случае использования, описанном в этом вопросе, пользователям, видимо, более целесообразно зашифровать свой локальный раздел или домашний каталог и использовать надежный пароль. Этот тип безопасности, как правило, хорошо проверен, широко доверен и общедоступен.
Ну, основная предпосылка здесь: нет, это еще не безопасно.
По сути, вы не можете запустить криптографию в JavaScript: JavaScript Crypto считается вредным.
Проблема в том, что вы не можете надежно получить криптографический код в браузере, и даже если вы можете, JS не предназначен для того, чтобы вы могли безопасно его запускать. Таким образом, до тех пор, пока в браузерах не появится криптографический контейнер (который предоставляют Encrypted Media Extensions, но который сплачивается для целей DRM), это невозможно будет сделать безопасно.
Что касается "лучшего пути", то сейчас его нет. Ваша единственная альтернатива - хранить данные в виде простого текста и надеяться на лучшее. Или не храните информацию вообще. В любом случае.
Либо так, либо, если вам нужна такая защита, и вам нужно локальное хранилище, создайте пользовательское приложение...
В качестве исследования этой темы у меня есть презентация под названием "Защита TodoMVC с помощью API веб-криптографии" ( видео, код).
Он использует API веб-криптографии для хранения списка задач, зашифрованного в localStorage паролем, защищающим приложение и использующим ключ, полученный из пароля, для шифрования. Если вы забудете или потеряете пароль, восстановление не будет. (Отказ от ответственности - это был POC, а не предназначенный для производственного использования.)
Как утверждают другие ответы, это все еще подвержено XSS или вредоносным программам, установленным на клиентском компьютере. Тем не менее, любые конфиденциальные данные также будут в памяти, когда данные хранятся на сервере и приложение используется. Я полагаю, что автономная поддержка может быть убедительным вариантом использования.
В конце концов, шифрование localStorage, вероятно, защищает данные только от злоумышленников, которые имеют доступ только для чтения к системе или ее резервным копиям. Он добавляет небольшую глубину защиты для OWASP Top 10 item A6-Sensitive Data Exposure и позволяет вам ответить "Сохраняется ли какая-либо из этих данных в виде открытого текста в долгосрочной перспективе?" правильно.
Это действительно интересная статья здесь. Я рассматриваю возможность внедрения шифрования JS для обеспечения безопасности при использовании локального хранилища. Совершенно очевидно, что это обеспечит защиту только в том случае, если устройство украдено (и реализовано правильно). Он не обеспечит защиту от клавиатурных шпионов и т. Д. Однако это не проблема JS, поскольку угроза кейлоггера - это проблема всех приложений, независимо от платформы их исполнения (браузер, нативный). Что касается статьи "JavaScript, криптографически опасный", на которую ссылается первый ответ, у меня есть одна критика; В нем говорится: "Вы можете использовать SSL/TLS для решения этой проблемы, но это дорого и сложно". Я думаю, что это очень амбициозный иск (и, возможно, довольно предвзятый). Да, SSL имеет свою стоимость, но если вы посмотрите на стоимость разработки собственных приложений для нескольких ОС, а не для веб-приложений из-за одной только этой проблемы, стоимость SSL станет незначительной.
Мой вывод - есть место для кода шифрования на стороне клиента, однако, как и во всех приложениях, разработчики должны признать его ограничения и реализовать его, если это соответствует их потребностям, и обеспечить способы снижения его рисков.
Недоступно для любой веб-страницы (правда), но легко доступно и легко редактируется с помощью инструментов разработчика, таких как chrome (ctl-shift-J). Следовательно, перед сохранением значения требуется пользовательская криптография.
Но если javascript необходимо расшифровать (проверить), тогда алгоритм дешифрования доступен и может быть изменен.
Javascript нужен полностью безопасный контейнер и возможность правильно реализовывать закрытые переменные и функции, доступные только интерпретатору js. Но это нарушает безопасность пользователей - поскольку данные отслеживания могут использоваться безнаказанно.
Следовательно, JavaScript никогда не будет полностью безопасным.
Нет.
localStorage доступен для любой веб-страницы, и если у вас есть ключ, вы можете изменить любые данные, которые вы хотите.
При этом, если вы можете придумать способ безопасного шифрования ключей, не имеет значения, как вы переносите данные, если вы можете хранить данные в закрытии, то эти данные (в некоторой степени) безопасны.