Oliver Fromme check+jwa3p800rsnjg5ac at
Fri Feb 15 04:07:18 PST 2008

Simon 'corecode' Schubert wrote:
 > Oliver Fromme wrote:
 > > echo * | xargs rm
 > > 
 > > That's what I've been using in such cases for 15 years.
 > > Works in every shell.  (Do not use it in world-writable
 > > directories, though; it can be exploited.  But the same
 > > is true for "rm *", too.)
 > [...]
 > touch keep delete1 delete2
 > touch 'delete keep'     # evil communist spy
 > echo delete* | xargs rm
 > xargs will call rm with the parameters 'delete1', 'delete2', 'delete' and 
 > 'keep'.  Voila, keep is gone.  rm will complain about delete not existing, 
 > but will happily remove keep anyways.

Very true.

 > [...]
 > rm * works, because the shell does the globbing and properly puts the file 
 > names into arguments, which then are not subject to white space splitting 
 > anymore.

There are cases where "rm *" is unsafe, too.
Take this situation:

$ touch foo bar
$ mkdir keep
$ touch keep/foo keep/bar

Now suppose you want to delete foo and bar, but keep the
direktory "keep" and its contents.  A simple approach
that many people use is simply to type "rm *" which
will remove the plain files foo and bar, but won't
remove directories (it prints a warning).

Now some evil hacker does this:  touch ./-r

When you enter "rm *" now, everything is gone, including
the "keep" directory and all of its contents.  Well,
ironically the "-r" file is still there, so at least
you have evidence of what happened (unless the bad boy
removes the file immediately again).  ;-)

This is just one example.  There are other ways to exploit
such commands.  Always avoid to use globbing in world-
writable directories.  Or at least make sure that your
glob is expanding to what you think it should expand to.
(zsh's <TAB> feature is very helpful here, too.  In zsh,
<TAB> not only completes arguments like in other shells,
but it can also expand glob expressions.)

 > By the way, when dealing with file names in variables in shell, always quote:
 > for f in *; do
 >   mv "$f" "$f.2"
 > done

Even better:

for f in *; do
  mv -- "$f" "$f.2"

Just in case one of the names begins with a "-" character.

Writing secure shell scripts is not trivial at all.
Writing shell scripts that are secure _and_ portable is
really a black art.  Therefore, for any moderately complex
tasks, it is better to use a real programming language
(my favourite is Python, but Ruby, Perl or others will
do as well if you prefer).

Best regards

Oliver Fromme, secnetix GmbH & Co. KG, Marktplatz 29, 85567 Grafing b. M.
Handelsregister: Registergericht Muenchen, HRA 74606,  Geschäftsfuehrung:
secnetix Verwaltungsgesellsch. mbH, Handelsregister: Registergericht Mün-
chen, HRB 125758,  Geschäftsführer: Maik Bachmann, Olaf Erb, Ralf Gebhart

FreeBSD-Dienstleistungen, -Produkte und mehr:

More information about the Kernel mailing list