next up previous
Next: Passing Arguments through Environment Up: Application layer issues Previous: Passing Strings to the

Other Pitfalls with Command Line Arguments

You will have noticed that the very first statement in the execute_viewer function above calls a function named sane_url that isn't shown in the listing. Before we actually write that function, let's talk about the potential damage an attacker can do through command line arguments.

Assume the user configures his application to use a different viewer, say lynx, this is invoked as "lynx %s". Probably the first thing that comes to mind are, what about local files as arguments? Well, just specifying /etc/passwd will cause no grief; all that happens is that the intended ``victim´´ is shown his own password file. A somewhat nastier variant though is to make lynx display special files like /dev/zero, which will cause lynx to sit there reading zero bytes from the device until it dies of memory exhaustion. Which is not a real problem either. On some Unix or Linux systems, however, the mouse device is readable by the user running the X Windows session, and telling lynx to read from the mouse device will seriously hose the victim's session.

There are worse things that can happen, however. Among other things, lynx supports special URL schemes such as lynxexec:command. If enabled,8.3 lynxexec URLs will cause the specified command to be executed. The advantage to a potential attacker is obvious.

However, there is even more havoc an attacker can cause. Think about command line arguments! lynx supports a huge number of them, and one of them is -cfg which lets you specify an alternative configuration file. And you can do interesting things with this file! One of them is defining what program to use in order to display images. Now imagine a nasty person manages to If the attacher manages to upload a fake configuration file on the victim's computer, say /tmp/nasty.cfg. this fake configuration file specifies the command rm -rf   as the image file viewer. Now all he needs to do is make the victim visit the URL -cfg=/tmp/nasty.cfg http://foo.com/blah.jpg and lynx will execute what it thinks is the program to view the downloaded JPEG file...wiping the victim's home directory instead. Of course, there are other things you can do here...you get the idea.

Now, there's a big IF in the scenario above; which is the attacker's ability to upload a file to the victim's machine. Contrary to popular belief, this is a lot easier than many people think. For instance, you can mail it to the victim, and for most Unix and Linux flavors it will wind up in /var/mail/login or similar. And guess what - most parsers, including lynx' config file parser, are robust enough to skip all mail headers and other gunk they're unable to parse.

So what do we learn from this? You need to be extremely paranoid about what you accept as command line arguments. First, never allow arguments starting with a dash. It could be a deadly command line option. And don't think that the lynx example above is contrived! There have been attacks on FTP daemons and telnetd that exploited this type of problem successfully.

Second, if you run powerful programs like lynx with untrusted command line options, try to be really anal about what you accept. It's better to make one or two people unhappy because you're too anal, than putting your entire user base at risk through e.g. a mail virus or worm. In the case of lynx, the right check would be to accept only HTTP and FTP URLs, for instance.

Here's some sample code:

int
sane_url(const char *url)
{
    int n;

    if (strncasecmp(url, "http:", 5)
     && strncasecmp(url, "https:", 6)
     && strncasecmp(url, "ftp:", 4))
        return 0;

    /* Be extra nasty: restrict the set of characters we accept.
     * Note that we can accept shell meta characters because we
     * use exec() rather than system() to run the command. */
    while (*url) {
        if (!isalpha(*url)
         && !isdigit(*url)
         && !strchr(".,?=;", *url))
            return 0;
    }
    return 1;
}

XXX: As a special case, mention sendmail which can take its list of addresses from the mail message itself (-t option).


next up previous
Next: Passing Arguments through Environment Up: Application layer issues Previous: Passing Strings to the
Olaf Kirch 2002-01-16