Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Is this code secure, can I test it on my machine?

by szabgab (Priest)
on May 23, 2010 at 08:45 UTC ( [id://841237]=perlquestion: print w/replies, xml ) Need Help??

szabgab has asked for the wisdom of the Perl Monks concerning the following question:

When downloading a CPAN module I quite blindly trust it to make no harm to my machine (which is stupid I know) but a recent blog post pointed to some code that is not (yet) on CPAN and I started to think how could I check if I can run that code safely on my machine?

I guess the best would be to create a new user and run it as that user but that sounds like too much work on one hand and not good enough on the other hand. (e.g. the code could still send out information about my machine)

So I was wondering how could I check if a the code is secure? I could read it hoping that I will recognize issues but that might be too much work and I can easily miss the important part. I think a better approach would be to check for any code that might be dangerous and check only that part.

I was thinking what could be dangerous and here is a short list I came up with:

The use of system, exec, qx, backtick, string eval, open with pipe, unlink.

I am sure I missed a few. Any other expression that you think might be dangerous?

Of course loading of any module via use, require or do would expose us to further dangers so I need to do the above check on all the modules that are loaded by the code recursively. That's still the same thing as above.

The last piece here is to make sure we know which files are actually loaded by the code so if I check /home/foo/code/File.pm I can be sure that file will be loaded and not some other File.pm i have not checked. For this I need to check for the appearance of use lib and @INC in the code.

I am quite sure I am not the first one to need this. Any solution that you might know of?

  • Comment on Is this code secure, can I test it on my machine?

Replies are listed 'Best First'.
Re: Is this code secure, can I test it on my machine?
by Xilman (Hermit) on May 23, 2010 at 09:31 UTC

    I keep saying this, on PerlMonks and elsewhere, but the message still doesn't seem to be widely understood: evaluating security is very difficult in the absence of an explicit threat model. What do you consider to be the threats? Against what type of attacker, with what resources available to them, are you attempting to protect what kind of assets? What is the value of your assets to you and what is the expected value of your assets to the attacker? How much are you prepared to spend in order to protect your assets?

    Once you have a threat model, you are in a position to evaluate the costs and benefits of performing a security analysis. Until then, you can only go on guided guesswork and try to avoid the simple pitfalls with low-cost countermeasures. With that in mind, the following material consists only of a few general principles to consider in addition to the items you've already mentioned.

    Any output could be dangerous. Consider, for example, what would happen if the code rewrote your kernel, your password database, the binaries of your critical utilities ...

    Some input could be dangerous (keyboard grabbers, password database, PKCS private keys ...) if the utility could later hijack a communications mechanism to leak the secrets. Note that the output channel need not be obvious --- there are any number of ways of setting up a covert channel.

    A commonly used environment for testing security properties of software is to run it in a sandbox where it can't easily do as much harm as running it on a production system. For example, download the package onto a local machine but do not install it there. Fire up a virtual machine, ensuring the VM has no connection with any other system, including its host's filesystem and network. Then install the package on the VM and see what happens. Note that this approach will not detect all security vulnerabilities, not least because it depends critically on the "see what happens" stage. Nonetheless, it tends to pick up quite a few of the more obvious attacks.

    Paul

      "threat model"

      Well, I understand that I should explicitly state what do I consider as a threat and what not but that in itself is to difficult for me now. Besides when I am asked if this code can be trusted, usually the person who asks this has even less understanding than I do. Which, you might guess, is really little.

      So I go back thinking about the issue at hand.

      I guess we have an advantage here that we have the source code so we don't necessarily need to check the behavior. We can check the source code.

      In the code that raised the whole question one of the modules only contains some variables. most of the code is just looks like this:

      # number of carnivores in the beginning $NUM_CARNIVORES = 30;
      I am not a security expert but I think we can easily agree that such code in itself cannot be dangerous even though we are talking about carnivores here.

      That means if I want to evaluate the code - regardless of my threat model or lack of it I can disregard those line when I am checking the source code.

      OTOH if I see code like this:

      use Carnivores;
      that should immediately raise the red flag and tell me to look for the Carnivores.pm file to see what dangers might lurk in there.

        Well, I understand that I should explicitly state what do I consider as a threat and what not but that in itself is to difficult for me now. Besides when I am asked if this code can be trusted, usually the person who asks this has even less understanding than I do.
        That's easy. In that case, the answer is No, I cannot trust the code. You just don't have enough information. Even if you do have perfect knowledge of the third party code, you still don't know enough of your own system.

        Suppose the code you're looking at contains something like this:

        use Fcntl ':flock'; my $lockfile = "/var/lock/frobnitz"; open $lh, "+<", $lockfile or die $!; flock $lh, LOCK_EX or exit; sleep 600; exit;
        Harmless? Probably. Unless you have another program running that uses /var/lock/frobnitz for locking - that one will be blocked for 10 minutes.
Re: Is this code secure, can I test it on my machine?
by moritz (Cardinal) on May 23, 2010 at 09:15 UTC
    The use of system, exec, qx, backtick, string eval, open with pipe, unlink.

    I am sure I missed a few. Any other expression that you think might be dangerous?

    truncate, syscall, sysopen, fork, kill

    There are various levels of paranoia you can apply, with more paranoia meaning more work. For example you can set up a virtual test machine with an selinux enabled kernel (or openbsd, which is paranoid by default, or a solaris zone, which is also said to be quite secure), where you can do things like forbid network access, prevent writing or even reading files with different security context etc.

    But I know of no solution that's both secure and little effort.

Re: Is this code secure, can I test it on my machine?
by salva (Canon) on May 23, 2010 at 09:31 UTC
    Doing that at the Perl level is impossible, you may defeat some simple attacks but nothing else. Perl is too flexible and in this case, TIMTOWTDI plays against you!

    Besides that, there are too many ways to gain complete control of the Perl interpreter: exploiting known bugs, forgering XS objects, unpack "p",..., etc.

    A better approach would be do it at the OS level, using some MAC framework as AppArmor or running the code inside a virtual machine or a container.

      Doing that at the Perl level is impossible

      Indeed. This is what Safe does, and it's officially considered to be unable to do its task.

      Clearly if someone can use XS otherwise leave perl that would need to be checked separately. The question then how can I locate the places in a perl code that indicate the usage of XS or other non-Perl code?

      What can you do with unpack "p"? Do you have an example?

        What can you do with unpack "p"
        I though it could be used to write to random locations in the process memory, but actually it can only be used to read from random memory, so it is mostly harmless, forget about it!
Re: Is this code secure, can I test it on my machine?
by BrowserUk (Patriarch) on May 23, 2010 at 12:06 UTC

    Seems to me this would be an excellent use of a module that people tend think I abhor. Perl::Critic. Seems likely that it will flag most of the "potentially dangerous" code by default. And with a little careful tuning of the profile--turning off the warnings for benign code--, you should be able to get it to tell you about just those things you are interested in.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Apparently more and more of my questions get the answer use Perl::Critic. Maybe I need to learn how to use it more that just running perlcritic.
Re: Is this code secure, can I test it on my machine?
by ikegami (Patriarch) on May 23, 2010 at 16:23 UTC
    eval EXPR, s///ee and use re 'eval'; can be used to execute arbitrary Perl code.
    >perl -e"system \"echo Hello World\"" Hello World
    can be written as
    >perl -MMIME::Base64 -e"$_='c3lzdGVtICJlY2hvIEhlbGxvIFdvcmxkIg=='; s/( +.*)/decode_base64 $1/seige" Hello World
      string eval is already flagged as dangerous spot and "use" too. The new thing here is substitution with two "e"-s:
      s/.../.../ee

      Do I understand correctly that a single e after the substitution would only be dangerous if the code inside is dangerous

      s/.../system($1)/e
      but code like this
      s/.../$1/e
      cannot be dangerous?

        string eval is already flagged as dangerous spot and "use" too

        I missed the mention of string eval. As for the use re 'eval';, it's not prevented by preventing the use of use as I suspect you can achieve the same effect without actually using use.

        The new thing here is substitution with two "e"-s:

        It's really just another way of writing a string eval.

        s/.../.../ee
        is the same as
        s/.../eval "..."/e

        (without making '"' special).

        Do I understand correctly that a single e after the substitution would only be dangerous if the code inside is dangerous

        If you consider $1 safe in code, then s/.../$1/e is safe too.

Re: Is this code secure, can I test it on my machine?
by LanX (Saint) on May 23, 2010 at 08:59 UTC
    You ask about running a CPAN-module, what about the installation process?

    E.g. the automatic tests are in Perl...

    (installations are often enough done as root ...)

    Cheers Rolf

      Actually in this specific case I was only asking about running the code as there is no installation process but for a package that does have installation process, such as a CPAN module, this should be addressed too.
Re: Is this code secure, can I test it on my machine?
by eyepopslikeamosquito (Archbishop) on May 23, 2010 at 22:00 UTC
Re: Is this code secure, can I test it on my machine?
by ikegami (Patriarch) on May 23, 2010 at 19:37 UTC

    For this I need to check for the appearance of use lib and @INC in the code.

    Impossible.

    my $x = 'INC'; unshift @$x, ...;
      Nice. Can you make this work with strict as well?
        use strict; use warnings; use Data::Dumper; sub foo { use constant foo1 => $^H = 0; push @{reverse 'CNI'}, 'hello'; } foo(); print Dumper \@INC;
        Sure:
        no strict 'refs'; unshift @{ 'INC' }, ...;
        Similar,
        unshift @{ $::{INC} }, ...;
        unshift @{ *INC }, ...;

        These might be considered the same as @INC, or maybe not:

        unshift @::INC, ...;
        unshift @main::INC, ...;
Re: Is this code secure, can I test it on my machine?
by Krambambuli (Curate) on May 24, 2010 at 07:20 UTC
    I'm afraid I'll frighten you with this, although it's rather obvious:

    some code is "really secure", translates to "that code does nothing else than what it is supposed to do, ever, in any circumstances".

    Which is the same as telling "that code has no known or unknown bug, present or future".

    errr... You got my point :)

    On the other hand, if you just wish to check that the code doesn't pro-actively spy out it's environment and send out passwords or the like, running it for a while on a virtual machine or in a chrooted environment and setting a Net filter around it to see if there is any suspect network activity is not hard to do.

    Also, on the test machine, you could set up a file checksum app (Tripwire, AIDE, integrit, yafic, ...) that might help in making sure that none of the files in the working environment haven't been altered during the tests.

    Even so, you'll catch just a tiny fraction of the possible gotchas.

    It's like in real life: the better you're looking, the more dangers you'll see.

    (Who would ever drink from the "clean" water at which she'd had a look through a good microscope before that...? :) ).
Re: Is this code secure, can I test it on my machine?
by ambrus (Abbot) on May 23, 2010 at 20:06 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://841237]
Approved by LanX
Front-paged by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (4)
As of 2024-03-29 15:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found