Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

security concerns with Perl /e modifier

Tags:

security

perl

Let's say that I have a Perl script which contains a substitution command which takes replacement string as a positional parameter and uses /e modifier:

perl -pe 's/abc/$ARGV[0]/ge;'

Are there any security concerns with this approach? I mean is it possible to give such positional parameter value which causes perl to execute an unwanted function? I mean something similar: perl -pe 's/abc//;unlink ("/tmp/file");'.

like image 213
Martin Avatar asked Jul 03 '17 22:07

Martin


2 Answers

perl -pe 's/abc/$ARGV[0]/ge'

Are there any security concerns with this approach? I mean is it possible to give such positional parameter value which causes perl to execute an unwanted function?


In perldoc perlop in the section Regexp Quote-Like Operators it explains

  • e Evaluate the right side as an expression
  • ee Evaluate the right side as a string then eval the result.

But this isn't entirely true. In both cases the "right side"—the replacement—is evaluated as if it were a do block. In the first case the result provides the replacement string, while in the second the result is passed to eval and the result of that provides the replacement string. There is no distinction whereby the replacement is evaluated as an "expression" in the first place and as a "string" in the second.

Both /e and /ee allow for any valid Perl code sequence, including loops, conditionals, and multiple statements, and aren't limited to a single expression

There's never anything wrong with $ARGV[0] in isolation. Tainted strings become dangerous only if you execute them, either as Perl, using eval, or as shell code using system, qx//, or backticks. So it's fine in the replacement part of a substitution with a single /e modifier

But if you use something else in the replacement, for instance

perl -pe 's/abc/qx{$ARGV[0]}/eg'

then that parameter will be executed as a shell command, so it clearly isn't safe. But then nor is

perl -pe 's/abc/unlink glob "*.*"/eg'

so you have to be sensible about it

What is dangerous is the double-e modifier /ee, which treats the replacement as a Perl do block and then does an eval on the result. So something like

    s/abc/$ARGV[0]/eeg

is very unsafe, because you could run your code like this

    perl -pe 's/abc/$ARGV[0]/eeg' 'unlink glob *.*'

With just a single /e this would just replace abc with the string unlink glob *.* in $ARGV[0]. But using /ee, the string is passed to eval and all your files are deleted!

Remember this:

  • /e — replacement is an expression (a do block)

  • /ee — replacement is an expression (a do block) and the result is passed to eval



This is why I choose to use braces to delimit substitutions that use one of the /e modes. With s{abc}{ $ARGV[0] }ge the replacement looks much more like the block of code that it is than if I had used the usual slashes

like image 169
Borodin Avatar answered Sep 21 '22 10:09

Borodin


Unlike /ee, there's no inherent risk to /e as it doesn't invoke the Perl parser. It simply causes code in the source file to be evaluated, just like how map BLOCK LIST and for (LIST) BLOCK evaluate their BLOCK.

Note that

s{$foo}{$bar}g

is simply short for

s{$foo}{ qq{$bar} }eg

So if you're ok with

perl -pe's/abc/$ARGV[0]/g'

then you're ok with

perl -pe's/abc/"$ARGV[0]"/eg'

and the virtually identical

perl -pe's/abc/$ARGV[0]/eg'
like image 22
ikegami Avatar answered Sep 24 '22 10:09

ikegami