Какая безопасность нарушится с target="_blank"?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Уязвимость target="_blank": Tabnabbing
Использование target="_blank" без дополнительных мер безопасности может привести к серьёзной уязвимости под названием tabnabbing (захват вкладки).
Суть проблемы
Когда вы открываете ссылку с target="_blank", новая вкладка получает доступ к объекту window.opener. Это означает, что код на внешнем сайте может:
- Перенаправить исходную вкладку на фишинговый сайт
- Подменить содержимое страницы
- Украсть данные пользователя
Сценарий атаки:
- Пользователь на вашем сайте нажимает ссылку на внешний (недоверенный) сайт
- target="_blank" открывает новую вкладку
- На внешнем сайте может быть вредоносный код:
// На внешнем (вредоносном) сайте
window.opener.location = "https://phishing-site.com/fake-login";
// Пользователь видит на исходной вкладке поддельную страницу входа
- Пользователь видит свой сайт, но это фишинг, и вводит пароль
- Атакующий получает доступ к аккаунту
Решение: rel="noopener noreferrer"
Правильный способ использования target="_blank":
<!-- Неправильно -->
<a href="https://external-site.com" target="_blank">Открыть</a>
<!-- Правильно -->
<a href="https://external-site.com" target="_blank" rel="noopener noreferrer">Открыть</a>
Что делают эти атрибуты:
- rel="noopener" — отключает доступ к window.opener. Это самое важное для защиты от tabnabbing
- rel="noreferrer" — не отправляет HTTP Referer на внешний сайт (добавляет приватность)
В современных браузерах (Chrome 49+, Firefox 52+) target="_blank" автоматически устанавливает noopener, но рекомендуется указывать явно для совместимости.
React/Next.js: правильная реализация
// Компонент с внешней ссылкой
export function ExternalLink({ href, children }) {
return (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
>
{children}
</a>
);
}
// Использование
<ExternalLink href="https://example.com">Нажми меня</ExternalLink>
Или можно использовать кастомный хук для упрощения:
function useExternalLink(href) {
return {
href,
target: "_blank",
rel: "noopener noreferrer"
};
}
// В компоненте
<a {...useExternalLink("https://example.com")}>Ссылка</a>
Дополнительные меры безопасности
1. CSP (Content Security Policy) Настройте CSP заголовок, чтобы ограничить доступ к window.opener:
Content-Security-Policy: default-src "self"; script-src "self"
2. Валидация ссылок Проверяйте, что href указывает на безопасный протокол:
function isValidExternalLink(href) {
try {
const url = new URL(href);
return ["http:", "https:"].includes(url.protocol);
} catch {
return false;
}
}
// Использование
{isValidExternalLink(href) && (
<a href={href} target="_blank" rel="noopener noreferrer">
Ссылка
</a>
)}
3. Whitelist доменов Для критичных ссылок делайте whitelist:
const TRUSTED_DOMAINS = ["github.com", "stackoverflow.com", "mdn.org"];
function isTrustedLink(href) {
const url = new URL(href);
return TRUSTED_DOMAINS.includes(url.hostname);
}
Заключение
target="_blank" — не опасен сам по себе, но **всегда используй rel="noopener noreferrer"**. Это стандартная практика и защищает пользователей от tabnabbing атак. В фронтенде React/Next.js рекомендуется либо использовать утилиты для форматирования внешних ссылок, либо создать переиспользуемый компонент ExternalLink.