2

I was unsure on how to correctly script a particular awk command which uses a shell variable, when I read the answers to How do I use shell variables in an awk script?.

The accepted answer demonstrates how interpolating a shell variable in an awkcommand would be prone to malicious code injection, and while I was able to reproduce the demo, I could not find the same problem with either of the following two commands:

#HWLINK=enp10s0
ip -o route | awk '/'$HWLINK'/ && ! /default/ {print $1}'
ip -o route | awk "/$HWLINK/"' && ! /default/ {print $1}'

So, the main question is if any of these (or both) is vulnerable.

A secondary question would be which form is preferred. I tried ip -o route | awk -v hwlink="$HWLINK" '/hwlink/ && ! /default/ {print $1}' but that doesn't work.

p.s. this is a refactoring; the original command was ip -o route | grep $HWLINK | grep -v default | awk '{print $1}'.

Marc.2377
  • 7,807
  • 7
  • 51
  • 95

2 Answers2

4

Your idea was right about letting the shell variables getting interpolated inside awk could let malicious code injection. As rightly pointed use the -v syntax, but your attempt fails because the pattern match with variable doesn't work in the form /../, use the direct ~ match

ip -o route | awk -v hwlink="$HWLINK" '$0 ~ hwlink && ! /default/ {print $1}'

Recommended way to sanitize your variables passed to awk would be to use the ARGV array or ENVIRON variable. Variables passed this way don't undergo expansion done by the shell

value='foo\n\n'
awk 'BEGIN {var=ARGV[1]; delete ARGV[1]}' "$value"

If you printed the value of var inside the awk it would be a literal foo\n\n and not the multi-line string which usually happens when the shell expands it.

Inian
  • 80,270
  • 14
  • 142
  • 161
  • 1
    Thank you for your answer. I had somewhat of a hard time picking one, since both were helpful (and are equally upvoted). This time I went with the other one but you do have my upvote. p.s.: great profile pic! – Marc.2377 Jun 14 '19 at 19:39
4

Sure, both are vulnerable, the first a bit less so.

This breaks your second line:

HWLINK="/{}BEGIN{print \"Your mother was a hamster and your father smelt of elderberries\"}/"

The only reason it doesn't break your first line is, in order to be able to be injected into the first line it must not contain spaces.

HWLINK="/{}BEGIN{print\"Your_mother_was_a_hamster_and_your_father_smelt_of_elderberries\"}/"

I see you already got the correct syntax to use :)

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • That's awesome. – Marc.2377 Jun 14 '19 at 05:10
  • Can you help me in getting it to run [sl](http://manpages.ubuntu.com/manpages/bionic/man6/sl.6.html)? I tried `HWLINK="\";sl -a;#"`. Didn't work. – Marc.2377 Jun 14 '19 at 05:38
  • That can't work - at this point, you're inside a regular expression, so `\"` just ends up trying to match a quote. What I do is breaking out of regular expression using `/{}`, which together with the existing `/` makes `//{}` (an empty regexp with empty statement); then use the `BEGIN{ ... }` to invoke awk code at the start; at the end, I use `/` again so that your closing `/` doesn't hang without a friend. Also, you're mixing up shell and awk; `sl` is a shell command, and you can't run it as if belongs there. You have to use `system` command. `"/{}BEGIN{system(\"sl -a\");exit}/"` – Amadan Jun 14 '19 at 05:59
  • and now imagine the following code in the BEGIN statement `{system( "rm -rf *") }` – kvantour Jun 14 '19 at 08:47
  • @kvantour: Indeed. – Amadan Jun 14 '19 at 08:48
  • ITYM "the first a bit **more** so" since in the first one the variable is completely unquoted and so will have globbing, etc. performed on it while the 2nd one is at least inside double quotes. – Ed Morton Jun 14 '19 at 10:49
  • 2
    @EdMorton: The issue is that _because_ it is unquoted, any space will _terminate_ the awk script; globbing won't really work if you can't have spaces to delimit it. E.g. if you tried to put in kvantour's `{system("rm -rf *")}`, the awk script would only be `//{}BEGIN{system("rm`, resulting in a syntax error. EDIT: HOWEVER, you could put a semicolon after the space and write plain bash command, which could indeed glob... ay ay ay, yes, you're right, it's _more_ so. – Amadan Jun 14 '19 at 10:51
  • I guess which is worse just depends on what the attack looks like. – Ed Morton Jun 14 '19 at 11:04