Multiple vulnerabilities were discovered in the Unitrends Backup appliance and client software. An attacker with network access to the management interface or backup ports on the client or server could be exploited to compromise the machine. Both suffer from critical remote code execution vulnerabilities.
This is the second installment of the Exploiting Unitrends series and will focus on several critical unauthenticated SQL Injection vulnerabilities leading to remote code execution. Part 1 is available at Exploiting Kaseya Unitrends Backup Appliance – Part 1.
The following vulnerabilities will be discussed in this blog and will outline an attack chain showing how an unauthenticated remote attacker can take full control of the target database and system.
Because the Unitrends Backup appliance server holds a privileged position in the network, a compromise could potentially extend to all computers configured as a backup client. Also, the Unitrends backup client software for Windows and Linux contains a critical unpatched vulnerability which allows for unauthenticated remote code execution as root/SYSTEM. It is strongly recommended to not expose the client ports directly to the Internet and internally. Follow the vendors guidance at https://support.unitrends.com/hc/en-us/articles/360013264518.
CyberOne’s offensive security team TeamARES can perform a penetration test of your company’s Unitrends backup infrastructure and internal environment to assess your organizations current security posture. For information, please contact at https://www.cyberonesecurity.com/contact-us .
CVE-2021-43035 Unauthenticated SQL Injection – config.php
An unauthenticated blind SQL Injection vulnerability was discovered in the /grid/config/config.php script, where arbitrary SQL statements can be injected into the host parameter. These statements are executed under the postgres superuser account. Remote code execution is possible for gaining shell access to the Linux system as the postgres account.
With the focus on unauthenticated vulnerabilities, I looked at any files that could be accessed without having to provide a password or valid session. Most requests resulted in an authentication error like below.
However, several PHP scripts were found under the grid/config directory which failed with a different error and further research was needed to find the request format.
It was found that config.php is really just a wrapper script that passes $_REQUEST to the process_config() function.
The process_config() function is located in a compiled shared object file located at /usr/lib64/php/modules/bpl.so. process_config() then calls get_symbol() to load the real function dynamically from /usr/lib64/libbpext.so. The get_symbol() function which is a wrapper around dlopen().
The id and host HTTP parameters were discovered.
Tracing the path in libbpext.so we eventually arrive at a SQL statement. There are two injection points into the query. The _pgVExec() function calls sprintf to insert the id and host paramters into the query statement.
I primarily used dynamic testing to find this vulnerability and then complimented that with static analysis to understand the issue better. Using dynamic and static analysis together while hunting for vulnerabilities can greatly speed up the process.
On the dynamic side I enabled statement logging in PostgreSQL which showed the following error when sending a single quote in the HTTP request. The error is not reflected in the request which would make it much more difficult to find without turning on the verbose logging.
The error was trimmed for brevity. Notice the single quote injected into the query.
The syntax error is a great sign that the input parameters were interpreted and there could be a potential for SQL injection. After running various tests I successfully proved the SQL Injection vulnerability by calling the pg_sleep() PostgreSQL function call. This is a simple way to confirm a blind SQL injection. The inline /*woot*/ comment was needed because whitespace would cause the value to be truncated.
The result was a seven second delay caused by the pg_sleep(7) call.
It was determined the application uses the postgres superuser account for database access. It is generally recommended to follow the least privielge model for database access. This made it very easy to achieve remote code execution creating a malicious user defined function (UDF).
Steps to reproduce:
Start a netcat listener.
Place the following string in a file named payload. Update LHOST and LPORT with the netcat listener.
An annotated version of the payload is included below.
Send a POST request using curl specifying the payload created in step 2 to receive a reverse shell running as postgres.
CVE-2021-43040 Unauthenticated SQL Injection – vaultServer
An unauthenticated blind SQL Injection vulnerability was discovered in the /cgi-bin/vaultServer HTTP endpoint. Arbitrary SQL statements can be injected into the name parameter when calling replication-state function. These statements are executed under the postgres superuser account. Remote code execution is possible using the same payload as shown in the previous SQL Injection vulnerability.
Steps to reproduce:
Executing the following curl command will result in a 14 second delay caused by the pg_sleep(7) PostgreSQL function call. The sleep time is doubled because the pg_sleep() call is executed in two different queries.
PoC showing the 14-second delay.
When beginning the research, I could not have anticipated the various issues uncovered. The discovery of unauthenticated SQL Injection vulnerabilities ultimately led to the full compromise of the server. These vulnerabilities could be chained with several local privilege escalation vulnerabilities to achieve root access. Visit Exploiting Kaseya Unitrends Backup Appliance – Part 1 for a detailed example showing the local privilege escalation to root
Stay tuned for part three for the details on several unauthenticated remote code execution vulnerabilities in the bpserverd daemon.
05/25/2021 – Email sent to email@example.com requesting a contact.
05/26/2021 – Email sent to firstname.lastname@example.org requesting a contact.
06/02/2021 – Requested contact from @unitrends on Twitter.
06/02/2021 – Created Unitrends Zendesk ticket. Received human reply from 5/25 email.
06/02/2021 – Sent vulnerability report via email.
06/25/2021 – 03/09/2022 Various email exchanges and conference call with vendor.
Discovered by Rich Mirch of CyberOne, TeamARES