One great way to disclose arbitrary file contents to an attacker
is to use strings specified by the peer in a pathname, without
checking for .. path components.
As an example, consider TFTP, the trivial file transfer protocol used by some operating systems in bootstrapping machines over the network, usually for downloading the OS kernel to a diskless or unconfigured machine. The protocol supports simple requests such as ``send me 1024 bytes at offset 65536 of file sun4mkernel.'' The daemon serving TFTP requests is usually called tftpd on Unixish systems, and is usually configured to serve only files located below /tftpboot or some other special directory.
Now older versions of tftpd on Linux (and probably some commercial Unixes as well) had that stupid bug of not checking for .. components in the path names. Thus by asking for ../../../etc/passwd anybody on the whole net could download the password database (provided there was no firewall).
So, whenever you use a string supplied by an untrusted peer, make
sure to check that it contains no .. path component. If
you're worried that legal requests might include file names containing
two adjacent dots, check for /.. and ../. Note that
checking for /../ does not work, because it will miss strings
starting with ../:
FILE *
open_userfile(const char *name)
{
char pathname[1024];
if (strstr(name, "../") || strstr(name, "/.."))
return NULL;
snprintf(pathname, sizeof(pathname), "%s/%s",
BASEDIRECTORY, name);
return fopen(pathname, "r");
}