Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don't think that setting IFS this way is a good idea. Of your variables do happen to contain tabs and newlines, you still get unwanted word expansion. Much better is to just use double quoted expansion primitives that always expand one element to each word: "${foo[@]}"


Agreed. The IFS trick is shortly followed by an explanation, which includes a bunch of anti-patterns, such as bare ${foo[@]} and $@ usage.

Rule of thumb: quote all your variables.

http://mywiki.wooledge.org/Quotes


That's the common answer, and while I practice that myself, I have to disagree with it as guidance. Maybe you and I are fastidious enough to always remember to quote all our variables, but many are not - I know I was writing shell scripts for a couple of years before I realized its importance, and it's very common that even experienced engineers don't know or care to do it. If someone writing or editing the code forgets to quote the variable that allows subtle bugs to sneak in.

It's unfortunate the semantics of bash don't have variable references behave like they are quoted by default. I really wish it did.


If you can remember to use $@ rather than $*, you should be able to remember to use "$@". The only reason $@ exists is that it behaves differently when enclosed in double quotes.


While setting IFS=$"\t\n" may make problems less likely when strings contain spaces, it's still not correct. File names (and other strings) can contain tabs and newlines, too. That's relatively rarer, but the quoting approach always works.


Hm, is that true? When I run this script:

  #!/bin/bash
  items=(
      'a'
      'b c'
      "d\te"
      "f\ng"
  )
  
  echo "Unquoted:"
  for item in ${items[@]}; do
      echo -e ".  $item"
  done
  
  echo "Quoted:"
  for item in "${items[@]}"; do
      echo -e ".  $item"
  done
  
  set -euo pipefail
  IFS=$'\n\t'
  echo "Unquoted strict mode:"
  for item in ${items[@]}; do
      echo -e ".  $item"
  done
... I get this output:

  Unquoted:
  .  a
  .  b
  .  c
  .  d    e
  .  f
  g
  Quoted:
  .  a
  .  b c
  .  d    e
  .  f
  g
  Unquoted strict mode:
  .  a
  .  b c
  .  d    e
  .  f
  g
Note the output for "Quoted" and "Unquoted strict mode" are identical.

(GNU bash, version 4.2.37(1)-release (x86_64-pc-linux-gnu))


Unquoted variables are an attack vector. Plain and simple. The IFS tip, as described in the original article, does nothing to remedy it.

https://www.owasp.org/index.php/Command_Injection


Can you give an example of an exploit in bash? The link you give is excellent information, but doesn't have any shell script examples.

My first thought: It seems like only $@, $* and variables read from the environment could be possible attack vectors. But since shell scripts can't be setuid, it's hard for me to immediately imagine how unquoting could enable a new exploit.

EDIT: the most dangerous example I can think of right now is a script like this, where a webapp invokes the script and passes a GET param as an argument:

  #!/bin/bash
  exec $1
But if I execute this like so:

  ./badscript.sh 'some-benign-command ; cat /etc/passwd'
... then passwd is not exposed, because the tokens ";", "cat" and "/etc/passwd" are passed into the argv of some-benign-command.

(And if "cat /etc/password" itself can be passed as $1, then quoting won't help...)




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

Search: