Расширения обладают особыми привилегиями в браузере, что делает их привлекательной целью для злоумышленников. Если расширение скомпрометировано, каждый пользователь этого расширения становится уязвимым для вредоносного и нежелательного вторжения. Обеспечьте безопасность расширения и защиту его пользователей, внедрив следующие методы.
Защита учетных записей разработчиков
Код расширения загружается и обновляется через учетные записи Google. Если учетные записи разработчиков будут взломаны, злоумышленник сможет напрямую распространить вредоносный код среди всех пользователей. Защитите эти учетные записи, создав специальные учетные записи для разработчиков и включив двухфакторную аутентификацию , предпочтительно с использованием ключа безопасности .
Сохраняйте избирательность в выборе групп.
При использовании групповой публикации ограничьте группу доверенными разработчиками. Не принимайте запросы на членство от неизвестных лиц.
Никогда не используйте HTTP.
При запросе или отправке данных избегайте HTTP-соединений. Предполагайте, что любые HTTP-соединения будут содержать перехватчики или содержать изменения. Всегда следует отдавать предпочтение HTTPS, поскольку он имеет встроенную защиту, предотвращающую большинство атак типа «человек посередине» .
Запросить минимальные разрешения
Браузер Chrome ограничивает доступ расширения к тем правам, которые были явно запрошены в манифесте . Расширениям следует минимизировать свои разрешения, регистрируя только API и веб-сайты, от которых они зависят. Произвольный код следует свести к минимуму.
Ограничение прав доступа расширения ограничивает возможности потенциального злоумышленника по использованию уязвимостей.
Междоменный XMLHttpRequest
Расширение может использовать XMLHttpRequest только для получения ресурсов как от себя самого, так и от доменов, указанных в разрешениях.
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"permissions": [
"/*",
"https://*.google.com/"
],
"manifest_version": 2
}
Это расширение запрашивает доступ ко всему содержимому developer.chrome.com и поддоменам Google, указывая в разрешениях "/*" и "https://*google.com/" . Даже если расширение будет взломано, оно всё равно будет иметь разрешение только на взаимодействие с веб-сайтами, соответствующими заданному шаблону . Злоумышленник не сможет получить доступ к "https://user_bank_info.com" или взаимодействовать с "https://malicious_website.com" .
Ограничить количество полей манифеста
Включение ненужных регистраций в манифест создает уязвимости и делает расширение более заметным. Ограничьте поля манифеста только теми, от которых зависит расширение, и укажите конкретные поля для регистрации.
Возможно внешнее подключение
Используйте поле externally_connectable чтобы указать, с какими внешними расширениями и веб-страницами расширение будет обмениваться информацией. Ограничьте круг лиц, с которыми расширение может устанавливать внешние соединения, только доверенными источниками.
{
"name": "Super Safe Extension",
"externally_connectable": {
"ids": [
"iamafriendlyextensionhereisdatas"
],
"matches": [
"/*",
"https://*google.com/"
],
"accepts_tls_channel_id": false
},
...
}
Ресурсы, доступные через Интернет
Предоставление доступа к ресурсам через Интернет, в разделе web_accessible_resources , позволит веб-сайтам и злоумышленникам обнаружить расширение.
{
...
"web_accessible_resources": [
"images/*.png",
"style/secure_extension.css",
"script/secure_extension.js"
],
...
}
Чем больше доступных в интернете ресурсов, тем больше возможностей для злоумышленника может использовать уязвимость. Сведите количество таких файлов к минимуму.
Включите явную политику безопасности контента.
Включите в манифест политику безопасности контента для расширения, чтобы предотвратить атаки межсайтового скриптинга. Если расширение загружает ресурсы только само с себя, зарегистрируйте следующее:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": "default-src 'self'"
"manifest_version": 2
}
Если расширению необходимо включить скрипты с определенных хостов, их можно добавить:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": "default-src 'self' https://extension.resource.com"
"manifest_version": 2
}
Избегайте исполняемых API.
API-интерфейсы, выполняющие код, следует заменить более безопасными альтернативами.
document.write() и innerHTML
Хотя динамическое создание HTML-элементов с помощью document.write() и innerHTML может показаться проще, это делает расширение и веб-страницы, от которых оно зависит, уязвимыми для внедрения вредоносных скриптов злоумышленниками. Вместо этого следует вручную создавать DOM-узлы и использовать innerText для вставки динамического контента.
function constructDOM() {
let newTitle = document.createElement('h1');
newTitle.innerText = host;
document.appendChild(newTitle);
}
eval()
По возможности избегайте использования eval() во избежание атак, поскольку eval() выполнит любой переданный ей код, который может быть вредоносным.
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// WARNING! Might be evaluating an evil script!
var resp = eval("(" + xhr.responseText + ")");
...
}
}
xhr.send();
Вместо этого отдайте предпочтение более безопасным и быстрым методам, таким как JSON.parse()
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// JSON.parse does not evaluate the attacker's scripts.
var resp = JSON.parse(xhr.responseText);
}
}
xhr.send();
Используйте скрипты контента с осторожностью.
Хотя скрипты контента существуют в изолированном мире , они не застрахованы от атак:
- Скрипты содержимого — единственная часть расширения, которая напрямую взаимодействует с веб-страницей. Из-за этого вредоносные веб-страницы могут манипулировать частями DOM, от которых зависит скрипт содержимого, или использовать неожиданные особенности поведения веб-стандартов, такие как именованные элементы .
- Для взаимодействия с DOM веб-страниц скрипты содержимого должны выполняться в том же процессе рендеринга, что и веб-страница. Это делает скрипты содержимого уязвимыми для утечки данных через побочные атаки (например, Spectre ), а также для захвата злоумышленником, если вредоносная веб-страница скомпрометирует процесс рендеринга.
Конфиденциальную работу следует выполнять в отдельном процессе, например, в фоновом скрипте расширения. Избегайте случайного раскрытия прав доступа к контентным скриптам расширения:
- Предположим, что сообщения из скрипта контента могли быть созданы злоумышленником (например, необходимо проверять и очищать все входные данные и защищать ваши скрипты от межсайтового скриптинга ).
- Следует исходить из того, что любые данные, отправляемые в скрипт контента, могут попасть на веб-страницу. Не отправляйте конфиденциальные данные (например, секреты расширения, данные с других веб-ресурсов, историю просмотров) в скрипты контента.
- Ограничьте область действия привилегированных действий, которые могут быть запущены скриптами содержимого. Не позволяйте скриптам содержимого запускать запросы к произвольным URL-адресам или передавать произвольные аргументы в API расширений (например, не разрешайте передачу произвольных URL-адресов в API
fetchилиchrome.tabs.create).
Регистрация и очистка входных данных
Защитите расширение от вредоносных скриптов, ограничив количество прослушивателей только теми, которые ожидает расширение, проверяя отправителей входящих данных и очищая все входные данные.
Расширение должно регистрироваться для runtime.onRequestExternal только в том случае, если оно ожидает связи с внешним веб-сайтом или расширением. Всегда проверяйте, соответствует ли отправитель доверенному источнику.
// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id === kFriendlyExtensionId)
doSomething();
});
Даже сообщения, передаваемые через событие runtime.onMessage из самого расширения, следует тщательно проверять, чтобы убедиться, что отправитель сообщения не является результатом использования скомпрометированного скрипта содержимого .
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.allowedAction)
console.log("This is an allowed action.");
});
Предотвратите выполнение скрипта злоумышленника расширением путем проверки пользовательского ввода и входящих данных, даже из самого расширения и одобренных источников. Избегайте использования исполняемых API .
function sanitizeInput(input) {
return input.replace(/&/g, '&').replace(/</g, '<').replace(/"/g, '"');
}