Hacking into Toyota’s global supplier management network
Discussion links: Twitter | Reddit
- Automotive News (Front page screenshot – February 8, 2023)
- Also featured in: Auto industry risks security breaches by underpaying white hat hackers
- Bleeping Computer
Key Points / Summary:
- I hacked Toyota’s Global Supplier Preparation Information Management System (“GSPIMS”), a web app used by Toyota employees and their suppliers to coordinate projects, parts, surveys, purchases, and other tasks related to the global Toyota supply chain.
- System Admin access achieved through accidentally introduced backdoor as part of a user impersonation/”Act As” feature.
- Any user could be logged in to just by knowing their email, completely bypassing the various corporate login flows.
- Read/write access to the global user directory containing 14k+ users was achieved.
- Data access achieved: 14k+ corporate user account details, confidential documents, projects, supplier rankings/comments, and more. Data access was global and not limited to North America.
- Issue was responsibly disclosed to Toyota in November 2022 and fixed in a timely manner.
Over the course of a slow week in late October 2022, I decided to explore the subdomains of various major companies to see if I could find any exploits worth reporting/writing about. I found several interesting Toyota websites. In 7 days, I reported 4 different security issues to Toyota, all of which were classified as “critical”. One of the reports had a remarkably severe impact and is one of the most severe vulnerabilities I have ever found (so far!)
I discovered what was essentially a backdoor login mechanism in the Toyota GSPIMS website/application that allowed me to log in as any corporate Toyota user or supplier just by knowing their email. I eventually uncovered a system administrator email and was able to log in to their account. Once that was done, I had full control over the entire global system. I used the word “staggering” to describe the amount of data I had access to in the Jacuzzi SmartTub hack, but that was relatively minor compared to this. I had full access to internal Toyota projects, documents, and user accounts, including user accounts of Toyota’s external partners/suppliers. External accounts include users from:
- Stanley Black & Decker
- Many more (note the various email domains in the screenshots below)
GSPIMS stands for “Global Supplier Preparation Information Management System”. It is an Angular single-page-application created and maintained by Toyota. At first, I didn’t know what GSPIMS was. Google showed a few job listings about it, but otherwise seemed obscure. I didn’t think it was that important at first, but I decided to put some time into it to see what might be hiding behind the login screen. It wasn’t until I bypassed the login screen that I saw the “Global Supplier Preparation Information Management System” label. Sounds important!
Bypassing the login
The login screen features corporate Toyota and Supplier login options:
Both options supply the same list of login methods:
- TMNA = Toyota Motor North America
- TME = Toyota Motor Europe
- TMC = Toyota Motor Corporation (Japan)
- TDEM = Toyota Daihatsu Engineering & Manufacturing (Asia)
- Other Affiliates = Unknown, this button does not currently work
Developers control access to Angular routes/pages by implementing CanActivate and CanActivateChild. Basically, when a user attempts to navigate to a route/page, you would determine if they are allowed to view it, and then return true or false. By patching both to return true, you can usually fully unlock an Angular app:
The logout code also needed to be removed to prevent a redirect back to the login page:
With those patches applied, the app loads and can be browsed:
JWTs for everyone!
Before abandoning work on the GSPIMS app, I looked through its code to see if there might have been any API keys, secret API endpoints, or anything else that might be interesting. I came across this function in the user service. Can you spot what is interesting about it?
It is interesting because it appears to be generating a JWT based on a provided email. No password required. I decided to compose this HTTP request to see if that createJWT endpoint actually worked. Even if it worked, it wouldn’t be enough without a valid email, which could have been difficult to figure out, especially if the underlying userbase was small.
Corporate Toyota emails use a predictable format in North America: firstname.lastname@example.org. That made guessing a valid email easier, but I still had to find someone. I Googled for Toyota employees involved in the supply chain, hoping to find someone who may be registered in the GSPIMS system. I found a promising match and formulated their email address based on their name. Then I fired off the createJWT HTTP request, and it returned a valid JWT!
It seems like I had discovered a way to generate a valid JWT for any Toyota employee or supplier registered in GSPIMS, completely bypassing the various corporate login flows, which probably also enforce two-factor authentication options. The reason createJWT exists will be revealed later in this post.
Utilizing the JWT was easy. The GSPIMS API authenticates via cookie, so I just added it through Chrome’s dev tools:
Escalating to System Admin
The user I logged in had the role of “Mgmt – Purchasing” which probably means they are in charge of organizing purchases of things from suppliers through this system. I had access to some data at this point, but I felt there was more waiting to be unlocked. Looking at the HTTP requests and responses, there is a rolePrivileges node in the user/details API response that returns information about the currently logged in user:
I wanted to try and find a user with the System Admin role. I noticed another API endpoint named findByEmail that returned information about a user’s account by just providing a valid email. Conveniently, this also tells you who the user’s managers are:
Checking the managers of the managers, etc. made it easy to find accounts that had elevated access to the system. Eventually I found a North America Regional Admin. That gave me access to the User Administration section. I then poked around more and found users with even higher access, such as Supplier Admin, Global Admin, and finally, System Admin.
In the GSPIMS settings, the tabs that appear are dependent on your role. There’s Regional Settings for Regional Admins, Global Settings for Global Admins, and System Admin Settings for System Admins. System Admins can access all the tabs. I also noticed that System Admins had access to substantially more users in the User Administration section. Regional Admins are probably only able to manage users in their region, whereas System Admins could manage everyone. With a System Admin JWT, I basically had total, global control over the entire system.
A few screenshots of various sets of users. Take note of the user and page counts in the bottom right corner (there’s a lot – 14,063 users across 563 pages!) Click on any image to enlarge it in a new tab.
I could edit any of those users:
Or add a new user using the user import button above the columns. There is also an export users button you can use to download user information.
Exploring the impact
Having full access, I looked around the GSPIMS app to see what was available to me as a System Admin. I was very careful to not modify anything. Here’s the System Admin Settings if you are curious about what is there. Nothing too exciting – it just controls what roles can access certain features.
Now on to more interesting things. The Parts section has a list of parts associated with the various projects. You choose an affiliate at the top and then the project to see the list of parts. Here is the parts list for a project:
It’s worth noting the projects are in codenames/numbers. It didn’t say anything like “2024 Toyota Corolla”. With a lot more time I probably could have figured out the codenames, but that was outside the scope of this investigation. Speaking of projects, I had access to all the active, global, and inactive projects:
I could view the details of each project, including who is involved, the schedule and milestones, and some type of survey feature. Click on any image to enlarge it in a new tab.
Can’t forget about the documents! Classified documents are all the rage nowadays.
Reviewing the HTTP trace I captured, I noticed you can also see Toyota’s various comments about their suppliers. It’s probably also visible in the UI somewhere.
The HTTP trace was captured by just having Fiddler open while browsing the app. The API is very generous with the amount of data it returns, in particular with the users list. You could download a lot of user information by increasing the page size and flipping through the pages.
You could also see all the suppliers and how Toyota ranks them regarding risk, delivery, and prep. There are almost 3,000 of them:
Finally, I discovered what the createJWT API was actually used for. There is an “Act As” feature that let me log in as any of those 14k+ global users. I could easily log in as anyone and get an idea of what projects they are working on, their tasks, surveys, etc. Whoever made the Act As system apparently didn’t realize they added a backdoor to the entire system. The Act As feature is only visible to certain users, like the System Admin user I was logged in as.
If a threat actor had discovered this issue, the consequences could have been severe. Here’s a few bad things they could have done. Please note that these are just ideas and none of these were carried out.
- Added their own user account with an elevated role, to retain access should the issue ever be discovered and fixed.
- Downloaded and leaked all the data.
- Delete everything or modify data in a way to be disruptive to global Toyota operations. Hopefully Toyota has working backups?
- Craft a highly targeted phishing campaign to attempt to capture real corporate login details, which could have exposed other Toyota systems to attacks. There’s 14k+ users available to attack. It’s one thing to have 14k+ corporate emails, but it’s another to have 14+ corporate emails and know exactly what they are working on/have worked on. If a supplier user has a habit of reusing passwords, it’s possible their own infrastructure could be attacked too.
Reporting to Toyota
The issue was reported to Toyota on November 3, 2022, and they responded later that same day confirming they received the report. On November 23, 2022, they confirmed the issue was remediated, although I noticed it was fixed before that when I randomly tested. I then informed them I would publish my writeup after the industry standard 90-day period has passed.
Toyota fixed the issue by making the createJWT and findByEmail endpoints return HTTP status 400 – Bad Request in all cases.
Out of all the security issues I have reported so far to various vendors, Toyota’s response was the fastest and most effective. I was very impressed with how quickly they responded and fixed the issue. Some companies can be slow to respond or fail to respond at all, so this experience was refreshing.
Thanks to this responsible disclosure, Toyota avoided what could have been a catastrophic leak of not only their own employees’ data, but the data of their partners/suppliers. Embarrassing internal comments and supplier rankings could have been published for the world to see. Toyota and their suppliers have been hit by cyberattacks before and it could have easily happened again.
Unfortunately, the reward for reporting this critical issue was $0. While it’s fun to find significant vulnerabilities like these, I will probably start shifting my efforts to companies offering monetary rewards help to sustain these often-lengthy investigations and writeups. PS: If you/your company’s security team are currently hiring, feel free to say hello🙂.