We recently found a vulnerability affecting Hyundai and Genesis vehicles where we could remotely control the locks, engine, horn, headlights, and trunk of vehicles made after 2012.
To explain how it worked and how we found it, we have
@ꙅɿɘƚɔɘqꙅ as our mock car thief:
Our finding began with
@ꙅɿɘƚɔɘqꙅ reaching out to
@Brett Buerhaus and myself to help explore potential security issues affecting vehicle telematics services.
Most car research we'd seen in the past involved really cool crypto attacks on physical keys, but what about the websites?
Both the Hyundai and Genesis mobile apps allow authenticated users to start/stop/lock/unlock their vehicle. Since we had access to a Hyundai, we began proxying all of the app traffic through Burp Suite and seeing what actual API calls were taking place.
The following is the simplified HTTP request to normally unlock the car:
POST /ac/v2/rcs/rdo/unlock HTTP/1.1
Access_token: token
{"userName":"EMAIL","vin":"VIN"}
The "Access_token" header was our JWT generated from authenticating via email/password to the mobile app.
What was interesting was that we were re-sending our email within the JSON body of the POST request. This was irregular as the server should be able to identify our email via our session token in the JWT.
We were curious: how was the server handling the JSON email parameter?
If we modified the email parameter to anything else besides the JWT email, the server would return "unauthorized".
It appeared that the server was comparing the email we sent in the JSON body to the email address parsed from our JWT and performing some sort of pre-flight check.
Since this was being done on the actual request to unlock the car, if it could be bypassed then we could theoretically unlock the car and perform all other actions.
We needed to find some way to trick the server into parsing out a victim email as valid from both of our inputs.
The first approach we thought of was fuzzing the Hyundai user account registration. Immediately, we noticed that the server did not require users to confirm their email address. There additionally appeared to be a very loose regex which allowed control characters in your email.
We played around with this for a while, until we tried something that worked:
By adding a CRLF character at the end of an already existing victim email address during registration, we could create an account which bypassed the JWT and email parameter comparison check!
To test if this worked, we sent an HTTP request to an endpoint which lists vehicles connected to the account using the following variables:
Registered JWT email: victim@gmail.com%0d
JSON parameter email: victim@gmail.com
The HTTP response returned the victim's VIN! We were in!
Our final check was to see if we could perform actual actions like unlocking or starting the car using our tampered JWT.
If we could do this, it would be full account and full vehicle takeover for all remotely enabled Hyundai (and, later we learned, Genesis) vehicles.
We sent the HTTP request using our CRLF-appended victim account to attempt to remotely unlock the vehicle connected to the victim's email address. The service took a few seconds, then finally returned "200 OK".
@ꙅɿɘƚɔɘqꙅ confirmed that his car had unlocked!
Since exploiting this involved many steps, we took all of the requests necessary to exploit this and put it into a python script which only needed the victim's email address. After inputting this, you could then execute all commands on the vehicle and takeover the actual account.
After putting everything together, we reported the issue to Hyundai and worked with them to confirm the fix.
Thanks for reading! This thread is a small part of a few months of web security research in the auto industry. We're hoping to disclose more related issues in the future.
Nearly forgot: huge thanks to
@@netspooky@haunted.computer for making the amazing ASCII art in the python script