Синема, синема, си-не-ма… от тебя мы без ума

в 8:43, , рубрики: android, android development, java, SSL, безопасность сайтов, Веб-разработка, информационная безопасность, кинематограф

— Каждому своё. Будущее нас рассудит. В дорогу! Наш зритель ждёт нас.

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

Итак, прочитав перед работой новость о том, что выпустили мобильное приложение, я уже планирую на какой фильм пойти на выходные с семьей воспользовавшись новым сервисом. Придя на работу, скачиваю приложение и получаю заставку минут на 5 и потом сообщение про ошибку сети. Как же так… По отзывам все у всех работает, а у меня что? Честно сказать не сразу догадался, пробовал и удалять и ставить заново, и только в последний момент попробовал отключить WiFi и запустить через 3G. Заработало! Все дело оказалось в WiFi сети предприятия, админ которой заботливо открыл только те порты, которые необходимы были для работы. Ну что ж — логично. Только немного странно. Зачем использовать нестандартный порт для приложения? Ведь использование WiFi на предприятиях популярно и для работников и для гостей. Тут то меня и зацепило…

Все цитаты и крылатые фразы взяты из фильма «Человек с бульвара Капуцинов».

— Когда у человека есть цель в жизни, смерть ему не страшна.

Возможно, надо было просто пойти к админу и попросить его понять через какой порт ломится приложение. На том бы все и закончилось. Но мы простых путей не ищем. Не так ли? И наша любознательность требовала большего. Тем более что статей «как открыть исходный код Android приложения» последнее время все больше и даже если не хочешь, обращаешь на них внимание по броским заголовкам вроде этой и этой. А для скачивания самого APK файла, есть плагин для Google Chrome.

Получив код приложения — ищем адрес сайта, чтоб понять — куда же оно стучится. Обнаруживаем что порт сервера: 28443. Что-то знакомое? Ну почти. Но об этом позже.

Бегло поискав все строки с указанием адреса в пределах одного файла — обнаружил массу интересного. И первое, на что обратил внимание — ссылка отправки SMS с кодом подтверждения номера телефона не имеет https://.

String str = requestGet("http://www.сайт-сети.ru/".concat("users/").concat("activate_cell_phone/").concat(paramString).concat("/"));

В качестве paramString передается номер пользователя, чей телефон надо подтвердить. Мне показалось, что я что-то упустил и надо было как то проверить мои догадки. Оставалось найти свой номер пользователя в системе. Как выяснилось дальше — больше.

— Билли… Заряжай!

При авторизации приложение делает заполнение формы, как мы это делали бы на сайте. Только с небольшим дополнением.
На сайте мы попадаем по ссылке http://www.сайт-сети.ru/users/login, а приложение использует ссылку http://www.сайт-сети.ru/users/login/mobapp:1
Заходим — авторизуемся… Я ожидал увидеть что-то вроде — вы успешно авторизованы. Но тут было больше. И самое главное был мой номер в системе.

"Auth":{"User":{"id":XXXXX,"login":"XXXXXXXXX","group_id":4,"created":"XXXXXXXXXXXX","modified":"XXXXXXXX",

Введя в адресной строке http://www.сайт-сети.ru/users/activate_cell_phone/XXXXX/, где XXXXX — наш номер в системе, я повторно получил SMS с кодом подтверждения.
Синема, синема, си не ма… от тебя мы без ума

Не так давно на хабре я встречал статью о том, что использовать открытую нумерацию заказов, пользователей и т.п. информации — зло. Но в данном случае зло не в порядковом номере, а в том что ссылка не защищена авторизацией. Обычный перебор этих номеров по порядку может привести как минимум к рассылке SMS активации номера телефона всем зарегистрированным пользователям. Что конечно негативно отразится на финансовом состоянии лицевого счета отправителя SMS — владельца сети кинотеатров. А когда их получит несколько тысяч жителей одного города от любимого кинотеатра — реакцию угадать будет не сложно.

Парни, кончайте эти сопли! Вас ждёт вторая серия!

Помните найденный порт — 28443? Зайдя на www.сайт-сети.ru:28443/ получаем отказ, что у нас нет сертификата. Теперь то точно понятно, что за порт и какой мы должны дать сертификат. Но приложение то его дает. И среди файлов приложения легко находится файл client.p12, который и является сертификатом. По всей видимости разработчики просто перенесли из веб-сайта в приложение методы доступа. Не подумав над тем, что они раздали всем желающим свой сертификат.

Для любознательных

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

  protected static final String URL_CREATE_ORDER = "Wga_CreateOrder";
  protected static final String URL_GET_ORDERS = "MyWeb_GetOrders";
  protected static final String URL_DROP_PLACE = "Wga_DropPlace";
  protected static final String URL_GET_PLACES = "Wga_GetPlaces";
  protected static final String URL_LOCK_PLACE = "Wga_LockPlace";
  protected static final String URL_SET_ORDER_TO_NULL = "Wga_SetOrderToNull";

Установка сертификата дает нам возможность зайти дальше. Написав в адресной строке https://www.сайт-сети.ru:28443/K*****r/ с комбинацией команд, получаем полный доступ к системе заказов:

  • Просмотр списка занятых мест на любой сеанс с номерами заказов для каждого места
  • Создание заказа на любой сеанс под видом любого пользователя, хоть весь зал, хоть весь кинотеатр
  • Отмена любого заказа, а можно вообще отменить все заказы
  • Просмотр списка заказов любого пользователя сети, где так же будут указаны его личные данные (ФИО, e-mail, номер телефона)
Несколько примеров

https://www.сайт-сети.ru:28443/K*****r/query?sp=MyWeb_GetOrders&IdClient=26001

<data>
<order IdOrder="9626565" idorder="9626565" ordercreatetime="2014-07-25 09:18:51.393" brokerage="0" timepayment="2014-07-25 09:22:01.326" orderexpiretime="" orderstate="2" orderprice="300.0000" orderpaysum="300.0000" orderrecalltickets="0" saledticketssum="300.0000" saledtickets="2" ordertotalticketssum="300.0" ordertotaltickets="2" name="**********" firstname="Антон" patronymic="" phone="" email="********@gmail.com" fax="" cellular="7983*******9" birthday="" orderdescription="Бронь из интернета, !!!ПРОВЕРЬ ОПЛАТУ!!!, пароль: 6649" orderpass="6649">
<performance showname="Планета обезьян: Революция" idperformance="4816821" performancestarttime="2014-07-25 12:40:00.0" hall="Зал1" building="Огни" idshow="5160915">
<place idplace="7902" rownom="10" placenom="11"/>
<place idplace="7903" rownom="10" placenom="10"/>
</performance>
</order>
</data>

https://www.сайт-сети.ru:28443/K*****r/query?sp=MyWeb_GetOrders&IdClient=11564

<data>
<order IdOrder="9628655" idorder="9628655" ordercreatetime="2014-07-27 10:01:56.256" brokerage="0" timepayment="2014-07-27 10:04:16.163" orderexpiretime="" orderstate="2" orderprice="320.0000" orderpaysum="320.0000" orderrecalltickets="0" saledticketssum="320.0000" saledtickets="2" ordertotalticketssum="320.0" ordertotaltickets="2" name="******" firstname="Мария" patronymic="Анатольевна" phone="" email="*******@bk.ru" fax="" cellular="7963*******7" birthday="" orderdescription="Бронь из интернета, !!!ПРОВЕРЬ ОПЛАТУ!!!, пароль: 6270" orderpass="6270">
<performance showname="Поддубный" idperformance="4817020" performancestarttime="2014-07-27 14:45:00.0" hall="Зал5" building="Огни" idshow="5160913">
<place idplace="8682" rownom="6" placenom="3"/>
<place idplace="8681" rownom="6" placenom="2"/>
</performance>
</order>
</data>

Стоит ли доверять таким разработчикам свои личные данные, свой кошелек — (ведь заказ можно и оплатить, а если его отменят, возврат денег на карту поступает через 5-7 дней, когда фильм уже пройдет). Ну а про распространение личных данных пользователей наверно вообще не стоит упоминать. Достаточно уже того что можно 100% знать что некая или некий конкретный человек идет в кино (а может и не один) в конкретное время и его не будет на протяжении длительности фильма. Сюжет из криминальной хроники прям.

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

Статья ни в коем случае не призывает воспользоваться всеми ошибками разработчиков и сайта и приложения. Хочется надеяться что они вынесут из этого соответствующий урок и исправят все ошибки. А пока ходите за билетами в кассу… Так надежнее…

Два билета на дневной сеанс — для меня… хм… и моей скво.

Автор: StormScreamer

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js