— Каждому своё. Будущее нас рассудит. В дорогу! Наш зритель ждёт нас.
Все началось очень хорошо, даже можно сказать замечательно. Город Барнаул получил долгожданную возможность посмотреть анонс фильмов через мобильное приложение в единственной сети кинотеатров. А самое главное делать бронирование и оплату билетов сидя дома на диване. К слову сказать, система покупки билетов существовала уже очень давно на сайте сети.
Итак, прочитав перед работой новость о том, что выпустили мобильное приложение, я уже планирую на какой фильм пойти на выходные с семьей воспользовавшись новым сервисом. Придя на работу, скачиваю приложение и получаю заставку минут на 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, который и является сертификатом. По всей видимости разработчики просто перенесли из веб-сайта в приложение методы доступа. Не подумав над тем, что они раздали всем желающим свой сертификат.
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