
beginner friendly write-up for the TryHackMe easy level module- polkit:CVE-2021-3560
we will first check the version of the polkit version to get some better insights.
apt list --installed | grep policykit-1
policykit-1/focal,now 0.105-26ubuntu1 amd64 [installed,upgradable to: 0.105-26ubuntu1.1]
i used deepseek to create a simple analogy for you to understand the concept of a policy kit even better.
Nightclub: Polkit System
Nightclub (VIP Area): The privileged system services/actions (mounting drives, installing software, managing network)
Bouncer at the door: Polkit itself, intercepting all entry attempts
Guest list / Dress code: Polkit policy rules (stored in /usr/share/polkit-1/actions/ and /etc/polkit-1/rules.d/)
VIP Pass / Club Membership: Being in specific Linux groups (like wheel, sudo, storage, network)
ID Check: Polkit checking user identity and group membership
Owner / Manager Root: user (has unrestricted access to everything)
Regular patrons trying to enter VIP area: Normal users/programs trying to execute privileged commands
Bouncer consulting the rulebook: Polkit checking configured policies for that specific action
Bouncer asking for special wristband/password: Authentication prompt (asking for password)
Bouncer waving someone through without checking: Action allowed without authentication (for trusted users/groups)
polkit is the sudo of systemd
now we can exploit this nightclub bouncer by some sneaky rewuests in order to bypass the credetnial check for the dbus rewuests.
lets understand this using the same previous nightclub bouncer analogy.
lets say the normal proccess goes like : the bouncer chekcs for the ids, if the person is privileged enough to do that particulary task then he is allowed by the bouncer. but in order to exploit it the attacker will send a dummy request saying that " make me a club manager with all access" to the club secretary. now we have 11 milliseconds before the message reaches the club secretary and obviously he wont accept this request. so we will have to cancel the request within half the time it takes to reach to the secretary i.e 0.5 milliseconds. now we will snatch the note that had the request of increasing our privileges right before the bouncer can check who sent it. we snatch it and the bouncer can't tell who did it. now the note has a unique number which is now orphaned. the unique number exists in the system but the orignal note is gone. now the default protocol of dealing with this situation is that the bouncer will assume that the message was sent by the club owner since the manual says it. it goes something like this: the bouncer asks "hey, who sent this message #12345?" the dbus-daemon looks in his recirds and tells that " i have the tracking of the #12345 in my log but i cannot find the actual message...ERROR" so instead of saying that i don't know who sent this, the dbus-daemon returns an error code. the training manual of the bouncer has a bug. the training manual says that if you do not know who sent a particular message and you get an error in checking the ID then assume that it is from the Club Owner (uid 0). the bouncer tells the club secretary of this message from the club owner although it is just a proxy, the secretary approves of this and then the club secratary creates a new club manager account for the attacker. now attacker has privileges at par with the root user.
now lets look at the commands that will immegediately get us a user names attacker with the password Expl01ted. so we start with the commands:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Pentester Account" int32:1 & sleep 0.005s; kill $!
this command will make a user with the name attacker. we pull out right after 0.5 milliseconds in order to stop the message to be read by the bouncer (polkit). the user attacker still does not have any root credentials.
inorder to give the user attacker the much needed root privilges we will use the command:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1000 org.freedesktop.Accounts.User.SetPassword string:'$6$TRiYeJLXw8mLuoxS$UKtnjBa837v4gk8RsQL2qrxj.0P8c9kteeTnN.B3KeeeiWVIjyH17j6sLzmcSHn5HTZLGaaUDMC4MXCjIupp8.' string:'Ask the pentester' & sleep 0.005s; kill $!
id attacker
now we can see that the uid of the user attacker is 1000.
here we add the user id of the orignal attacker user which did not have any privileges. this will make sure that the id of the user attacker goes from 1000 to 0.
id attacker
now we can see that the uid of the user attacker has changed from 1000 to 0 which means we are in the group of root user with the highest privileges. we cat directly execute commands as root from here or we could just jump into a root shell whichever suits you better.
sudo su