in reply to stringification

For those that asked: the rationale is that I want an easily generalisable way of setting values in my program. E.g. a form input of foo__bar=whatever should result in $foo->{bar} = "whatever".

I think it is fairly secure: you can set variables but you can't execute anything.

Now equally, I don't always want to convert my variables to the appropriate string by hand. I want a quick method of changing $foo->{bar} to "foo__bar", so I can write

use CGI; print hidden( -name => struct_to_string($foo->{bar}, -value => $foo->{bar} );
.. and do that for lots of variables.

Ysee?

update: Some guys suggested Data::Dumper or FreezeThaw. That does seem obvious, but these things are also mostly for storing the data in a variable, not the name of the variable - e.g. Data::Dumper dumps stuff as $VAR1, and FreezeThaw freezes the value but not its name! but maybe I should put all the values I want to change into a big hash and then reference into it with Data::Dumper.

dave

Replies are listed 'Best First'.
Re: Re: stringification
by chromatic (Archbishop) on Feb 27, 2001 at 22:42 UTC
    Makes sense, depending on how far you trust the user. If you come up with a technique that can set a named variable, a saavy malicious user could set *any* named variable, if he guesses it correctly. If you have a variable named $datafile that points to a file to read, what if he sends "data__/etc/passwd" or what have you? Even worse, "data__|rm -rf . *"?

    You could solve two problems in one swoop by sticking every settable variable in a hash. You have to know the hash keys to access the values (so they're available), and if you only allow the hidden fields to modify pairs in the hash, it's a lot harder to do nasty tricks like above.

    On the other hand, you could use Apache::Session or a related technique, saving the data on the server temporarily, and passing only a session key or unique identifier on the hidden field, not serializing your data to hidden fields in HTML. I'd take this last approach, because I don't trust the clients to *type* the right thing, let alone send back correct data.

Re: Re: stringification
by merlyn (Sage) on Feb 27, 2001 at 22:56 UTC
      merlyn: very good point. but, can't you get round this by enclosing the variables in quotes? e.g.

      >perl -e ' sub string_to_struct { my $string = shift; my @refs = split /__/, $string; $string = "\$$refs[0]"; for (1 .. $#refs) { $string .= "-> {q/$refs[$_]/}" }; return eval "\\$string"; } print string_to_struct "foo__`rm xxx`"; ' SCALAR(0x8056ba4) >ls ... xxx ... >perl -e ' sub string_to_struct { my $string = shift; my @refs = split /__/, $string; $string = "\$$refs[0]"; for (1 .. $#refs) { $string .= "-> {$refs[$_]}" }; return eval "\\$string"; } print string_to_struct "foo__`rm xxx`"; ' SCALAR(0x8056bb0) > ls [argh! xxx has been removed]

      Anyway, I'll check the refs and consider making sure all my configs get written in a safe way. It still wouldn't be nice to let them set any variable, I guess....

      update:
      Great reference. That solves it. Once again, chromatic sorts me out.

      update 2:
      Well, not completely. Chromatics solution in the thread referred to above will traverse a hash and show all the keys (and values). I'll have a think how to hack it to go just to the key and value you want.

      update 3:
      And by the way, my claim that the code above would be safe is not true - see replies to this post for why.

      David

        Any solution that uses eval and doesn't do sanity checking on the input is vulnerable.

        For example, in the code snippet where you put q// around the keys, if I pass in the string "foo__/.`rm xxx`.q/" then the line that gets evalled is \$foo-> {q//.`rm xxx`.q//} If you do decide to go with eval, which personally I would not recommend, then you should turn on taint checking and make sure the input is safe before you eval it.

        >perl -e ' sub string_to_struct { my $string = shift; my @refs = split /__/, $string; $string = "\$$refs[0]"; for (1 .. $#refs) { $string .= "-> {q/$refs[$_]/}" }; return eval "\\$string"; } print string_to_struct "foo__`rm xxx`"; '
        just to interject here, on every unix system ive ever used, just typing 'perl return' will allow you to code freely until __END__ or control-d and then execute. no need for the -e '...'

        --
        transcending "coolness" is what makes us cool.