in reply to Re^11: Best way to write to a file owned by root?
in thread Best way to write to a file owned by root?
So basically you are saying get rid of my little hack script because it adds a vulnerability. OK, I'll buy that.
From experience, some little hacks evolve to huge programs that are distributed widely, and this little bit of a messy hack is so deeply in its core, wrapped in more and more workarounds, that you can't get rid of it any more.
I do want to learn to do this properly because eventually I'd like to be able to run scripts that update things like apache config files (owned by root) on a live server. I'd like to figure out what it takes to do this kind of thing without introducing security holes.
And here comes the evolution of that little hack. ;-)
Is there some tool or module already out like that that would allow me safely automate updates to my /etc/hosts file?
I don't know of any. Webmin and similar tools allow editing, perhaps even automatically, but that comes at a price. Webmin runs a huge base of ancient perl code as root. That's far from being secure.
Or do you recommend I just update it manually as I'm doing now with sudo vim?
Well, if you are happy with sudo vim, use it. But it seems that you have a good reason for using a dedicated tool, and if only for the validation.
I obviously don't have the talent (nor the year it would probably take me to learn how) to write something like that.
Most of the code already exists or is at least outlined in this thread:
The unprivileged user interface is quite easy. It reads /etc/hosts (let's stay with that file, but it could be any file, including Apache config files), creates a modified copy, places it somewhere, and tells the privileged service about a new job. This could be as easy as writing "/etc/hosts\0/tmp/hiuz8723rg978zt/etc-hosts\0\0" into a named pipe or a unix domain socket.
The privileged service is just an ordinary program running as root, preferably with taint mode on, opening a named pipe or a unix domain socket. It waits for a job in the form $sysfile."\0".$tmpfile."\0\0" from that source, starts the validating process, and if that returns ok, changes mode and owner of the temp file to that of the system file and renames the temp file to the system file. It should be obvious that you need different validators for different files, so the privileged service has something like this:
%validators=( '/etc/hosts' => '/usr/libexec/privileged-service/validators/etc-ho +sts', '/etc/apache/httpd.conf' => '/usr/libexec/privileged-service/valid +ators/apache-httpd-conf', '/etc/samba/smb.conf' => '/usr/libexec/privileged-service/validato +rs/smb-conf', '/etc/mail/aliases' => '/usr/libexec/privileged-service/validators +/mail-aliases', );
If $sysfile is not in keys %validators, that counts as failed validation and nothing more happens. The privileged service simply returns to wait for a new job.
Turing a simple program into a service is trivial if you use deamontools or tools copying daemontools. See my other daemontools postings and the djb way.
The validators obviously depend on the file format, but in they end, they can be quite primitive, at least for /etc/hosts. You want that file to have a size of significantly less than 1 MBytes. Die if the file is larger. Read the file line by line. All lines should match exactly one of four patterns: comment line, only zero or more white space, IPv4 + hostnames, IPv6 + hostnames. Die on the first line that does not match any of those patterns. Exit with 0 if all tests have passed.
Little details:
You may need do to something after changing some files: /etc/hosts is harmless, /etc/mail/aliases may need newaliases, /etc/apache/httpd.conf needs something like apachectl restart, and so does /etc/samba/smb.conf. Other programs only need a simple SIGHUP. Consider a second hash containing post-change-commands. Some programs insist on being stopped before changing their config files, add a third hash for pre-change-commands.
Even more links:
perlipc for Inter-process communication and dropping privileges, perlsec for taint mode, and Secure Webmin and Building a web-based system administration interface in Perl for concepts of similar, but larger tools.
Alexander
|
---|