Another "TicketTrick" story
Few months ago, researcher Inti De Ceukelaire disclosed a well written research blog on a vulnerability type that he named TicketTrick. With this trick, he was able to use support emails to get variety of different emails from other companies. For example, he could create Slack accounts, Yammer accounts and many more. Since then, there has been an increase in reports about this type of bug. At the same time, new variants of this issue has also come up such as this one that I am going to detail on my blog.
To start with...
One of the most common thing that I do every week is to do manual reconnaissance on Uber. This helps me learn about the app and even if I do not find any bugs, it helps me learn new things or get to know about new features. During this process, I look into any new changes that Uber has made or if they launched a new feature. For companies like Uber, it is common to release features almost every week. While some might be small feature or code changes, sometimes there are also new addition to the app and the company in itself. One of the app that I really wanted to look into was Uber for Business.
Uber for Business is extremely helpful for companies to organize rides for events, personnels that are coming to offices etc. This application is also heavily monitored by the Uber's MIR team based on what I saw when I was looking into it. For example, once they detected that I was trying to get info of other accounts by testing IDOR and other attacks my account was banned right away. With these informations in mind, I decided to test Uber for Business again to see if there was anything new or interesting that I had not tested before.
When testing, my account stopped working and I count not sign in anymore. To figure what was going on, I decided to contact the support team through their live chat feature. Uber business has their own support team for business users instead of the regular support team so the email and live chat were also different. During the chat, Uber told me that they suspended my account for security reasons (😲 that is some solid monitoring). They asked to me to send some HR documents to prove that I worked for the company I signed up with. After the chat ended, I received an email asking me to send the file over the email. I noticed something really interesting during the process. There was not only a case ID but also a reference ID on the email:
Initiating the test..
When I started to see how the reference id worked, I was not sure what service they were using. My original thought was Zendesk because Uber uses that for their regular support (at least they used to, I cannot confirm if they still do it). In order to understand the reference id and how it worked, I decided to send an email to their business support one more time but this time with a different email. After sending the request, I got an automated reply and it also included a reference id. Next, I started to compare the ref id to see how it worked.
ref:_00Do0aYry._5001JasMIX:ref vs ref:_00Do0aYry._5001Jas9FN:ref
In the reference id listed above, you can see that most part of the ticket is exactly same except the last digit (MIX vs 9FN).
After noticing that the reference ids are technically not that different (more detailed info on reference id is below) I decided to try an attack by changing the reference id and sending a new email from another email id with a ref id that already exists (
ref:_00Do0aYry._5001JasMIX:ref). Soon after this, I got an email from Business Support with the subject id of the report referenced when I start attacking it.
As soon as this worked, I decided to file a vulnerability report to Uber through their bug bounty program. After some investigation, Uber decided that the ref id might be hard to brute so they decided to close it as Informative. Even though I agreed with them, this was a really interesting behavior so I decided to spend some time to see how this system worked. During this, I found out they are using Salesforce for support. I found this was by checking the live chat logs for my previous support request where the url of the support was linked to Salesforce's live agent feature. When I started reading Salesforce docs and started to compare the features, I found out that the Uber was using Salesforce Service Cloud to generate cases for their support agent.
After finding out about Salesforce Service Cloud, I went ahead and signed up for the trial version to understand how the app worked. Once I got hang of the feature where it would generate a case based on the email sent, I started to read Salesforce documents to understand how the case concatenation worked when I sent an email with an already existent references ID. During this process, I found multiple help forum articles about the feature and how it worked. It also explained how the reference ID was generated which helped me understand why last 3 digit were different.
How is the reference id generated:
- First part of the ref id is the organization id in salesforce and it never changes. In Uber's case this is 00Do0aYry.
- Next, the 5001 stays pretty frequent throughout the case because it is the first 4 digit of the case ID. It is unlikely that it will change for every case so an attacker does not have to worry about this either.
- Next, throughout multiple tests that I did,
Jasstayed the same because that is part of the last 6 digit of the case id.
- The only part that changed is the last three digit of the reference id.
How to distinguish a valid ref id with a not valid one
Salesforce checks for reference id in two email places: Subject and Body. If either of them has the reference id, it will successfully concatenate the support requests. In Uber case, it is even easier because Uber has auto reply setup so if you send an email with the reference id and you do not get the auto reply back that says a new ticket was generated then your email would have successfully concatenated with a ticket.
Along with that, based on what I saw when testing you could easily go through all iterations of three digit alphanumeric string and all of them would work. This is because based on what I found
Jas will change to another string after the three alpha numeric string after it runs out. So it will only change after around 46656 tickets have been filed.
Once I realized that it was not that hard to exploit this, I went ahead and wrote the above explanation to Uber to let them know it is not hard to exploit. Soon after that, Uber changed the state to Triaged and started investigating it.
Chaining and exploiting this further...
As previously stated, in this case the email will concatenate if any part of the email body had the reference id. Quite a while ago, TicketTrick blog by Inti came out where he discussed using corporate emails from support platforms to access internal resources. During this, I realized that I could do the same attack and signup on any page specially on sites where Uber might have a corporate account. Sadly, I could not do this in Slack because Uber does not allow signup on their corporate Slack and only the workspace owners can add users. One place, I was able to attack is Google itself where you can signup for an account with custom domain. Even though this does not give much access to internal files because the account won't be under the same GSuite, it would allow you to request file access and because the request is done through a @uber.com email it would be easy to phish users and gain access to internal Uber documents.
As I stated previously, Uber originally closed the bug as Informative and decided it was not something they did not want to fix. While I understood their decision, I was not convinced that this was not hard to exploit. In this case, I decided that it was better for me if I actually had experience with Salesforce app before I go back to Uber and tell them they were wrong. Two key things that I learned just from the experience of a report going from informative -> triaged are:
- If you believe that a report should be considered valid, do not go right back at the company saying they are wrong. Try to explain them clearly why the report should be considered valid and why they should change their decision in the report. Many researchers/hunters believe that companies do not listen to their comments or feedbacks but that is never true. For this specific case, I went back and researched about Salesforce and its feature completely, then I went back to Uber and explained them how this could be exploited.
- Always be patience: after I provided the info that was necessary, Uber replied back saying they will look into it internally and let me know. This was a complex bug so I knew this was going to take them some time. I made sure I did not keep asking them about updates and instead waited about 2 weeks at the least before I asked if they had made a decision. This not only helped me, it also helped Uber because this gave them enough time to discuss the bug internally, understand its impact and triage it based on the severity they saw was accurate.
One thing that I have learned when dealing with cases where there are multiple vendors/companies involved in the report is to not rush things. Even after Uber triaged the bug, they could take one of two routes: 1) Add a fix from their own side that would be way more complex than the bug was or 2) Talk with Salesforce and work in a resolution that Salesforce could make from their side. Uber decided that step number 2 would be the best because this will not only help Uber, it will also help any company that was using Salesforce's service. Once I knew that Salesforce and Uber were working on a fix together, I decided to give them enough time to work on a fix instead of asking them constantly for updates. As researchers, what we have to understand that while it might be easy for us to submit a bug and ask for updates, companies will need time to work internally and make sure the patch actually fixes the bug and does not introduce new bugs.