14

I can configure sudo (via the sudoers file) to allow a user to run the chown and chmod commands on any file or directory in the system. However, I only want to grant a user permission to run these commands on files that reside beneath the /var/www/html directory.

How can I restrict privileged commands such that the user may only run them in a pre-specified directory?

For example: The following command grants 777 permissions to index.html file.

sudo chmod 777 /var/www/html/index.html

Now I want to perform two actions

  1. Restrict sudo such that the user may only run chmod and chown from within /var/www/html

  2. Disallow the user from executing these commands elsewhere in the system (e.g. the commands cannot be run in /var/www or /var/ftp)

PrashantB
  • 325
  • 1
    Please don't crosspost - http://superuser.com/questions/456662/how-to-restrict-to-run-commands-in-specific-directory-through-sudo – Ulrich Dangel Aug 02 '12 at 11:22
  • 7
    Is this really the right way? How about a www-data group eliminating the need to chmod/chown anything? – sr_ Aug 02 '12 at 11:23
  • Cool. That way you get root pretty easy. It is a very bad idea to give away chown. Apart from that I see no reason why chmod has to be run as root. – Nils Aug 03 '12 at 19:38

3 Answers3

14

What you're asking is difficult if not impossible. Even if you did restrict the application of chown and chmod to files under a specific directory, someone could still pass a symbolic link and so affect files anywhere they like.

Fortunately, it's highly likely that what you're attempting to do is just not the right solution to your actual problem, and there is another method that works.

Usually, users who need additional permissions to create and modify files under /var/www are added to a group (often www-data, or you may have different groups for different parts of the site). You can use group ownership and setgid directories: chgrp www-data /var/www/html; chmod g+ws /var/www/html allows everyone in the www-data group to write to the /var/www/html directory, and files created in that directory will be owned by the www-data group instead of the primary group of the user who created the file. However, this is not very flexible.

What you probably should do is set up access control lists for files under /var/www. First, make sure that ACLs are enabled: the filesystem that /var/www is on must be mounted with the acl option. See Make all new files in a directory accessible to a group for help on that. Also install the ACL utilities (getfacl and setfacl). Then give extra permissions to the tree under /var/www/html to the users who should have them. You can set per-user ACLs, but it's often easier to put users who should have the same rights on a part of the filesystem in a group and set ACLs for that group. For example, if the users in the group html-writers should have read-write access to the tree under /var/www/html:

setfacl -d -m group:html-writers:rwx /var/www/html
setfacl -m group:html-writers:rwx /var/www/html
  • Concerning "this is not very flexible" (at the end of paragraph 3) — why is it not? Is it because people need to be in a certain group? (I know barely nothing about permissions and ACL and related things.) – KajMagnus Aug 14 '15 at 07:33
  • 3
    @KajMagnus It's inflexible because root has to manage groups, and files can only belong to a single group. ACL let any user select who can access the files they own, and multiple users and groups can be mentioned in an ACL . – Gilles 'SO- stop being evil' Aug 14 '15 at 10:12
3

You can restrict the command to be used by "myuser" with all arguments in /etc/sudoers file with the command visudo add:

## Allows myuser to chmod the html dir and chmod 755 the html2 dir
myuser  ALL=NOPASSWD:/bin/chmod [0-7][0-5][0-5] /var/www/html/*,/bin/chown myuser:mygroup /var/www/html/*,/bin/chmod 755 /var/www/html2/myapp/*.txt 

enable logging for every operation adding:

Defaults logfile=/var/log/sudo.log

sample output:

[root@myhost /]# su - myuser
-sh-3.1$ sudo /bin/chmod 755 /var/www/html/index.html 
-sh-3.1$ sudo /bin/chmod 755 /var/www/html/*
-sh-3.1$ sudo /bin/chmod 777 /var/www/html2/myapp/*.txt
Sorry, user myuser is not allowed to execute '/bin/chmod 777 /var/www/html2/myapp/*.txt' as root on myhost.mydomain.
-sh-3.1$ sudo /bin/chmod 755 /var/www/html2/myapp/*.txt 
-sh-3.1$ 

When you use sudo, the premise should be that "myuser" is a trusted person. Be carefull with file permissions, there is no a simple way to stop a malicious sudo user from link a file from an external resource and change it.

  • I have tried it before, but it gave the error as:

    Sorry, user prashant is not allowed to execute '/bin/chmod 777 /var/www/html/a' as root on prashant.xyz.com.

    – PrashantB Aug 02 '12 at 12:11
  • have you switched user with su - prashant or su prashant? – tombolinux Aug 02 '12 at 12:14
  • Yes I am executing command by prashant user. I read forums,they say commands run system-wide. No one has write about such issue. – PrashantB Aug 02 '12 at 12:19
  • I run it whooo :). But this will be static command. Can we make it general so that I can apply any permission on any file under /var/www/html? – PrashantB Aug 02 '12 at 12:22
  • The sudoers file is read when the user login, if you logged in with su prashant the sudoers file isn't readed.
  • 2)Make sure that you have entered the commands with all arguments when edit with visudo to limit the action of the command in a specified dir. 3) use the wildcard as you want; if you put /var/www/* your limit is the /var/www dir, if you put /var/* the limit is all the var and so on...

    – tombolinux Aug 02 '12 at 12:25
  • /bin/chmod [0-7][0-7][0-7] /var/www/html/* should also work – tombolinux Aug 02 '12 at 12:55
  • Should probably note the limitations. It will only work with absolute paths and it won't support any extra parameters for chmod and chown. – Šimon Tóth Aug 02 '12 at 13:45
  • @tombolinux It works like charm.

    Now I trying same thing with chown command. I can't get the rid of Regular expression for username:username.

    – PrashantB Aug 02 '12 at 13:51
  • probably [0-9a-zA-Z]+:[0-9a-zA-Z]+ – tombolinux Aug 02 '12 at 15:05
  • 5
    This is completely insecure: sudo /bin/chmod 666 /var/www/html/../../../etc/passwd And if you somehow fix that, ln -s /etc /var/www/html/foo/etc; sudo /bin/chmod 666 /var/www/html/foo/etc/passwd – Gilles 'SO- stop being evil' Aug 02 '12 at 23:17
  • @Gilles I agree with you. While maybe possible to filter which kind of file can be chmodded with a regex, there isn't a safe solution to stop a sudoer user to chmod 666 a link to other resource. – tombolinux Aug 03 '12 at 04:26
  • maybe disallow ln -s for the user ? – john Smith Jun 22 '15 at 11:18