RHSB-2021-002 Privilege escalation via command line argument parsing - sudo - (CVE-2021-3156)

Public Date: January 26, 2021, 6:00 pm
Updated -
Resolved Status
Important Impact

Insights vulnerability analysis

View exposed systems



Red Hat is aware of a flaw in the way sudo handles command line arguments. A local attacker could cause memory corruption, leading to a crash or privilege escalation. The sudo package is installed by default on Red Hat Enterprise Linux (RHEL) and allows users to execute commands as other users, most commonly root. The issue is assigned CVE-2021-3156 and Red Hat Product Security has classified this flaw as having a severity rating of Important. Affected customers are urged to upgrade to newer versions of sudo. 

The following Red Hat product versions and containers are either directly affected or potentially impacted:

  • Red Hat Enterprise Linux 6

  • Red Hat Enterprise Linux 7

  • Red Hat Enterprise Linux 8

  • Red Hat OpenShift Container Platform 4 [1]

  • Red Hat Virtualization (RHV) 4.3 and 4.4 [1]

  • Red Hat OpenShift Container Storage 4

    • ocs4/rook-ceph-rhel8-operator [2]

    • ocs4/cephcsi-rhel8 [2]

[1] These products contain content from RHEL and will release advisories with updated content soon after RHEL.

[2] Container security relies upon the integrity and updates of the base image, and will be updated to include base image updates. The Container Health Index, part of the Red Hat Container Catalog, can always be used to verify the security status of the following Red Hat containers.

To determine if your system is currently vulnerable to these flaws, see the Diagnose section below.

A heap-based buffer overflow was found in the way sudo parses command line arguments. This flaw is exploitable by any local user who can execute the sudo command (by default, any local user can execute sudo) without authentication. Successful exploitation of this flaw could lead to privilege escalation.

Red Hat Product Security strongly recommends customers to update to fixed sudo packages once they are available. For customers who cannot update immediately, the following interim partial mitigation using systemtap is suggested:


1. Install required systemtap packages and dependencies, example: 

# yum install systemtap yum-utils kernel-devel-"$(uname -r)"

RHEL 7 may require the installation of the kernel debuginfo, using:

# debuginfo-install -y kernel-"$(uname -r)" 

For RHEL 8 & 6[1] install sudo debuginfo, using:

# debuginfo-install sudo

2. Create the following systemtap script: (call the file as sudoedit-block.stap)

probe process("/usr/bin/sudo").function("main")  {
        command = cmdline_args(0,0,"");
        if (isinstr(command, "edit")) {
                raise(9);
        }
}

3. Install the script using the following command: (using root)

# nohup stap -g sudoedit-block.stap &

(This should output the PID number of the systemtap script)

This script will cause the vulnerable sudoedit command functionality within sudo to stop working. The sudo command will still work as usual (including the editing functionality provided by sudo -e).

Attempting to run the sudoedit command will fail if this system tap script is running. The above change does not persist across reboots and must be applied after each reboot.

Please consult How to make a systemtap kernel module load persistently across reboots? to learn how to turn this into a service managed by initd.


4. Once the new fixed packages are installed, the systemtap script can be removed by killing the systemtap process.  For example, by using:

# kill -s SIGTERM 7590 (where 7590 is the PID of the systemtap process)

Warning: Do not attempt to disable sudoedit by removing the symlink as this is not a sufficient partial mitigation option.

[1] More detailed instructions can be found on installing debuginfo packages in the article linked. 

Red Hat customers running affected versions of these Red Hat products are strongly recommended to update as soon as errata are available.

Product

Component(s)

Advisory/Update

Red Hat Enterprise Linux 8 

sudo

RHSA-2021:0218

Red Hat Enterprise Linux 8.2.0 Extended Update Support [2]

sudo 

RHSA-2021:0219

Red Hat Enterprise Linux 8.1.0 Extended Update Support [2]

sudo

RHSA-2021:0220

Red Hat Enterprise Linux 7

sudo

RHSA-2021:0221

Red Hat Enterprise Linux 7.7 Extended Update Support [2]

sudo

RHSA-2021:0222

Red Hat Enterprise Linux 7.6 Extended Update Support [2]

sudo

RHSA-2021:0223

Red Hat Enterprise Linux 7.4 Update Services for SAP Solutions, Advanced Update Support [3],[4]

sudo

RHSA-2021:0224

Red Hat Enterprise Linux 7.3 Advanced Update Support [4]

sudo

RHSA-2021:0225

Red Hat Enterprise Linux 7.2 Advanced Update Support [4]

sudo

RHSA-2021:0226

Red Hat Enterprise Linux 6 Extended Lifecycle Support [5]

sudo

RHSA-2021:0227

Red Hat OpenShift Container Platform 3.11 [6]sudoRHSA-2021:0221
Red Hat OpenShift Container Storage 4ocs4/cephcsi-rhel8
ocs4/rook-ceph-rhel8-operator
Pending [1]
Red Hat OpenShift Container Platform 4.6 [7]Red Hat CoreOS

RHBA-2021:0235

Red Hat OpenShift Container Platform 4.5 [7]Red Hat CoreOS​​​​​​​RHBA-2021:0231
Red Hat OpenShift Container Platform 4.4 [7]Red Hat CoreOSRHSA-2021:0281
Red Hat Virtualization 4.3Red Hat virtualization hostPending [1]
Red Hat Virtualization 4.4Red Hat virtualization hostPending [1]


[1] Advisory/Update link will be added once updates are live.

[2] What is the Red Hat Enterprise Linux Extended Update Support (EUS) Subscription?

[3] What is Advanced mission critical Update Support (AUS)?

[4] What is the Red Hat Enterprise Linux SAP Solutions subscription?

[5] An active Extended Life-cycle Support (ELS) subscription is required for access to this patch.  Please contact Red Hat sales or your specific sales representative for more information if your account does not have an active ELS subscription.

[6] Manually updating the sudo package from the Red Hat Enterprise Linux 7 advisory is required

[7] Affected Red Hat CoreOS components consume RHEL content, and will be rebuilt and released as an advisory for Red Hat OpenShift Container Platform

NOTE: This flaw does not affect the versions of sudo shipped with Red Hat Enterprise Linux 5, because the vulnerable code was not present in these versions.

Red Hat OpenShift Dedicated clusters are affected as the vulnerable sudo version is present in the systems. However, the impact is very low as the access to the sudo command is already restricted to users with cluster-admin privileges on dedicated clusters.

A vulnerability detection script has been developed to determine if your system is currently vulnerable to this flaw. To verify the authenticity of the script, you can download the detached OpenPGP signature as well. Instructions on how to use GPG signatures for verification are available on the Customer Portal.

Current version: 1.1

Additionally, an Ansible playbook is available which automates the mitigation described above. This playbook will install the packages necessary to use systemtap, and will then create and install a systemtap script to prevent the use of the sudoedit command. This mitigation will need to be re-applied after a reboot, which can be achieved by re-running the playbook.

To use the playbook, define the extra variable HOSTS with the Ansible inventory name of the hosts to which the mitigation will be applied. For example,

ansible-playbook -e HOSTS=web,ns1,mail CVE-2021-3156_stap_mitigate.yml

To verify the authenticity of the playbook, you can download the detached OpenPGP signature. See the Customer Portal for instructions on using GPG signatures for verification.

Current version: 1.0

Red Hat thanks Qualys Security for reporting this flaw.

How to use GPG to verify signed content from Product Security 

31 Comments

Subscriber exclusive content

A Red Hat subscription provides unlimited access to our knowledgebase, tools, and much more.

Current Customers and Partners

Log in for full access

Log In

In step 1. please add yum/dnf to the instructions to make it clear?

I've changed formatting over the mitigation area to make the commands clearer, plus explicitly adding yum in front of the packages listed.

On RHEL 8.3 when I run 'nohup stap -g sudoedit-block.stap &' and look in nohup.out I see: WARNING: cannot find module /usr/bin/sudo debuginfo: No DWARF information found [man warning::debuginfo] Missing separate debuginfos, use: debuginfo-install sudo-1.8.29-6.el8.x86_64

Guessing this isn't expected? Also when I run the debuginfo-install tells me: Could not find debuginfo package for the following installed packages: sudo-1.8.29-6.el8.x86_64 Could not find debugsource package for the following installed packages: sudo-1.8.29-6.el8.x86_64 Dependencies resolved. Nothing to do.

Our instructions did list to install the sudo debuginfo package, I've improved the formatting to make it easier to see. The warning itself doesn't affect the effectiveness of the mitigation. In our testing the mitigation still works and this warning can be ignored.

When implementing the workaround on RHEL6.7 when I run the "nohup stap ..." command I get:

nohup: ignoring input and appending output to `nohup.out'

The following is written to nohup.out:

semantic error: while resolving probe point: identifier 'process' at /usr/local/sbin/sudoedit-block.stap:1:7 source: probe process("/usr/bin/sudo").function("main") { ^ semantic error: no match (similar functions: umask, _fini, exit, open, textdomain) Pass 2: analysis failed. [man error::pass2]

Really need to implement this workaround ASAP since RHEL6 is EOS.

I think you need to re-apply on every reboot of a RHEL 6 :(

The mitigation was only tested and provided for Red Hat Enterprise Linux 7 and 8.

Try installing the sudo-debuginfo, that resolved the semantic error for me. There's also a change needed to the stap script, replacing the line with strpos() with:

if (isinstr(command, "edit")) {

Note that update was released for Red Hat Enterprise Linux 6 Extended Lifecycle Support, the the errata list above.

I can confirm that with this change and after debuginfo-install sudo the systemtap script can be installed on RHEL6.

The strpos error also appears with RHEL 7.4, not only with 6.x

The main article has been updated with small change from line: if (strpos(command, "edit") >= 0) { to: if (isinstr(command, "edit")) { And we now list the requirement to install the sudo debuginfo package for RHEL 6. From testing this works on RHEL 6, 7, & 8.

Still working on migrations of a few legacy apps on RHEL 6 (still worrying) over to newer RHEL versions (all patched). The mitigation steps provided (even after installing sudo-debuginfo) still leads to the following error message on Rhel 6:

" semantic error: unresolved function (similar: strtol, strlen, error, log, pid): identifier 'strpos' at /root/sudoedit-block.stap:5:13 source: if (strpos(command, "edit") >= 0) { ^

Pass 2: analysis failed. [man error::pass2] "

If instead sysytemtap is installed from source to version 4.4 (with the other required packages remaining); a slightly different error message occurs:

" semantic error: unresolved function (similar: strtol, strlen, error, log, pid): identifier 'strpos' at sudoedit-block.stap:6:13 source: if (strpos(command, "edit") >= 0) { ^

Pass 2: analysis failed. [man error::pass2] "

Red Hat should be generous to customers with no ELS to just give us the sudo patched package as there are RHEL6 in prod with legacy apps... Just to secure the sudo severity until we migrate to RHEL7/8...

available from upstream sudo.ws: https://github.com/sudo-project/sudo/releases/tag/SUDO_1_9_5p2

The main article has been updated with small change from line: if (strpos(command, "edit") >= 0) { to: if (isinstr(command, "edit")) { And we now list the requirement to install the sudo debuginfo package for RHEL 6. From testing this works on RHEL 6, 7, & 8.

How can you check if a particular systemtap script is already installed? I'm trying to implement an ansible playbook to install the mitigation. In order to make it idempotent a check is needed to avoid installing the same script over and over again.

It loads a kernel module that you can check for with lsmod. As it generates a random name if executed as suggested above, so for your usecase, you probably want to give it some static name using the -m option, such as -m stap_sudoedit_block.

Or just run sudoedit and check for the Killed / 137 exit status.

Thanks, reusing the sudoedit check works.

With help from Tomas Hoger I created the following ansible playbook.

A check run fails because the sudo_result isn't registered during a check but it does install the mitigation script on RHEL6 systems.

Hope this helps someone

---
- hosts: all
  vars:
    sudoedit_block_stap_script: |
      probe process("/usr/bin/sudo").function("main")  {
              command = cmdline_args(0,0,"");
              if (isinstr(command, "edit")) {
                      raise(9);
              }
      }
  tasks:
  - name: Install required systemtap packages and dependencies and sudo debuginfo packages
    yum:
      name:
        - systemtap
        - yum-utils
        - "kernel-devel-{{ ansible_kernel }}"
        - audit-debuginfo
        - glibc-debuginfo
        - libselinux-debuginfo
        - openldap-debuginfo
        - pam-debuginfo
        - sudo-debuginfo
        - yum-plugin-auto-update-debug-info
        - zlib-debuginfo
      enablerepo:
        - rhel-6-server-debug-rpms
        - rhel-6-server-optional-rpms
      state: latest
    when: ( ansible_os_family == "RedHat" and ansible_facts['distribution_major_version'] == "6")

  - name: Deploy systemtap script
    copy:
      dest: /root/sudoedit-block.stap
      content: "{{ sudoedit_block_stap_script }}"
      owner: root
      group: root
      mode: '0640'
    when: ( ansible_os_family == "RedHat" and ansible_facts['distribution_major_version'] == "6")

  - name: check sudo CVE
    command: sudoedit -s /
    register: sudo_result
    changed_when: False
    ignore_errors: true
    when: ( ansible_os_family == "RedHat" and ansible_facts['distribution_major_version'] == "6")

  - name: install the systemtap script
    shell: cd /root; nohup stap -g sudoedit-block.stap -m stap_sudoedit_block </dev/null >/dev/null 2>&1 &
    when: (( ansible_os_family == "RedHat" and ansible_facts['distribution_major_version'] == "6") and (sudo_result.rc != -9) and ("usage:" not in sudo_result.stderr)) and not ansible_check_mode
    async: 10
    poll: 0

I would suggest to make the systemtap script a automatically started service and install an appropriate unit file through ansible. This will free you from having to rerun the playbook after each host reboot.

Here is our current setup:

/root/sbin/sudoedit-block.sh

#!/bin/bash

HERE=`dirname $0`
PIDFILE="${HERE}/sudoedit-block.pid"

(
  cd $HERE  # cd to the script location to ensure proper location of nohup.out
  nohup stap -g sudoedit-block.stap &
  echo $! > $PIDFILE
)

/etc/systemd/system/sudoedit-block.service

[Unit]
Description=Temporary mitigation of CVE-2021-3156 (sudoedit privilege escalation bug)
Wants=basic.target

[Service]
Type=simple
ExecStart=/root/sbin/sudoedit-block.sh
PIDFile=/root/sbin/sudoedit-block.pid

[Install]
WantedBy=basic.target

The debuginfo packages (debuginfo-install -y kernel-"$(uname -r)") don't seem to be required. The mitigation seems to work fine w/o them.

When will a fixed version of sudo be available for RHEL 7.5?

There is no active support stream for Red Hat Enterprise Linux 7.5, so there will be no update specifically for the 7.5 version.

Will the RHEL 7.8 specific repository be updated with the new Sudo Package?

Similar to the above question for 7.5 - there's no active support stream for Red Hat Enterprise Linux 7.8 either, hence no update for any 7.8 repo.

I was receiving the same semantic errors for my RHEL 6.10 Server. I was also unable to perform #debuginfo-install sudo. HOWEVER; it gave me the clues. I downloaded the packages and installed them in this order: openldap-debuginfo-"$(uname -r)" sudo-debuginfo-"$(uname -r)" zlib-debuginfo-"$(uname -r)" audit-debuginfo-"$(uname -r)" After that, the script ran like a champ. Added line to the bottom of /etc/rc.local nohup /uar/bin/stap -g /root/sudoedit-block.stap & Checked to see if process was running. ps aux | grep sudo Ta da! I had some help from the Red Hat Support Case I opened up also. But; HTH with the packages required to run the .stap for RHEL 6 folks who can't run debuginfo-install sudo.

When will a fixed version of sudo be available for RHEL 7.9?

When will a fixed version of sudo be available for RHEL 7.9?

Relevant erratum is https://access.redhat.com/errata/RHSA-2021:0221

It's been available as of Jan26.