Hacking into the worldwide Jacuzzi SmartTub network
Discussion links: X | Reddit (gadgets, netsec)
News coverage:
- New York Post
- Gizmodo (best headline award๐)
- Motherboard – VICE
- TechCrunch (Front page screenshot – June 22, 2022)
- PortSwigger
June 22, 2022 update: Clarified that SmartTub shut down the smarttub.io admin panel themselves, and not Auth0.
July 25, 2022 update: Read the response Jacuzzi Group sent to their retail partners a month ago.
Background
Jacuzzi Brands is a widely recognized hot tub and spa manufacturer. There are several brands under their umbrella:
When you go to buy a hot tub, Jacuzzi is likely what comes to mind first, and you’d probably go check out offerings from Jacuzzi Hot Tubs. They make the best ones and have been in business a long time.
I ordered a hot tub from a local dealer in June 2021. Delivery took place in December 2021. As part of the order, I optioned the SmartTub feature.
What is SmartTub?
SmartTub consists of two elements: a module inside the tub itself with cell data reception that can access/control tub functionality, and an Android/iPhone app. The tub module is always connected to a central server, providing tub status updates and listening for commands. Command examples: turning on lights, jets, setting water temperate, and more. The module is OEM and can be installed as a factory option, or retrofitted at any time after delivery.
You could consider SmartTub an IoT/smart device. Aside from the Android/iPhone app, it also integrates with Alexa, Google Assistant, Wear OS, and Apple Watch.
SmartTub is available for multiple brands. Below is a screenshot from the app:
More about SmartTub on the Jacuzzi website
Setting up SmartTub
On delivery day I was eager to set up SmartTub. After waiting a little while for the dealer to do the pairing/activation, I created my account using the app and started messing around with it. I went to add the account password to my password manager and checked what website/URL should be associated with it. The account confirmation email came from smarttub.io, so that is what I used.
A flash of data
After setting the password in my password manager, I went to the smarttub.io site to see what was there. There was an Auth0-branded login page. SmartTub uses Auth0 for their login and user account system. If you don’t want to build your own login and user account system, Auth0 is a good choice and saves you a lot of time by providing a full & secure user account system out of the box. Anything you build from scratch is unlikely to be as secure as Auth0’s offerings.
I entered my details, thinking this was a website alternative to the mobile app. I was greeted with an Unauthorized screen:
Right before that message appeared, I saw a header and table briefly flash on my screen. Blink and you’d miss it. I had to use a screen recorder to capture it. I was surprised to discover it was an admin panel populated with user data:
Glancing at the data, there is information for multiple brands, and not just from the US. There are a few @jacuzzi.eu emails and a @hotmail.co.uk one, so it seems data from overseas is here too.
The unauthorized redirect makes further investigation impossible, so let’s try to bypass it!
Breaking in
smarttub.io hosted a single-page-application (SPA) built using React. Admin panels are commonly built as an SPA, so seeing it used here is unsurprising. I downloaded the JavaScript bundle and searched for instances of “unauthorized”. I found where it sets the URL to the error path, and also where it seemingly creates the unauthorized div:
If you look closely in the second image, it checks if the user is admin. If they aren’t, they get redirected to the unauthorized page. This is the isAdmin check:
The login works by sending the username and password to Auth0. On success, access and ID tokens are returned. The access token is then sent to Auth0’s /userinfo endpoint and this information is returned:
This information contains a list of roles, and isAdmin is checking whether Admin is there. In my case, it is not. If the HTTP response could be intercepted to add in the missing Admin role, it’s possible the unauthorized page would no longer show. I used Fiddler to modify the HTTP response accordingly, and I was finally able to access the admin panel in full.
Unrestricted Access
Once into the admin panel, the amount of data I was allowed to was staggering. I could view the details of every spa, see its owner and even remove their ownership:
I could view every user account, and even edit them:
Please note that no operations were attempted that would actually change any data. Therefore, it’s unknown if any changes would actually save. I assumed they would, so I navigated carefully.
A second admin panel
The first admin panel revealed user and spa information. That is pretty bad, but things get worse through the discovery of a second admin panel.
This second admin panel was discovered while reviewing the Android app APK. There is link to an admin console in a configuration function:
This login screen is not Auth0 branded, so I didn’t expect my credentials to work. I tried them anyway – they seemed to work, but I got a message saying I do not have permission:
This is a standard browser alert, coming from JavaScript code. Could the same bypass trick on the first admin panel be used here?
Breaking in – Again
I downloaded the JavaScript bundle. It’s completely different than the first admin panel, but still uses React. I found the code that shows the browser alert, and the isAdmin check.
There appears to be other groups besides admin and user. There is one for a “tools admin” and one for the development team. To get user information, the access token JWT is decoded client-side, instead of using it to call /userinfo. And, the groups section of the user information is being checked this time, instead of roles.
To attempt to bypass this, I used Chrome Local Overrides to load a modified JavaScript bundle file. The modifications I made were to simply change canUseTools, checkAdmin, and checkDevTeam to return true in all cases. This way, I didn’t need to intercept the HTTP response each time to modify the groups.
Logging in using the modifications worked and I could see the panel, populated with user data yet again:
It’s worth noting that being a member of the tools admin and development team groups unlocks additional menu options that are apparently off-limits to “normal” admins (under the More menu):
The spa and user access is mostly the same as the previous panel. There’s a few new options though, particularly an option to extend your cell data subscription (or shorten someone else’s…):
As for other internal sections, including sections that normal admins can’t even access, here is a list of what I observed could be done. Out of respect for Jacuzzi/SmartTub, screenshots of these private/secret/internal areas will not be shown.
- Promotions section – create promo codes for the in-app shopping feature. You can buy accessories, chemicals, and renew your cell data subscription.
- Products section – create, modify, and delete tub colors, cabinet colors, equipment options, revisions, and models. This is basically the database of options for hot tubs.
- Dealers section – create, modify, and delete licensed hot tub dealers.
- Registered phones – unclear what this does exactly. Seems to be some kind of notification system for customer phones. Email addresses are visible, but no phone numbers.
- Serial Number Update section – unclear what this does exactly. Seems like a serial number replacement feature, with options to “fix” certain things.
- Manufacturing Logs section – a list of serial numbers and IDs for some type of device. Maybe the SmartTub modules as they roll of the assembly line. Each entry has a “Mark Done” button.
Production Data
It’s worth noting that both admin panels are accessing the same data source/database, and are accessing production data. I confirmed this by looking up my own account.
User Data and California Laws
Worldwide user data was exposed, which included first name, last name, and email address. There is a phone number field, but thankfully I never saw it filled in anywhere, and you aren’t asked for it when creating an account.
It would be trivial to create a script to download all user information. It’s possible it’s already be done. Jacuzzi is incorporated in California which has data breach notification laws. I’m uncertain whether the exposed data meets the bar for the law’s requirements, and it may not be technically possible to identify California residents in the SmartTub network. Jacuzzi did not respond when I brought up the California laws.
Disclosure Timeline
All times in EST.
- Dec 3, 2021, 2:17 PM: Email sent to address listed on SmartTub’s Google Play page (jacuzzi.app@jacuzzi.com). The email was short and I wrote that I had found security issues with SmartTub, and to please connect me with a security contact. I discovered the security issues just a few hours prior to sending this email. No response was ever received from this address.
- Dec 6, 2021, 4:31 PM: Same email sent to a different address shown in the in-app help section: support@smarttub.net.
- Dec 6, 2021, 10:12 PM: Response from SmartTub support (support@smarttub.net) asking for more details.
- Dec 6, 2021, 11:45 PM: Comprehensive email reply sent with screenshots and explanations. Advice on suggested fixes also given.
- Dec 16, 2021, 2:30 PM: Email reply sent asking if last email was received.
- Jan 3, 2022, 2:14 PM: DM sent to @JacuzziOfficial on Twitter, asking if they are able to provide an update on the email ticket/reference ID, or if they can provide a different way to contact SmartTub.
- Jan 4, 2022, 1:22 PM: @JacuzziOfficial confirms the only way to reach someone at SmartTub is via the support email I have been using. They were of no further help.
- Jan 4, 2022, 1:25 PM: Happy-new-year email reply sent, asked for an update.
- Jan 4, 2022, 1:40 PM: After about 1 month of no communication, I came up with an alternative. I contacted Auth0’s security team, asking if they would be willing to help their customer.
- Jan 4, 2022, 5:44 PM: Auth0 security rep asks me to use their submission form to securely provide more details.
- Jan 4, 2022, 7:27 PM: Auth0 form submitted. This opens a submission on Auth0’s Bugcrowd.
- Jan 4, 2022, 8:28 PM: Auth0 security rep reproduces the issue, starts “internal process of reaching out to the customer”.
- Jan 4, 2022, 8:29 PM – Mar 7, 2022, 5:23 PM: For brevity, this is a summary of activity on the Bugcrowd submission: Auth0 also had trouble reaching SmartTub, but eventually got in touch and SmartTub said they would look into the issues. SmartTub told Auth0 they would shut down the smarttub.io admin panel to “prevent any issues moving forward”. I told Auth0 the second admin panel was still vulnerable. Auth0 was not able to get any further responses from SmartTub, and, understandably, they said they were unable to help further and I should try contacting SmartTub again. This entire time period, I never got any response from SmartTub.
- Mar 15, 2022, 5:42 PM: I send a new email to support@smarttub.net, jacuzzi.app@jacuzzi.com, and a new one I found on Google Play listed under their Wear OS app: jacuzzi.engineering@gmail.com.
- Mar 15, 2022, 5:50 PM: I was delighted to finally receive a response from someone letting me know they’ve escalated the issue to management, and to expect communication soon. The reply came from support@smarttub.net.
- Mar 24, 2022, 2:33 PM: After no communication, I reply letting them know I had heard nothing.
- Mar 31, 2022, 2:04 PM: I sent another reply asking if they are receiving my emails.
- Apr 12, 2022, 3:17 PM: I begin to wonder if the communication breakdown could be caused by their CMS/support system not processing email replies correctly. To date, I have never received a reply to a reply. I send a new email asking for an update.
- Apr 21, 2022, 10:00 AM: It seems my theory may have been incorrect. My new email was not responded to. I decide to email the Auth0 security rep asking if they could email SmartTub, and copy me on the message.
- May 2, 2022, 7:46 AM: I decide to send one last new email to support@smarttub.net, asking for an update. They never responded.
- May 5, 2022, 2:13 AM: Auth0 security rep confirmed Auth0 is unable to help further.
- Jun 4, 2022: I notice the second admin panel has finally been secured.
- Jun 20, 2022: Report published.
Summary: After multiple contact attempts through 3 different Jacuzzi/SmartTub email addresses and Twitter, a dialog was not established until Auth0 stepped in. Even then, communication with Jacuzzi/SmartTub eventually dropped off completely, without any formal conclusion or acknowledgement they have addressed all reported issues.
I would like to thank the Auth0 security team. Auth0 didn’t have to help since this was not their problem, but they did, and without their assistance, this disclosure would probably have remained stalled. I was happy to see they are willing to help their customers.
In the end, the second admin panel was secured. I wasn’t notified and decided to check it randomly one day because I wanted to start preparing this report. This is how it looks when I checked on June 4th, 2022 – after logging in, you get this message from the server and there is no way around it:
Dear Jacuzzi: I would like to discuss a few other security concerns not mentioned in this report. Please contact me – I want to help!