Hacker News new | past | comments | ask | show | jobs | submit login

1. Shell-escaping all values used to construct commands

Avoid shell-escaping and the shell altogether! Use list form program execution wherever possible.

In Perl:

    open(my $fh, "-|", "find", $dir, "-type", "f", "-print0") or die;
In Python:

    f = os.popen2(["find", dir, "-type", "f", "-print0"])
If you're executing a pipeline, you do need to get the shell involved. But I'd probably write the author's examples like so (once again avoiding the need to shell escape arguments):

    f = os.popen2(["sh", "-c", \
       'find "$0" -type f -print0 | xargs -0 grep foo | wc -l', dir])
2. Prefixing each multi-command pipeline with “set -o pipefail;

Alas, pipefail is not in POSIX /bin/sh, which many of us prefer for shell scripting. It's in bash and ksh though.

3. Explicitly checking for failure after each shelled out command

Valid. You should always do this. In shell scripts, "set -e" is a good thing, although pipelines without "set -o pipefail" are still a problem.




The article does not address another significant point: filenames should also be classified as untrusted input. Using -- to separate flags from arguments can help:

    /tmp$ mkdir x
    /tmp$ cd x
    /tmp/x$ echo hello > a 
    /tmp/x$ grep hello *
    hello
    /tmp/x$ touch -- -q 
    /tmp/x$ grep hello *
    /tmp/x$ grep hello -- *
    a:hello
    /tmp/x$
It's rare to see protection against this problem either when shelling out or in native shell scripts.


Your quoting of "$0" does not protect it from the shell. An attacker need only provide an input such as: /tmp"; rm -rf /; "

There are pipeline libraries that avoid the shell for several languages. Some I can recommend:

* libpipeline http://libpipeline.nongnu.org/ easy, if somewhat verbose, pipeline construction in C.

* hsh https://github.com/jgoerzen/hsh/wiki makes pipelines in haskell, using operators so they really look like pipelines, but without involving the shell. Example: "ls -l" -|- "wc -l"


Your quoting of "$0" does not protect it from the shell. An attacker need only provide an input such as: /tmp"; rm -rf /; "

Not true.

  $ sh -c 'ls "$0"' '/tmp"; rm -rf /; "'
  ls: cannot access /tmp"; rm -rf /; ": No such file or directory
If you were right, there would be no reasonable way to write shell scripts.


My mistake, not knowing python's variable interpoltion well, I thought that the $0 was expanded by it, not the shell. Which, if it were the case, would indeed be vulnerable.

Isn't it a bit harsh to downvote to -1 a comment which links to two completly on-topic libraries?


Your comment would be correct if it were PHP.


I didn't downvote you, fwiw.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: