Ищем подходящий автомобиль…

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

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

_gs3fvfdtwcumj4i9fyzwbdwvy4.gif

С чего все началось?


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

Я использовал mitmproxy (Man In The Middle Proxy) — программа для атаки «человек посередине». Есть много инструкций по её установке и настройке, а общий принцип такой:

  1. Подключаешься к домашнему WiFi с телефона и компьютера
  2. Запускаешь mitmproxy на компьютере
  3. В телефоне прописываешь локальный адрес компьютера как основной прокси (уже можно смотреть внутрь http)
  4. Скачиваешь и подтверждаешь сертификат на телефоне (позволяет заглядывать внутрь https)


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

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

Bug bounty Mail.ru


Я оформил всю информацию на hackerone и отправил на рассмотрение. После опыта взаимодействия с баг баунти Яндекса, я не рассчитывал на быстрый ответ, однако уже через 3 минуты некто »3apa3a» закрыл мой репорт. Отличная скорость, Mail.ru!

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

qn3_1vv7iselt7k0vya4b-4ddiy.png

Ну что ж. Раз это публичные данные, давайте развлекаться!

Как получить данные?


Информацию о 10 ближайших водителях к геопозиции можно получить, отправив POST запрос на следующий адрес:

https://c-api.city-mobil.ru/getdrivers

При этом в теле запроса нужно указать интуитивно-понятные параметры:

{
    "latitude": LAT,
    "longitude": LON,
    "limit": 10,
    "method": "getdrivers",
    "radius": 5,
    "tariff_group": [ 4, 5, 6 ],
    "ver": "4.33.0"
}

Здесь tariff_group — массив классов авто. Например, эконом, комфорт, бизнес и т.п.
При этом поля radius и limit не работают, как надо, но и убрать их нельзя.

В итоге, запрос на получение информации можно отправить просто из командной строки:

curl -X POST --data '{ "latitude": 55.7, "limit": 10, "longitude": 37.6, "method": "getdrivers", "radius": 5, "tariff_group": [4], "ver": "4.33.0" }' https://c-api.city-mobil.ru/getdrivers

В ответ приходит JSON с данными о 10 ближайших к (LAT, LON) автомобилях:

Ответ сервера
{ 
   "drivers":[ 
      { 
         "id":"1c1f6779f893af6fe5bf4509af7366cd",
         "lt":"55.7025061",
         "ln":"37.5954334",
         "direction":"3",
         "CarColorCode":"000000",
         "car_type":"comfort_plus"
      },
      { 
         "id":"1a13d0daad9b6a3fa2b3d04a5b6f8c2a",
         "lt":"55.7019682",
         "ln":"37.6054896",
         "direction":"3",
         "CarColorCode":"000000",
         "car_type":"comfort"
      },
      { 
         "id":"c7c1634fae41a68924083af1d496d0a7",
         "lt":"55.7014223",
         "ln":"37.6067352",
         "direction":"3",
         "CarColorCode":"000000",
         "car_type":"comfort_plus"
      },
      { 
         "id":"f15ce054ccdaa268b16a0904b9eecdae",
         "lt":"55.6956527",
         "ln":"37.5972063",
         "direction":"4",
         "CarColorCode":"000000",
         "car_type":"sedan"
      },
      { 
         "id":"94ebc0fcc644bb1da4b57e7d23942e6d",
         "lt":"55.694786",
         "ln":"37.5982642",
         "direction":"4",
         "CarColorCode":"000000",
         "car_type":"sedan"
      },
      { 
         "id":"7251c45ee945c9cb839d69d5902b9f17",
         "lt":"55.7009351",
         "ln":"37.6094206",
         "direction":"3",
         "CarColorCode":"000000",
         "car_type":"comfort"
      },
      { 
         "id":"cb9dab2ba7379c3db817dd76ec68e6c5",
         "lt":"55.6950137",
         "ln":"37.6041883",
         "direction":"8",
         "CarColorCode":"000000",
         "car_type":"sedan"
      },
      { 
         "id":"761891d9c1129b1678c3eba616249e2b",
         "lt":"55.6944542",
         "ln":"37.5951122",
         "direction":"2",
         "CarColorCode":"000000",
         "car_type":"sedan"
      },
      { 
         "id":"4f0e835751cadaa5d5386f0e1374f315",
         "lt":"55.7066516",
         "ln":"37.6011767",
         "direction":"7",
         "CarColorCode":"000000",
         "car_type":"sedan"
      },
      { 
         "id":"2eb330cad5e5d9c87e6d0600a9ff10e8",
         "lt":"55.7066801",
         "ln":"37.6009127",
         "direction":"8",
         "CarColorCode":"000000",
         "car_type":"comfort"
      }
   ],
   "nearest":{ 
      "duration":420
   },
   "service_status":1
}


Посмотрим, что тут у нас


{ 
    "id":"2eb330cad5e5d9c87e6d0600a9ff10e8",
    "lt":"55.7066801",
    "ln":"37.6009127",
    "direction":"8",
    "CarColorCode":"000000",
    "car_type":"comfort"
}


Идентификатор, широта, долгота, код направления (Северо-запад), код цвета и тип авто. Отлично!

Нужно больше данных!


Так как поля лимит и радиус в запросе игнорируются, а в ответ возвращается не больше 10 ближайших авто, нельзя так просто взять и выбрать N точек на Москву, чтобы за N запросов получить всю информацию об автопарке.

Но решение есть. Я написал алгоритм, похожий на заливку, который запускает запросы на поиск с координатами водителей, найденных на прошлом этапе. Ещё я все это дело распараллелил, а прокси подключать не пришлось — mail.ru позволяет мне делать все несколько тысяч запросов за минуту с одного и того же ip.

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

Давайте посмотрим, как работает алгоритм еще раз
_gs3fvfdtwcumj4i9fyzwbdwvy4.gif


Думаете, сколько водителей на линии в воскресенье утром?
В 11 утра их было 4374

Но разве нас интересует срез? Давайте посмотрим в динамике.

hbwgmwde3ny4-eoo9fzcqf7wpl4.png

Найс. А как эти водители распределены в пространстве?

ocgsvjxaf9goeppl2l8rv3vvyj4.gif

Ну и напоследок давайте проследим за каким-нибудь водителем.

potccx-li8zwvyzlp-yp-ior7j4.gif

Вот, видно маршрут. А ведь можно еще поднять частоту опроса и получить более точные данные.

И что такого?


А то, что данные вроде как важные.

Во-первых, можно оценить долю рынка и доходность компании «Ситимобил».

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

В-третьих, раз можно отследить конкретного таксиста, можно отследить и его клиента. Это уже серьёзно. По факту, можно узнать, куда уехал человек на «Ситимобиле», если вы знаете, где он сел в такси.

Заключение


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

Если Mail.ru все еще считают, что эту информацию не нужно защищать, то Яндекс.Такси, вот вам гора данных. С её помощью вы сможете забрать часть прибыли Ситимобила.

Если же Mail.ru признаёт, что данные чувствительные и закрывает к ним доступ, то будет честно выплатить вознаграждение по bug bounty.

Как, думаете, ещё можно использовать данные о таксистах?

Спасибо, что дочитали! Надеюсь, вам было интересно.
Успехов!

© Habrahabr.ru