in reply to Re: Locking PERL code another way
in thread Locking PERL code another way

Thank you for thinking about this. This is how it works

1. OK, I've parsed. Now, get my tree.
2. When called, give out my tree MD5, say I keep running as a server process
3. Something else has all the MD5s and "pings" me pretty regularly

Since the inherited PMs, get-my-tree etc are all in the tree, (excepting ///o and others as other submitters have suggested) our MD5 seems to "lock" up everything that matters.

With regards to changing the code on disk, I assume something conventional watches the .pl file and that other security is in place for other compromises. This would help us trust the PERL binary etc.

We then want to prevent foo-root-user being able to fiddle with the executable image in memory. At the PERL level at least.

So, you are right; something has to watch something - it's not "self-auditing" :-).

But is it the case that something could be injected into the memory image which issues fake MD5s for us? How hard is it to fiddle with execution tree in the Perl state machine?

I'll also follow up what other people have posted, thank you.

Replies are listed 'Best First'.
Re: Re: Re: Locking PERL code another way
by liz (Monsignor) on Sep 25, 2003 at 05:47 UTC
    There must be a routine that returns the MD5. Let's call this "giveMD5" in package Foo. Then the following code will replace that routine by another routine, without the outside world knowing about it.
    { my $giveMD5 = \&Foo::giveMD5; my %givenMD5; *Foo::giveMD5 = sub { my $md5 = $givenmd5{@_} ||= $giveMD5->( @_ ); # execute old to obt +ain "real" MD5 # do evil things to op tree for given parameters if first time return $md5; # the "right" value }; }

    Of course, this is more or less pseudo-code to give you the idea.

    By the way, this "wrapping" technique is used in all sorts of Perl modules, so disabling this feature in Perl is basically impossible.

    Liz

      Thanks Liz,
      I was pretty sure there'd be something like that possible, but do you know how your example could be executed so that it affects my program _while its running_?

      I assume I am protected by *NIX protected memory... but I wonder if there is some debug mode for Perl that lets one inspect running code...or poke at a Perl process...? Cheers,
      Craig.
      PS My idea is getting some function creep, or worse, creep creep. However, to compromise the running process would require your hack above being able to affect my running process. I hope you haven't lost patience with this idea. The question then becomes "does this fangled idea really add any more security than tripwire etc?"
        You need to watch out for string eval's during execution. Now you might say, I'm not doing any string eval's. That may be true, but the modules that you've used at compile time, may do require at run-time. Many times this is done to reduce the memory footprint of the module and/or to reduce startup time.

        This is also the mechanism that AutoLoader type modules use.

        So you need to make sure that the files that are being required, can not be changed to include trojan horses. One way of doing that is with tripwire.

        Then there is also the possibility of programs changing @INC and/or @ISA of a module. That would also offer ways of introducing executable code.

        So basically, I think that if all of your explicit string eval's are covered, and you are sure that the modules that you use do not contain backdoors that would allow a string eval, and you're monitoring the files with tripwire, then maybe your idea makes sense as the final check on everything else. With a high chance on false positives, as Perl does its rearranging and changing of optrees with runtime requires anyway.

        I don't think it is worth the trouble given all the other security features that Perl has. But please don't take my word for it, as I am not a security professional, just someone with some experience.

        Liz

      Liz, a late reply here after some meditation. Your code snippet to steal the getMD5 routine would itself become part of the syntax tree for the program. This changes the MD5, even before you get to it. Anything calling us for the MD5 will get a bad MD5. This is, unless you can call getMD5 before the Perl code fully parses.

      Another way would be to somehow obtain the MD5 from our live script by copying the script elsewhere and executing it under debug. Presumably we can then observe the variable that handles the MD5 and grab it on its way through without modifying the syntax tree for the script. With the MD5, we can pretend to be the script.

      I know little about Debug. Does debug modify the syntax tree for a script by, say, instrumenting the code (the way some profilers do at run time?) if so, Debug could not help an attacker. Also, we could peek the memory for the data segment used by the script/Perl and try to find the MD5. However, with protected memory we would presumably be somewhat prevented from doing this.

      Presumably Perl has some Debug/Devel feature that lets one "watch" the state machine and so obtain the values of of any SV at any time? Or does it have security to prevent this?

      I think my idea is doomed, however. Trust requires secrets. If my script can be read, I have naught that can't be copied and used to pretend to be me to a remote entity. The Devel::opprof idea just attempts to prove all's well on-the-fly with a schroedinger's cat and a remote entity watching the door on the cat's box.

      This doesn't prevent someone from copying the cat/box and then putting up a picture of the cat/box for the remote observer.

      Cheers
      Craig.