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

I've been working on a script that will send email using the Mail::Mailer module. I've come across a problem that I can't figure out due to my inexperience with Mail::Mailer, and with taint checking in general. First, here's the error message I'm getting:

Insecure $ENV{PATH} while running with -T switch at /usr/local/share/perl/5.8.0/Mail/Mailer/sendmail.pm line 16.

And now a snippet or two from my script:

#!/usr/bin/perl -T use strict; use warnings; use CGI qw( -unique_headers ); use CGI::Carp qw( fatalsToBrowser ); use Mail::Mailer; # Much stuff... ;) sub send_message { my ( $recipient_addr, $sender_name, $sender_email, $subject, $message ) = @_; my $mail = new Mail::Mailer; $mail->open( { To => $recipient_addr, From => $sender_email, Subject => "[Mailer Response] " . $subject } ); print $mail $message; close $mail; }

It is my understanding that Mail::Mailer does not send anything through the shell. For example, if it chooses sendmail as the method of sending an email message, it uses the fork and exec technique to avoid passing arguments through the shell.

I am taking the message itself, the sender's address ("From"), the sender's name, and the subject line pretty much directly from the outside world (a CGI generated form). The recipient's address is hardwired into the script, and therefore, shouldn't be a security issue. The user input is coming in through the $q->param() method of CGI.pm.

The two biggest obstacles I see are (1) untainting a user-supplied 'from' email address, given that almost any ASCII character is permissible within what constitutes a valid address. ...and (2), just about any ASCII character is valid within a message body. Because of these two issues, I chose to use Mail::Mailer because what I've read about it indicates that it avoids the shell, thus passing parameters to the sending-agent safely.

My experience with untainting web-based input is quite limited; it is basically what I've gleaned from the POD for taint mode, and the Mouse book (2nd Edition). But what I've read about Mail::Mailer leads me to believe that though the user-input may not necessarily be valid, it's not getting anywhere near the shell, and thus not a serious security risk. What could I have missed?

So why the taint error? And what can / should I do to safely untaint a user-supplied "from" address (if that's even the issue)? Should I be looking at another module?

Thanks for any suggestions.


Dave


"If I had my life to do over again, I'd be a plumber." -- Albert Einstein

Replies are listed 'Best First'.
Re: Mail::Mailer and difficulty with -T taint mode
by PodMaster (Abbot) on Oct 12, 2003 at 10:47 UTC
    An error message, interesting ... from `perldoc perldiag':
    Insecure $ENV{%s} while running %s

    (F) You can't use system(), exec(), or a piped open in a setuid or setgid script if any of $ENV{PATH}, $ENV{IFS}, $ENV{CDPATH}, $ENV{ENV} or $ENV{BASH_ENV} are derived from data supplied (or potentially supplied) by the user. The script must set the path to a known value, using trustworthy data. See perlsec.

    Does that help?

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      That is helpful, but it seems then, that it is telling me there is NO way to successfully pass a user-supplied From address to Mail::Mailer, if that module uses system, exec, or a piped open. I say this because in untainting an email address supplied by the user, you risk wrecking valid addresses since just about any character may exist within a valid address. I used Mail::Mailer because of its proported feature of avoiding the shell, in the interest of security. I don't believe that Mail::Mailer uses a piped open, as it is the module's goal to keep the message being sent far away from the shell. But the exec one seems a little tricky to get around.

      I could supply a hard-wired From, and then pass the user's supplied From through the body of the message, but even that must pass through Mail::Mailer.

      Surely I am just not seeing the simple solution. ;)


      Dave


      "If I had my life to do over again, I'd be a plumber." -- Albert Einstein

        Some quick tests indicate that if Mail::Mailer really were using exec in a safe way, perl wouldn't care about $ENV{PATH}.

        [sgifford@sghome sgifford]$ perl -T -e"exec('echo', 'OK')" Insecure $ENV{PATH} while running with -T switch at -e line 1. [sgifford@sghome sgifford]$ perl -T -e"exec('/bin/echo OK')" Insecure $ENV{PATH} while running with -T switch at -e line 1. [sgifford@sghome sgifford]$ perl -T -e"exec('/bin/echo', 'OK')" OK

        What mailer are you using with Mail::Mailer, and what version? Can you find the relevant code that you think should be secure but Perl doesn't agree? Why is it a problem to untaint the from address to guarantee that it doesn't contain anything strange?

        but it seems then, that it is telling me there is NO way to successfully pass a user-supplied From address to Mail::Mailer,
        So what you're saying is that you're using taint mode without knowing how it works? All of the values in %ENV are tainted. If you don't know what that means, or how to get around it, read perlsec (it's a link you know).

        MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
        I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
        ** The third rule of perl club is a statement of fact: pod is sexy.

        Mail::Mailer does use a piped open. From my version of Mail::Mailer (in MailTools 1.60) about line 226:

        # Fork and start a mailer (defined($exe) && open($self,"|-")) # (snip)

        I don't know enough about packages to know if this is a potentially harmful open call, but I can understand how the taint checking is complaining about the path.