Skip to content

Commit 0a51109

Browse files
authored
Translated article
Статью перевела, замечания и пожелания по переводу приветствуются. Также не знаю, нужно ли переводить текст в коде в файлах-примерах (которые отдельно от статьи идут).
1 parent 6021f7c commit 0a51109

1 file changed

Lines changed: 221 additions & 0 deletions

File tree

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
Атака Clickjacking
2+
3+
Атака типа "clickjacking" (англ. "захват клика") позволяет вредоносной странице кликнуть по "сайту жертве" от имени посетителя.
4+
5+
Многие сайты были взломаны подобным способом, включая Twitter, Facebook, Paypal и другие. Все они, конечно же, были восстановлены.
6+
7+
Идея
8+
9+
Идея данной атаки очень проста.
10+
11+
Вот как clickjacking атака была проведена для Facebook:
12+
13+
Посетителя заманивают на вредоносную страницу (не важно как).
14+
На странице есть ссылка, которая выглядит безобидно (например "Разбогатей прямо сейчас" или "Нажми здесь, это очень смешно").
15+
Поверх этой ссылки вредоносная страница размещает прозрачный <iframe> с src с сайта facebook.com таким образом, что кнопка "like" находится прямо над этой ссылкой. Обычно это делается с помощью z-index в CSS.
16+
При попытке клика на эту ссылку, посетитель на самом деле нажимает на кнопку.
17+
18+
Демонстрация
19+
20+
Вот как выглядит вредоносная страница. Для наглядности <iframe> полупрозрачный (на реальных вредоносных страницах он полностью прозрачен):
21+
22+
<style>
23+
iframe { /* iframe с сайта жертвы */
24+
width: 400px;
25+
height: 100px;
26+
position: absolute;
27+
top:0; left:-20px;
28+
*!*
29+
opacity: 0.5; /* в реальности opacity:0 */
30+
*/!*
31+
z-index: 1;
32+
}
33+
</style>
34+
35+
<div>Нажми, чтобы разбогатеть:</div>
36+
37+
<!-- The url с сайта жертвы -->
38+
*!*
39+
<iframe src="/clickjacking/facebook.html"></iframe>
40+
41+
<button>Нажмите сюда!</button>
42+
*/!*
43+
44+
<div>...И ты крутой (вообще-то я крутой хакер)!</div>
45+
46+
Полная демонстрация атаки:
47+
48+
[codetabs src="clickjacking-visible" height=160]
49+
50+
Здесь у нас есть полупрозрачный <iframe src="facebook.html">, и в примере мы видим его висящим поверх кнопки. Клик на кнопку фактически кликает на iframe, но это не видно пользователю, потому что iframe прозрачный.
51+
52+
В результате если пользователь авторизован на сайте Facebook ("Запомнить меня" обычно всегда активировано), то он добавляет "like". В Twitter это будет кнопка "Follow".
53+
54+
Вот тот же пример, но более приближенный к реальности с opacity:0 для <iframe>:
55+
56+
[codetabs src="clickjacking" height=160]
57+
58+
Всё, что нам необходимо для атаки — это расположить <iframe> на вредоносной странице так, чтобы кнопка находилась прямо над ссылкой. Обычно это можно сделать с помощью CSS-позиционирования.
59+
60+
Эта атака срабатывает только на действия мыши.
61+
62+
Технически, если у нас есть текстовое поле для взлома, мы можем расположить iframe таким образом, чтобы текстовые поля перекрывали друг друга. Тогда посетитель при попытке сфокусироваться на текстовом поле, которое он видит на странице, фактически будет фокусироваться на текстовом поле внутри iframe.
63+
64+
Но есть одна проблема. Всё, что посетитель печатает, будет скрыто, потому что iframe не виден. Обычно люди перестают печатать, когда не видят на экране новых символов.
65+
66+
Примеры слабой защиты
67+
68+
Самым старым вариантом защиты является код JavaScript, запрещающий открытие страницы во фрейме (так называемый "framebusting").
69+
70+
Выглядит он вот так:
71+
72+
if (top != window) {
73+
top.location = window.location;
74+
}
75+
76+
В этом случае если окно обнаруживает, что оно открыто во фрейме, оно автоматически располагает себя сверху.
77+
78+
Этот метод не является надёжной защитой поскольку появилось множество способов его обойти. Рассмотрим некоторые из них.
79+
80+
Блокировка top-навигации.
81+
Мы можем заблокировать переход вызванный сменой top.location в beforeunload событии.
82+
83+
Верхняя страница (принадлежащая хакеру) устанавливает обработчик на это событие, и когда iframe пытается изменить top.location, посетитель видит сообщение с вопросом действительно ли он хочет покинуть эту страницу.
84+
85+
Вот пример:
86+
87+
window.onbeforeunload = function() {
88+
window.onbeforeunload = null;
89+
return "Ты хочешь покинуть эту страницу так и не узнав все её секреты (ха-ха-ха)?";
90+
};
91+
92+
В большинстве случаев посетитель ответит отрицательно, поскольку он не знает об iframe - всё что он видит, это верхнюю страницу, которую нет причин покидать. Поэтому top.location не изменится.
93+
94+
В действии:
95+
96+
[codetabs src="top-location"]
97+
98+
Атрибут Sandbox
99+
100+
Одной из возможностей, ограниченных в sandbox атрибутах, является навигация. Соответственно iframe внутри sandbox не изменит top.loacation.
101+
102+
Поэтому мы можем добавить iframe с sandbox="allow-scripts allow-forms". Это снимет некоторые ограничения, разрешая при этом использование скриптов и форм. Но мы опускаем allow-top-navigation, чтобы изменение top.location было запрещено.
103+
104+
Вот код данного примера:
105+
106+
<iframe *!*sandbox="allow-scripts allow-forms"*/!* src="facebook.html"></iframe>
107+
108+
Есть и другие способы обойти эту простую защиту.
109+
110+
Заголовок X-Frame-Options
111+
112+
Заголовок X-Frame-Options со стороны сервера может разрешать или запрещать отображение страницы внутри фрейма.
113+
114+
Этот заголовок должен быть отправлен сервером: браузер проигнорирует его, если найдет в теге <meta>. Поэтому при <meta http-equiv="X-Frame-Options"...> ничего не произойдёт.
115+
116+
Заголовок может иметь 3 значения:
117+
118+
DENY : Никогда не показывать страницу внутри фрейма.
119+
120+
SAMEORIGIN : Разрешить открытие страницы внутри фрейма только в том случае, если родительский документ имеет такое же происхождение.
121+
122+
ALLOW-FROM domain : Разрешить открытие страницы внутри фрейма только в том случае, если родительский документ находится на указанном в заголовке домене.
123+
124+
Например, Twitter использует X-Frame-Options: SAMEORIGIN.
125+
126+
Вот результат:
127+
128+
'''html
129+
<iframe src="https://twitter.com"></iframe>
130+
'''
131+
132+
<!-- ebook: prerender/ chrome headless dies and timeouts on this iframe -->
133+
<iframe src="https://twitter.com"></iframe>
134+
135+
В зависимости от того, какой браузер вы используете, iframe выше либо будет пустым, либо оповестит вас о том, что его невозможно отобразить.
136+
137+
Отображение с ограниченными возможностями.
138+
139+
У заголовка X-Frame-Options есть побочный эффект. Другие сайты не смогут отобразить нашу страницу во фрейме даже если у них будут на то веские причины.
140+
141+
Так что есть другие решения.
142+
143+
Например, мы можем "накрыть" страницу блоком <div> с заданными height: 100%; и width: 100%;, чтобы он перехватывал все клики. Этот <div> должен исчезнуть если window == top или если мы поймём, что защита нам не нужна.
144+
145+
Что-то вроде этого:
146+
147+
<style>
148+
#protector {
149+
height: 100%;
150+
width: 100%;
151+
position: absolute;
152+
left: 0;
153+
top: 0;
154+
z-index: 99999999;
155+
}
156+
</style>
157+
158+
<div id="protector">
159+
<a href="/" target="_blank">Перейти к сайту</a>
160+
</div>
161+
162+
<script>
163+
// Здесь будет отображаться ошибка, если верхнее окно имеет другое происхождение
164+
// а здесь будет код, если всё в порядке
165+
if (top.document.domain == document.domain) {
166+
protector.remove();
167+
}
168+
</script>
169+
170+
Демонстрация:
171+
172+
[codetabs src="protector"]
173+
174+
Samesite cookie атрибут
175+
176+
Атрибут Samesite cookie также может не допустить clickjacking атаку. Целью этого атрибута является предотвращение отправки файлов cookie на веб-сайт, если пользователь не намерен посещать его. Этот атрибут был придуман для защиты от другой атаки — подделки межсайтовых запросов, но также помогает с clickjacking поскольку перехваченный клик обычно приводит к непреднамеренному запросу на другую страницу. Когда файл cookie имеет samesite атрибут, принимает ли он при этом значение strict или lax, он не отправляется на сайт, который загружен во фрейме.
177+
178+
Атрибут samesite может быть задан либо через заголовок ответа HTTP, либо с помощью JavaScript. Через HTTP это выглядит так:
179+
180+
Set-Cookie: demoCookie=demoValue; samesite=lax
181+
182+
или
183+
184+
Set-Cookie: demoCookie=demoValue; samesite=strict
185+
186+
С помощью JavaScript:
187+
188+
document.cookie = "demoCookie=demoValue; SameSite=Lax";
189+
document.cookie = "demoCookie=demoValue; SameSite=Strict";
190+
191+
Если задано значение lax, следующие типы запросов блокируются:
192+
193+
Form POST submit (<form method="POST" action="...">)
194+
iframe (<iframe src="..."></iframe>)
195+
AJAX ($.get("..."))
196+
Image (<img src="...">)
197+
Script (<script src="..."></script>)
198+
Stylesheet (<link rel="stylesheet" type="text/css" href="...">)
199+
200+
Если задано значение strict, эти типы запросов также блокируются, в дополнение к тем, что блокируются с помощью lax:
201+
202+
Clicking a link (<a href="..."></a>)
203+
Prerender (<link rel="prerender" href=".."/>)
204+
Form GET submit (<form method="GET" action="...">)
205+
206+
В данном случае нас беспокоит запрос через iframe. Попытка перехвата провалится, поскольку предполагается что пользователь не авторизован, например на странице Facebook, и не может лайкнуть ничего через iframe.
207+
208+
Атрибут samesite не сыграет никакой роли, если cookie-файлы не используются. Это может позволить веб-сайтам легко отображать публичные, неаутентифицированные страницы в iframe на неаффилированных сайтах. Однако, это также может позволить проведение clickjacking атаки в некоторых случаях. Например, сайт для анонимных опросов, который предотвращает повторное голосование пользователя путем проверки IP адреса, останется уязвимым к атаке, потому что не аутентифицирует пользователей с помощью cookies.
209+
210+
Итого
211+
212+
Атака сlickjacking - это способ "обмануть" пользователей, чтобы они кликнули на вредоносный сайт, не подозревая, что происходит. Это опасно, если на странице есть важные действия, активируемые щелчком мыши.
213+
214+
Хакер может разместить ссылку на свою вредоносную страницу в сообщении или найти другие способы как заманить пользователей. Вариантов множество.
215+
216+
С одной стороны — эта атака "неглубокая", ведь хакер перехватывает только один клик. Но с другой стороны, если хакер знает, что после этого клика появятся другие элементы управления, то он может хитростью заставить пользователя кликнуть на них.
217+
218+
Данная атака довольно опасна, ведь при разработке интерфейсов мы не предполагаем, что хакер может кликнуть от имени пользователя. Поэтому уязвимости могут быть обнаружены в совершенно неожиданных местах.
219+
220+
В настоящий момент для защиты от этой атаки рекомендуется использовать X-Frame-Options: SAMEORIGIN на страницах и целых сайтах, которые не предназначены для просмотра во фрейме.
221+
Если же мы хотим отображать страницу во фрейме и при этом оставаться в безопасности, то стоит использовать перекрывающий блок <div>.

0 commit comments

Comments
 (0)