#define BUFSIZE 256
int escape_single_quotes(char *to, char *from, int max)
{ int l= 0;
for (;*from;from++)
{
switch (*from) {
case '\'':
if (l>=max-4) return 0; // not enough space for escaped chars!
// replace ' with '\''
*(to++)= '\'';
*(to++)= '\\';
*(to++)= '\'';
l += 3;
default:
if (l>=max-1) return 0; // not enough space for this char!
*(to++)= *from;
l++;
}
}
*to= 0;
return 1;
}
int main(int argc, char *argv[])
{
FILE *fp;
char buf[BUFSIZE];
char escaped_name[BUFSIZE]; char *filename;
int lines, chars, cpl;
if (argc != 2)
{
fprintf(stderr, "Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
filename= argv[1];
printf("Counting %s ... \n", filename);
if (!escape_single_quotes(escaped_name, filename, BUFSIZE)) {
fprintf(stderr, "Escaped filename is too long!\n");
exit(EXIT_FAILURE);
}
if (snprintf(buf, BUFSIZE, "wc -l '%s'", escaped_name)>=BUFSIZE)
{
fprintf(stderr, "Filename %s is too long!\n", filename);
exit(EXIT_FAILURE);
}
fp= popen(buf, "r");}
Is this script safe from command injection? It replaces ‘ by ‘\”. Is there anyway to break from single quotes and inject a command?
If I read this program correctly, it simply calls
wc -lon its filename parameter.When you are trying to escape this filename, it probably means it comes from source that you cannot trust.
Given that, few points:
access()call, and if it does, you can pass it to wc without much concern.I would not trust even whoever calls this very program, which means you cannot trust your own PATH. In other words, when you call
wc -l, you may very will be calling something evil, because somebody did something along these lines:Oops! Even if file name was good, attacker still was able to trick your program to calling evil code.
Solutions:
In this particular case, you can probably implement
wc -lon your own and not call anything external – it is very simple algorithm after all.Also, when calling external programs, you should try to call them by full name, like
/usr/bin/wc.If parameters are filenames, it is good idea to check if they actually exist before passing them over.
You may want to sanitize your parameters for valid chars, but this is easy to do wrong, and for example remove non-ASCII symbols that are crucial for all non-English speaking world.