10

On a Linux server, I need to remove root privileges from a group of users. But those users have legitimate reasons to be able to use the "find" utility to search for files based on file names, modification dates, and other metadata.

On the server, file names are not sensitive, but the file contents may be.

I would like use sudo to allow the users to search for files anywhere on the server. The "find" utility is great, but it allows for all kinds of side effects, such as using "-exec" to spawn arbitrary commands.

Can I get find to work with my restrictions?

  • 14
    Typically you don't want the search results for file name patterns to contain files that you can't actually access. In that regard your requirement is a bit odd. – HBruijn May 3 '17 at 11:44
  • 2
    Noone forces you to engage in the question. I think one of Server Fault's purposes is to serve as a forum for odd situations. – Troels Arvin May 3 '17 at 15:45
  • 2
    Server Fault is not a forum, and attempts at reverse psychology don't change the validity of HBruijn's observation (which was, I'm sure, posed in an attempt to help you). – Lightness Races in Orbit May 4 '17 at 13:36
19

What about locate?

locate reads one or more databases prepared by updatedb(8) and writes file names matching at least one of the PATTERNs to standard output, one per line. If --regex is not specified, PATTERNs can contain globbing characters. If any PATTERN contains no globbing characters, locate behaves as if the pattern were PATTERN.

By default, locate does not check whether files found in database still exist. locate can never report files created after the most recent update of the relevant database.

Or maybe even slocate:

Secure Locate provides a secure way to index and quickly search for files on your system. It uses incremental encoding just like GNU locate to compress its database to make searching faster, but it will also store file permissions and ownership so that users will not see files they do not have access to.

This manual page documents the GNU version of slocate. slocate Enables system users to search entire filesystems without displaying unauthorized files.

  • Good idea. I don't know why I didn't think of this. But I'm afraid that the "-d" parameter could be somehow used to read into arbitrary files, if sudo rules allows the user to run any "locate" command? – Troels Arvin May 3 '17 at 21:32
  • 2
    @TroelsArvin: locate doesn't need sudo; only its updatedb job requires special privileges. Your users thus shouldn't ever be running or be able to run sudo locate. – jwodder May 4 '17 at 1:36
  • 1
    @jwodder: On an RHEL 7 server: Let's say user u does not have access to /data/foo. In /data/foo, there's a file "somefile.csv". Now, when u performs "locate somefile.csv", the output from "locate" does not include /data/foo/somefile.csv -- unless user u executes "locate" via sudo. (Using the "--nofollow" argument does not help.) – Troels Arvin May 4 '17 at 6:08
  • 1
    @TroelsArvin but the -d flag only sets the database path? Maybe I misunderstood you. – Lenniey May 4 '17 at 7:16
21

According to man 7 capabilities

   CAP_DAC_READ_SEARCH
          * Bypass file read permission checks and directory read and execute permission checks;
          * Invoke open_by_handle_at(2).

This worked for me. (lines beginning with '#' are root, those with '$' are non-root) in this case the non-root user is in the wheel group.

# cp /usr/bin/find /usr/bin/sudofind
# chmod 710 /usr/bin/sudofind
# chown root:wheel /usr/bin/sudofind
# setcap cap_dac_read_search+ep /usr/bin/sudofind
# exit
$ find /root 
find: ‘/root’: Permission denied
$ sudofind /root
/root /root 
/root/Testbed 
...
... 
$ sudofind /root -exec cat {} \;
cat: /root: Permission denied 
cat: /root/Testbed: Permission denied
$ sudofind /root -printf "%u %g %m %c %p\n"
root root 644 Mon Apr 20 09:20:48.0457518493 2015 /root
root root 755 Fri Dec  4 02:34:03.0016294644 2015 /root/Testbed
...
...
$ # Capability inheritance test..
$ sudofind /root -exec /bin/sleep 10 \; &
[1] 17017
$ getpcaps $(pgrep find)
Capabilities for `17017': = cap_dac_read_search+ep
$ getpcaps $(pgrep sleep)
Capabilities for `17019': =

Given what the capability grants, it fits in with exactly what you want. I've not exhaustively checked whether find has a feature which allows you to read bytes inside of files, but obvious stuff like LD_PRELOAD and library shim attacks shouldn't work due to the nature of setuid checks in Linux, and the capability bits don't get inherited by child processes either (unlike raw setuid) so that's another bonus.

Bear in mind that what you want to do does raise possible privacy concerns in regards to temporary file creation or access, and the program could be used as a basis to mounting a race condition / privilege escalation attempt (against programs that create well-known filenames but don't do correct security checks).

Also, some poorly written applications may rely on file metadata or tree structure as a way to convey meaning or hide data. This might cause release of restricted information or reveal privileged documents not otherwise known about (security through obscurity I know, but this is a thing that closed-source vendors in particular like to do, unfortunately).

Therefore, take care and be wary about doing it and understand there is still risk associated with this even if the obvious things don't work.

Oh, and I'd be interested to see if someone has a proof of concept attack which uses this mechanism as a basis for privilege escalation in the comments!

  • 5
    This indeed looks quite interesting! – Sven May 3 '17 at 12:10
  • Like this? Well, no PoC, but interesting nonetheless: forums.grsecurity.net/… – Lenniey May 3 '17 at 13:47
  • I like this idea, but it has a significant drawback: sudofind is now a binary which is not part of any software (e.g. RPM) package on the system. So if the distribution sends out a patch for "find", then sudofind will not be updated. – Troels Arvin May 3 '17 at 15:41
  • 2
    @TroelsArvin That's not necessarily a bad thing. If you're adding setuid-like capabilities to an existing utility that wasn't designed for those capabilities, you wouldn't want any any updates to the underlying utility before you verified that the updated utility can be safely used with your non-standard capabilities. Imagine in this case if an update were to give find the capability to execute some user-supplied code directly, similar to what awk can do. – Andrew Henle May 3 '17 at 15:52
  • 4
    Biggest problem I can see with this is that world-writable directories that are underneath non-searchable directories can suddenly be written to. – Tavian Barnes May 3 '17 at 18:07
2

I would give the users proper permissions.

By default, if the umask is 022, directories are created so that everyone can list and stat the files in them. If not, you can manually change the permission of the directory to be the bitwise or of its old permissions and 0555:

chmod +0555 foo

And if those users don't have execute permission on all the parents of that directory (for example, another user's home directory), it probably means you should put the first directory somewhere else.

If you want to only let some users to read and execute that directory, you can change its mode to 0750, put those users in a group, and change the group owner of the directory to that group:

groupadd can_read_foo
chmod 0750 foo
chgrp can_read_foo foo
gpasswd -a alice can_read_foo
gpasswd -a bob can_read_foo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.