An authentication bypass issue was discovered in JitBit Help Desk Software v8.9.11 in October of 2016. This issue was reported to the vendor, and after several communications and numerous updated releases, the software is still vulnerable. JitBit Help Desk Software is a popular ticketing system which boasts some well-known clients.
It is possible to perform an authentication bypass on default installations of JitBit Help Desk Software due to a few issues.
Let’s take a look at a default installation to see what is available. As an unauthenticated user, we are limited to a few things such as reading public knowledgebase articles, submitting new tickets, registering an account, and requesting a password reset.
The authentication issue is due to the way that password resets work. Let’s take a default installation and register a new user to demonstrate the issue.
After registering, we get a “Welcome” email with our plaintext password, and are automatically logged in using our new user.
Now that we have a user set up, let’s log out and request a password reset. The form only requires that we provide an email address of a valid user to send a reset email.
After submitting the form, we will get the below email with a link to login and reset the password.
It is possible to skip the password update by clicking anywhere else on the page to browse around while logged in as our trustedsec user. Let’s take a closer look at the link that was sent and see how this can be used for authentication bypass. Below is the full link:
The link will still work without the ReturnURL parameter and when used without it, will not prompt to change the user’s password. Using the following link will automatically authenticate us as the trustedsec user and skip the change password prompt.
Looking at the parameters, we need to know the username, email, and userHash to log in as a given user. The code for creating these links can be found in the HelpDesk.dll file in a function called “SendAutoLoginLink”.
This function makes a call to “GetAutoLoginUrl” which is responsible for creating the portion of the link that is important.
Here we can see that the “userHash” parameter is calculated as an MD5 hash of several strings of information appended together. The only portion that we do not know how to calculate is the “autoLoginSharedSecret”. Checking the site settings while logged in as the administrator shows that the shared secret was populated during the install. In the demo version, we are not able to update this value.
Tracing back through the code we can find that the shared secret is created and stored in the database during installation by a function called “InitInstanceSettings”.
Inside the “InitInstanceSettings” function, the shared secret is created by calling “CryptoUtils.GenerateRandomCode(20)”.
The code is a 20-digit code consisting of 32 different character combinations. It is not feasible to brute-force the secret value as it would require at most 32^20 operations. Even with a modern computer, this would take many centuries to complete. The issue with the code generation is in the use of the “System.Random” class. By default, the seed value is provided by “Environment.TickCount” on instantiation. The seed value is stored as a 32bit signed integer value which is much more feasible to brute-force, as it only takes 2^32 operations at most.
I’ve created a tool that can be used to brute-force through all possible seed values for the “System.Random” class and use each instance to generate a 20-character secret using the same method. This process takes 3 hours at most to exhaust all 2^32 possible seed values on an Intel Core i7 4790k using 8 threads.
In order to derive the correct secret value, we will need to brute-force the seed values to generate possible shared secrets and then calculate the “userHash” value using the same username, email, and date values used when we requested the password reset. If we compare these results to the hash that we received in the reset link and find a match, we should have recovered the correct seed value, which then leads us to the correct shared secret value. Running the utility, you can see that we were able to recover the secret in just over one minute.
Now that we have the shared secret, we should be able to calculate a “userHash” for the admin account like so:
MD5(‘admin + ‘email@example.com’ + ‘AUVSC6E4X329GFVBWY7F + ‘2509’) =
Before we use this hash though, if you take a look at the “VerifyAutoLogin” function, we can see that the application allows for a sliding time window as well as a hash calculated without the date at all! This is for backwards compatibility since older versions of the software did not create time sensitive reset links.
So, if we wanted, we could just calculate the hash without the date to create a reset link that never expires:
MD5(‘admin + ‘firstname.lastname@example.org’ + ‘AUVSC6E4X329GFVBWY7F) =
Using the new hash, our reset link should look like this:
At this point, we are now logged in as the admin user! We now have full control over the application. Source code for the POC can be found at the following:
Short Term Workaround
For any users of this software that are affected by this issue, a short term workaround would be to provide your own secret value. Do not rely on the generate code button in the settings page to create a new shared secret. Use a secure password generator to create a new secret value and replace the one generated by the helpdesk software. This will prevent malicious users from brute-forcing the seed value used to generate the shared secret.